-
Notifications
You must be signed in to change notification settings - Fork 12
/
smalloc.3.txt
329 lines (238 loc) · 19.2 KB
/
smalloc.3.txt
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
SMALLOC(3) Library Functions Manual SMALLOC(3)
NNAAMMEE
ssmmaalllloocc : sm_malloc, sm_zalloc, sm_free, sm_realloc, sm_realloc_move,
sm_calloc, sm_szalloc - allocate, manage, resize, query size and free
dynamic memory which is allocated from user pointed static memory area;
sm_alloc_valid - query object validity;
sm_malloc_stats - get attached pool statistics;
sm_set_default_pool, sm_release_default_pool - attach and release pool;
sm_set_ub_handler - set global ssmmaalllloocc undefined behavior handler.
SSYYNNOOPPSSIISS
##iinncclluuddee <<eerrrrnnoo..hh>>
##iinncclluuddee <<ssmmaalllloocc..hh>>
vvooiidd **ssmm__mmaalllloocc(_s_i_z_e___t _n);
vvooiidd **ssmm__zzaalllloocc(_s_i_z_e___t _n);
vvooiidd ssmm__ffrreeee(_v_o_i_d _*_p);
vvooiidd **ssmm__rreeaalllloocc(_v_o_i_d _*_p, _s_i_z_e___t _n);
vvooiidd **ssmm__rreeaalllloocc__mmoovvee(_v_o_i_d _*_p, _s_i_z_e___t _n);
vvooiidd **ssmm__ccaalllloocc(_s_i_z_e___t _y, _s_i_z_e___t _x);
ssiizzee__tt ssmm__sszzaalllloocc(_v_o_i_d _*_p);
iinntt ssmm__aalllloocc__vvaalliidd(_v_o_i_d _*_p);
iinntt ssmm__mmaalllloocc__ssttaattss(_s_i_z_e___t _*_t_o_t_a_l, _s_i_z_e___t _*_u_s_e_r, _s_i_z_e___t _*_f_r_e_e,
_i_n_t _*_n_r___o_b_j);
iinntt ssmm__sseett__ddeeffaauulltt__ppooooll(_v_o_i_d _*_p_o_o_l, _s_i_z_e___t _p_o_o_l___s_i_z_e, _i_n_t _d_o___z_e_r_o,
_s_m_a_l_l_o_c___o_o_m___h_a_n_d_l_e_r _o_o_m___h_a_n_d_l_e_r___f_n);
iinntt ssmm__rreelleeaassee__ddeeffaauulltt__ppooooll(_v_o_i_d);
vvooiidd ssmm__sseett__uubb__hhaannddlleerr(_s_m_a_l_l_o_c___u_b___h_a_n_d_l_e_r _u_b___h_a_n_d_l_e_r);
DDEESSCCRRIIPPTTIIOONN
ssmmaalllloocc is a portable and simple memory management package which is
intended to be used especially with user provided memory regions. It is
like a normal malloc(3) provided by any modern system today (and you
should expect conventional behavior), but it extends it by allowing the
user to specify memory area, _a _c_u_s_t_o_m _h_e_a_p, in which all the allocations
will be stored.
ssmm__mmaalllloocc,, ssmm__zzaalllloocc,, ssmm__ccaalllloocc allocate memory. ssmm__zzaalllloocc and ssmm__ccaalllloocc
guarantee zero-fill of newly created object. ssmm__mmaalllloocc may return object
containing garbage (usually, if pool is static storage, it contains
zeroes after program start, but after extensive usage it will contain
garbage).
ssmm__rreeaalllloocc change already allocated object size, but also can be used to
allocate and free memory too.
ssmm__rreeaalllloocc__mmoovvee works like ssmm__rreeaalllloocc, but fails if physical reallocation
(move) of the object is required.
ssmm__ffrreeee deallocates ssmmaalllloocc allocated memory.
ssmm__sszzaalllloocc queries a _v_a_l_i_d ssmmaalllloocc memory block size.
ssmm__aalllloocc__vvaalliidd tests if a pointer belongs to valid ssmmaalllloocc object within
the pool.
ssmm__mmaalllloocc__ssttaattss accept four pointers to numbers where it stores current
pool state: _*_t_o_t_a_l accepts total used bytes in pool: user data with any
overhead added by ssmmaalllloocc, _*_u_s_e_r accepts total user bytes with any user
overhead, _*_f_r_e_e accepts total free bytes still available, and _*_n_r___o_b_j
accepts number of already allocated objects within the pool.
ssmm__sseett__ddeeffaauulltt__ppooooll takes _*_p_o_o_l pool of _p_o_o_l___s_i_z_e size and registers it
as a global default pool. Nonzero _d_o___z_e_r_o instructs ssmmaalllloocc to zero-fill
pool before use, _a_n_d _a_l_s_o _z_e_r_o _a_n_y _n_e_w_l_y _a_l_l_o_c_a_t_e_d _o_b_j_e_c_t_s _b_e_f_o_r_e
_r_e_t_u_r_n_i_n_g _t_h_e_m_, _a_n_d _z_e_r_o _a_n_y _t_o _b_e _f_r_e_e_d _o_b_j_e_c_t_s _u_p_o_n _t_o _r_e_t_u_r_n_i_n_g _t_h_e_m
_b_a_c_k _t_o _t_h_e _p_o_o_l_. If _d_o___z_e_r_o is 0, then only ssmm__zzaalllloocc and ssmm__ccaalllloocc
zero-fill object before returning them to caller, but ssmm__mmaalllloocc will
return object possibly containing garbage. _o_o_m___h_a_n_d_l_e_r___f_n can be either
_N_U_L_L or a pointer to OOM handler function (see _E_R_R_O_R _H_A_N_D_L_E_R_S for a
description). In case of _N_U_L_L, no OOM handler is called at all on an OOM
condition.
ssmm__rreelleeaassee__ddeeffaauulltt__ppooooll deregisters current pool and zero-fills it
(erases) if _d_o___z_e_r_o argument to ssmm__sseett__ddeeffaauulltt__ppooooll was nonzero. All
further calls to any allocation or freeing functions will fail without
registered pool.
ssmm__sseett__uubb__hhaannddlleerr sets global undefined behavior handler. It's
description is given in _E_R_R_O_R _H_A_N_D_L_E_R_S section. If _N_U_L_L is passed as
_u_b___h_a_n_d_l_e_r, then internal UB handler is reset to ssmmaalllloocc default one:
crashing the program.
RREETTUURRNN VVAALLUUEE
ssmm__mmaalllloocc,, ssmm__zzaalllloocc,, ssmm__ccaalllloocc return a pointer to newly created object
on success. The data it poins to can be used only up to _n argument passed
to them (or _y _* _x in case of ssmm__ccaalllloocc) If _n is 0, these functions return
a pointer to newly created object _w_h_i_c_h _c_o_n_t_e_n_t _s_h_o_u_l_d _b_e _n_e_v_e_r _a_c_c_e_s_s_e_d.
They return _N_U_L_L on failure to allocate memory and set _e_r_r_n_o to _E_N_O_M_E_M.
ssmm__rreeaalllloocc returns a pointer to object which size was adjusted. _T_h_e
_o_b_j_e_c_t _a_d_d_r_e_s_s _m_a_y _d_i_f_f_e_r _f_r_o_m _p_a_s_s_e_d _i_n _a_d_d_r_e_s_s. If _p is _N_U_L_L, then the
call is equivalent to ssmm__mmaalllloocc(_n). If _p is a pointer to existing object
and _n is 0, then the call is equivalent to ssmm__ffrreeee(_p). On failure to
relocate or size change, it will return _N_U_L_L and set _e_r_r_n_o to _E_N_O_M_E_M.
ssmm__rreeaalllloocc__mmoovvee works exactly as ssmm__rreeaalllloocc, but fails if physical
reallocation (move) of the object is required. In such case, _N_U_L_L is
returned and _e_r_r_n_o is set to _E_R_A_N_G_E. Original object of question is not
touched, it's size is not changed and it can be used as before.
ssmm__ffrreeee does not return a value, but may change _e_r_r_n_o in cases described
in _N_O_T_E_S section.
ssmm__sszzaalllloocc return an exact object size of object pointed to by _p (the
argument _n passed to any of: ssmm__mmaalllloocc,, ssmm__zzaalllloocc,, ssmm__rreeaalllloocc,,
ssmm__rreeaalllloocc__mmoovvee and _y _* _x result of ssmm__ccaalllloocc) _T_h_i_s _i_s _t_h_e _o_n_l_y _p_e_r_m_i_t_t_e_d
_a_r_e_a _t_h_a_t _t_h_e _c_a_l_l_e_r _m_a_y _u_s_e_. For _N_U_L_L as argument, ssmm__sszzaalllloocc returns 0.
For unique object of 0 size created with ssmm__mmaalllloocc(_0) (or equivalent),
the return value is 1, _b_u_t _t_h_i_s _m_a_y _b_e _c_h_a_n_g_e_d _i_n _f_u_t_u_r_e.
ssmm__aalllloocc__vvaalliidd returns 1 if object pointed to by _p is valid reference, 0
otherwise. It does not permit to differentiate between multiple pools.
ssmm__mmaalllloocc__ssttaattss return 1 when the pool contains at least one object, thus
numbers stored are not zeroes, 0 if no objects are in pool or _a_l_l
_a_r_g_u_m_e_n_t_s _a_r_e _N_U_L_L_s, or -1 on any other error described in _N_O_T_E_S section.
ssmm__sseett__ddeeffaauulltt__ppooooll returns 1 on success (pool was registered), 0 if pool
is very small to use. In this situation, an _e_r_r_n_o will be also set to
_E_N_O_S_P_C.
ssmm__rreelleeaassee__ddeeffaauulltt__ppooooll returns 1 on success (an existing pool was
successfully deregistered), 0 otherwise, with _e_r_r_n_o set to _E_I_N_V_A_L.
ssmm__sseett__uubb__hhaannddlleerr always succeeds and does not return any value.
NNOOTTEESS
If pool was never registered, or recently was deregistered with
ssmm__rreelleeaassee__ddeeffaauulltt__ppooooll, then all memory management functions will fail
by returning their error values: _N_U_L_L or _0 or _-_1 or _(_s_i_z_e___t_)_-_1, or _(_v_o_i_d_)
and _e_r_r_n_o will be set to _E_I_N_V_A_L.
All functions working on existing objects which take pointers to them,
except ssmm__aalllloocc__vvaalliidd, will check the pointer to be a valid reference to
existing object belonging to registered pool. If an invalid pointer is
catched, then ssmmaalllloocc calls an _u_n_d_e_f_i_n_e_d _b_e_h_a_v_i_o_r handler. The default
ssmmaalllloocc embedded UB handler is set to crash the program to bring
programmer's attention as early as possible. This handler can be
overriden with ssmm__sseett__uubb__hhaannddlleerr for a lifetime of program until next
call to this function. ssmm__aalllloocc__vvaalliidd does not call UB handler in case
of invalid pointer reference: it was specially designed to answer the
question: "Is this pointer a valid object reference?"
One can implement a classic but more precise malloc on top of ssmmaalllloocc by
using brk(2) as a custom heap and extending it on each OOM handler call.
EERRRROORR HHAANNDDLLEERRSS
ssmmaalllloocc__oooomm__hhaannddlleerr Out Of Memory handler is defined as follows:
typedef size_t (*smalloc_oom_handler)(struct smalloc_pool *, size_t);
size_t oom_handler(struct smalloc_pool *spool, size_t failed_alloc_req);
It takes a pool descriptor _*_s_p_o_o_l (see _M_U_L_T_I_P_L_E _P_O_O_L_S section) and
_f_a_i_l_e_d___a_l_l_o_c___r_e_q, which is size of object that failed to be created (the
_n argument to allocation functions). The task of OOM handler is either
to report an abnormal condition, possibly (and often) with program
abortion or other way to exit, or to extend the pool, if possible (if
pool is static, but resizeable). In case of refuse to extend, but
without abortion, the handler must return 0. Otherwise handler must
return a _n_e_w _s_i_z_e _o_f _p_o_o_l _a_f_t_e_r _s_u_c_c_e_s_s_f_u_l _e_x_t_e_n_s_i_o_n.
_I_M_P_O_R_T_A_N_T_! _T_h_e _p_o_o_l _C_A_N_N_O_T _B_E _R_E_L_O_C_A_T_E_D _I_F _I_T _C_O_N_T_A_I_N_S _A_L_L_O_C_A_T_E_D _O_B_J_E_C_T_S
with functions such as realloc(3). Relocation of pool will lead to bad
references to the objects stored inside pointers across your program! You
must ensure that pool will never be relocated once used when resizing the
pool. Returning a size lesser than current pool size will not lead to
extension of pool, the effect will be the same as if handler would return
0. Returned size may or may not be not aligned: the function will align
the new size automatically.
ssmmaalllloocc__uubb__hhaannddlleerr Undefined Behavior handler is defined as follows:
typedef void (*smalloc_ub_handler)(struct smalloc_pool *, const void *);
void ub_handler(struct smalloc_pool *spool, const void *offender);
It takes a pool descriptor _*_s_p_o_o_l (see _M_U_L_T_I_P_L_E _P_O_O_L_S section) and
_*_o_f_f_e_n_d_e_r pointer which is an exact pointer value that caused an UB
exception. The task of UB handler is to report the condition as fast as
possible and abort the program. An UB handler can _i_g_n_o_r_e abnormal
condition, but it is highly discouraged. Default UB handler embedded
into ssmmaalllloocc itself is to cause program crash by writing to NULL pointer.
It does not report condition somewhere just not to depend on libc's stdio
package (or something other, possibly platform specific).
MMUULLTTIIPPLLEE PPOOOOLLSS
ssmmaalllloocc supports using multiple pools in parallel (but not in
multithreaded environment however). There are versions of described
functions above which names end with `_pool' suffix and have prepended
their first argument as _s_t_r_u_c_t _s_m_a_l_l_o_c___p_o_o_l _*, which is a pool descriptor
of this format:
struct smalloc_pool {
void *pool;
size_t pool_size;
int do_zero;
smalloc_oom_handler oomfn;
};
Manual fill of the structure is _N_O_T _R_E_C_O_M_M_E_N_D_E_D, it is best to use a pool
aware ssmm__sseett__ppooooll function, which is just the ssmm__sseett__ddeeffaauulltt__ppooooll variant
with _s_t_r_u_c_t _s_m_a_l_l_o_c___p_o_o_l _* as it's first argument.
Releasing such a pool is done with ssmm__rreelleeaassee__ppooooll, which takes _s_t_r_u_c_t
_s_m_a_l_l_o_c___p_o_o_l _* as it's only single argument.
Memory behind these descriptors is not allocated by ssmmaalllloocc, it is task
of the caller to store pool descriptors somewhere.
Then caller may turn normal functions into pool versions, for example:
ssmm__rreeaalllloocc(_v_o_i_d _*_p, _s_i_z_e___t _n) turns into ssmm__rreeaalllloocc__ppooooll(_s_t_r_u_c_t
_s_m_a_l_l_o_c___p_o_o_l _*_s_p_o_o_l, _v_o_i_d _*_p, _s_i_z_e___t _n), and so on.
There is a ssmm__aalliiggnn__ppooooll function, which takes a pool descriptor and
adjusts it's _p_o_o_l___s_i_z_e member to a value best fit for a ssmmaalllloocc. This
function is provided only for manual fill of the pool descriptor.
_U_n_a_l_i_g_n_e_d _p_o_o_l _d_e_s_c_r_i_p_t_o_r_s _w_i_l_l _b_e _r_e_j_e_c_t_e_d by ssmmaalllloocc and _e_r_r_n_o will be
set to _E_I_N_V_A_L in such cases.
ssmmaalllloocc__ccuurrrr__ppooooll symbol points to global pool descriptor which is used
by ssmm__sseett__ddeeffaauulltt__ppooooll and ssmm__rreelleeaassee__ddeeffaauulltt__ppooooll, as well as by
`non-pool' functions.
FFIILLEESS
See _s_m_a_l_l_o_c_._h, _s_m_a_l_l_o_c___t_e_s_t___s_o_._c, and source code.
EEXXAAMMPPLLEE
This is the minimal example of how to use the library:
#include <smalloc.h>
static char my_pool[16384];
int main(void)
{
char *s, *d;
size_t n;
if (!sm_set_default_pool(my_pool, sizeof(my_pool), 0, NULL)) return 1;
s = sm_malloc(40);
if (s) {
n = sm_szalloc(s);
memset(s, 'X', n);
}
d = sm_malloc(700);
if (d) memset(d, 'Y', sm_szalloc(d));
s = sm_realloc(s, n+30);
if (s) memset(s+n, 'x', sm_szalloc(s)-n);
d = sm_realloc(d, 14000);
if (d) memset(d, 'y', sm_szalloc(d));
sm_free(s);
sm_free(d);
sm_release_default_pool();
return 0;
}
BBUUGGSS
Returned objects may or may not be aligned to be used for any kind of
variable. However it places objects exactly so at least integers and
pointers can be placed and used without harm within them.
Allocations lesser than 12 bytes on 32 bit systems (typ.) are not so
efficient: the object header takes 12 bytes and minimum overhead size is
also 12 bytes. So per each, for example, 4 byte request there will be a
20 byte of overhead. On 64 bit systems it's even worse, things usually
double.
True multithreading with locking was not implemented and is not currently
a planned task.
Unlike highly promoted Linux's behavior about always succeeding mmaalllloocc,
the memory in ssmmaalllloocc is managed directly by programmer.
CCOONNFFOORRMMIINNGG TTOO
ssmm__mmaalllloocc,, ssmm__ccaalllloocc,, ssmm__rreeaalllloocc and ssmm__ffrreeee are fully compatible with
usual mmaalllloocc,, ccaalllloocc,, rreeaalllloocc and ffrreeee. Their behavior on normal/failed
situations is same (or should be same - report a bug if not). Programmer
should not bother about UB because good program does not invoke UB.
ssmm__zzaalllloocc,, ssmm__sszzaalllloocc,, ssmm__rreeaalllloocc__mmoovvee and ssmm__aalllloocc__vvaalliidd are ssmmaalllloocc
extensions. They're not implemented in other malloc type packages, thus
their usage is not portable.
AAUUTTHHOORRSS
ssmmaalllloocc was written in spare time by Andrey Rys <_r_y_s_@_l_y_n_x_l_y_n_x_._r_u> This
library is available at hhttttppss::////ggiitthhuubb..ccoomm//eelleeccttrroorryyss//ssmmaalllloocc//.
The code, unlike any other programs written by Rys is MIT licensed:
_C_o_p_y_r_i_g_h_t _(_c_) _2_0_1_7 _A_n_d_r_e_y _R_y_s _<_r_y_s_@_l_y_n_x_l_y_n_x_._r_u_>. See _C_O_P_Y_R_I_G_H_T file in
the source distribution for complete terms.
SSEEEE AALLSSOO
malloc(3), calloc(3), free(3), realloc(3).
R2 19Aug2017 R2