-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemLock.h
More file actions
165 lines (138 loc) · 5.2 KB
/
MemLock.h
File metadata and controls
165 lines (138 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* Copyright (C) 2020-2025 Stuart Calder
* See accompanying LICENSE file for licensing information. */
/* The environment must externally define SSC_EXTERN_MEMLOCK to enable
* this header. */
#if !defined(SSC_MEMLOCK_H) && defined(SSC_EXTERN_MEMLOCK)
#define SSC_MEMLOCK_H
#ifdef SSC_EXTERN_MEMLOCK_THREADSAFE
#include <pthread.h>
#endif
#include "Macro.h"
#include "Error.h"
#define R_ SSC_RESTRICT
SSC_BEGIN_C_DECLS
typedef struct {
uint64_t page_size; /* The size of virtual memory pages, in bytes. */
uint64_t limit; /* The memory locking limit, in bytes. */
uint64_t n; /* The number of locked bytes. */
#ifdef SSC_EXTERN_MEMLOCK_THREADSAFE
pthread_mutex_t n_mtx; /* Mutex limiting access to @n. */
#endif
} SSC_MemLock;
#define SSC_MEMLOCK_NULL_LITERAL SSC_STRUCT_LITERAL(SSC_MemLock, 0)
SSC_API extern SSC_MemLock SSC_MemLock_Global; /* Global SSC_MemLock structure. */
enum {
SSC_MEMLOCK_ERR_LOCK_OP = -1,
SSC_MEMLOCK_ERR_MTX_OP = -2,
SSC_MEMLOCK_ERR_MTX_INIT = -3,
SSC_MEMLOCK_ERR_OVER_MEMLIMIT = -4,
SSC_MEMLOCK_ERR_UNDER_MEMMIN = -5,
SSC_MEMLOCK_ERR_GET_LIMIT = -6,
SSC_MEMLOCK_ERR_SET_LIMIT = -7,
SSC_MEMLOCK_ERR_UNINITIALIZED = -8
};
typedef enum {
SSC_MEMLOCKFLAG_GRACEFUL_OVERMEMLIMIT_FAIL = 0x01,
SSC_MEMLOCKFLAG_GRACEFUL_LOCK_FAIL = 0x02,
SSC_MEMLOCKFLAG_GRACEFUL_UNLOCK_FAIL = 0x02
} SSC_MemLockFlag_t;
#ifdef SSC_OS_UNIXLIKE
/* SSC_MEMLOCK_ERR_SET_LIMIT is only returned on Unixlike systems. */
#define SSC_MEMLOCK_INIT_MAYRETURN_ERR_SET_LIMIT 1
#else
#define SSC_MEMLOCK_INIT_MAYRETURN_ERR_SET_LIMIT 0
#endif
#ifdef SSC_EXTERN_MEMLOCK_THREADSAFE
/* SSC_MEMLOCK_ERR_MTX_INIT is only returned when thread safety is enabled. */
#define SSC_MEMLOCK_INIT_MAYRETURN_ERR_MTX_INIT 1
#else
#define SSC_MEMLOCK_INIT_MAYRETURN_ERR_MTX_INIT 0
#endif
/* Initialize a SSC_MemLock struct at @ml.
* This must be called on a SSC_MemLock before using it in
* the other procedures. */
SSC_API SSC_Error_t
SSC_MemLock_init(SSC_MemLock* ml);
/* Initialize, if not already initialized. */
SSC_INLINE SSC_Error_t
SSC_MemLock_Global_init(void)
{
if (!SSC_MemLock_Global.page_size)
return SSC_MemLock_init(&SSC_MemLock_Global);
return 0;
}
/* Initialize @ctx. Die on failure. */
SSC_API void SSC_MemLock_initHandled(SSC_MemLock* ctx);
/* Initialize the global variable SSC_MemLock_Global, the default
* memory locking structure when none is specified.
* Die on failure. */
SSC_INLINE void SSC_MemLock_Global_initHandled(void)
{
if (!SSC_MemLock_Global.page_size)
SSC_MemLock_initHandled(&SSC_MemLock_Global);
}
/* Attempt to lock the memory @p with requested number of bytes @n, with the
* MemoryLock struct pointer @ctx. */
SSC_API SSC_Error_t
SSC_MemLock_lockContext(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx);
/* Lock the memory @p with number bytes @n using the default global context. */
SSC_INLINE SSC_Error_t
SSC_MemLock_lock(void* R_ p, uint64_t n)
{
return SSC_MemLock_lockContext(p, n, &SSC_MemLock_Global);
}
/* Lock the memory @p with number bytes @n using context
* @ctx with the handle flags @f. */
SSC_API void
SSC_MemLock_lockContextHandled(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx, SSC_MemLockFlag_t f);
/* Lock the memory @p with number bytes @n using context @ctx. */
SSC_INLINE void
SSC_MemLock_lockContextOrDie(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx)
{
SSC_MemLock_lockContextHandled(p, n, ctx, 0);
}
/* Lock the memory @p with number bytes @n using the default global context, with a handle flag of @f. */
SSC_INLINE void
SSC_MemLock_lockHandled(void* R_ p, uint64_t n, SSC_MemLockFlag_t f)
{
SSC_MemLock_lockContextHandled(p, n, &SSC_MemLock_Global, f);
}
/* Lock the memory @p with number bytes @n using the default global context. */
SSC_INLINE void
SSC_MemLock_lockOrDie(void* R_ p, uint64_t n)
{
SSC_MemLock_lockHandled(p, n, 0);
}
/* Unlock the memory @p with number bytes @n using the context @ctx. */
SSC_API SSC_Error_t
SSC_MemLock_unlockContext(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx);
/* Unlock the memory @p with number bytes @n using the default global context. */
SSC_INLINE SSC_Error_t SSC_MemLock_unlock(void* R_ p, uint64_t n)
{
return SSC_MemLock_unlockContext(p, n, &SSC_MemLock_Global);
}
/* Unlock the memory @p with number bytes @n using the context @ctx, with a handle flag of @f. */
SSC_API void
SSC_MemLock_unlockContextHandled(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx, SSC_MemLockFlag_t f);
/* Unlock the memory @p with number bytes @n using the context @ctx, with a handle flag of 0. */
SSC_INLINE void
SSC_MemLock_unlockContextOrDie(void* R_ p, uint64_t n, SSC_MemLock* R_ ctx)
{
SSC_MemLock_unlockContextHandled(p, n, ctx, 0);
}
/* Unlock the memory @p with number bytes @n using the default global context, with a handle flag of @f. */
SSC_INLINE void
SSC_MemLock_unlockHandled(void* R_ p, uint64_t n, SSC_MemLockFlag_t f)
{
SSC_MemLock_unlockContextHandled(p, n, &SSC_MemLock_Global, f);
}
/* Unlock the memory @p with number bytes @n using the
* default global context, with a handle flag of 0. */
SSC_INLINE void
SSC_MemLock_unlockOrDie(void* R_ p, uint64_t n)
{
SSC_MemLock_unlockHandled(p, n, 0);
}
SSC_END_C_DECLS
#undef R_
#endif /* ~ if !defined(SSC_MEMLOCK_H) && defined(SSC_EXTERN_MEMLOCK) */