5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 - 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcutil/Memory Pool Interface
24 * SilcStack is a pre-allocated memory pool system which allows fast memory
25 * allocation for routines and applications that frequently allocate small
26 * amounts of memory. Other advantage of this system is that there are no
27 * memory leaks, as long as the stack is freed eventually. Since the stack
28 * is usually allocated only once this is not an issue.
30 * SilcStack supports stack pushing and popping allowing to push the stack,
31 * allocate memory and then pop it to free the allocated memory. The freeing
32 * does not actually do any real memory freeing so it is optimized for
33 * performance. The memory alignment may also be specified by user for
34 * the stack. This allows the caller to use special alignment for memory
35 * allocations, if needed.
37 * SilcStack is also a full featured memory pool which allows user to group
38 * together multiple stacks. Child stacks may be created from a parent stack
39 * without consuming the parent stack. When the child is freed, its memory
40 * is returned back to the parent and can be used again by other childs.
41 * It is also possible to create child stacks from another child stack.
43 * A basic set of utility functions are provided for application that wish
44 * to use the SilcStack as their primary memory allocation source. The
45 * following functions (among many others) support SilcStack:
47 * silc_smalloc, silc_smalloc, silc_scalloc, silc_srealloc, silc_smemdup,
48 * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
49 * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
50 * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
51 * silc_buffer_sstrformat, silc_buffer_senlarge, silc_dlist_sinit,
52 * silc_hash_table_alloc
54 * The SilcStack is not thread-safe so that same context could be used for
55 * allocations from multiple threads. It is however safe to create and use
56 * child stacks in a different thread from the parent stack. Each thread
57 * should allocate their own SilcStack, however they may be child stacks.
64 /****s* silcutil/SilcStack
68 * typedef struct SilcStackStruct *SilcStack;
72 * This context represents the stack and it is allocated by
73 * silc_stack_alloc and is destroyed with silc_stack_free functions.
74 * The context is given as argument to all routines that use this
75 * stack allocation library.
78 typedef struct SilcStackStruct *SilcStack;
80 /****s* silcutil/SilcStackFrame
84 * typedef struct SilcStackFrameStruct SilcStackFrame;
88 * Static stack frame context that optionally can be used as stack
89 * frame in SilcStack. By default silc_stack_push use pre-allocated
90 * stack frame, but user may also use statically allocated SilcStackFrame
91 * instead. This is recommended when using SilcStack in recursive routine
92 * and the recursion may become deep. Using static frame assures that
93 * during recursion frames never run out.
96 typedef struct SilcStackFrameStruct SilcStackFrame;
98 /****f* silcutil/SilcStackOomHandler
102 * typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
106 * Callback of this type can be given to silc_stack_set_oom_handler
107 * to set Out of Memory handler to `stack'. If memory allocation from
108 * `stack' fails this callback is called to indicate error. The `context'
109 * is the context given to silc_stack_set_oom_handler.
112 typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
114 /****f* silcutil/silc_stack_alloc
118 * SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
122 * Allocates new data stack that can be used as stack for fast memory
123 * allocation by various routines. Returns the pointer to the stack
124 * that must be freed with silc_stack_free function when it is not
125 * needed anymore. If the `stack_size' is zero (0) by default a
126 * 1 kilobyte (1024 bytes) stack is allocated.
128 * If `parent' is non-NULL the created stack is a child of the `parent'
129 * stack. All of childs the memory is allocated from the `parent' and
130 * will be returned back to the parent when the child is freed. Note
131 * that, even though child allocates memory from the parent, the parent's
132 * stack is not consumed.
134 * Returns NULL on error and sets silc_errno.
137 SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
139 /****f* silcutil/silc_stack_free
143 * void silc_stack_free(SilcStack stack);
147 * Frees the data stack context. The stack cannot be used anymore after
148 * this and all allocated memory are freed.
150 * If `stack' is a child stack, its memory is returned back to its
151 * parent. If `stack' is NULL this function does nothing.
154 void silc_stack_free(SilcStack stack);
156 /****f* silcutil/silc_stack_push
160 * SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
164 * Push the top of the stack and add new stack frame on top of the stack.
165 * For every silc_stack_push call there must be silc_stack_pop call. All
166 * allocations between these two calls will be done from the top of the
167 * stack and all allocated memory is freed after the next silc_stack_pop
168 * is called. This returns so called stack pointer for the new stack
169 * frame, which the caller may use to check that all calls to
170 * silc_stack_pop has been made.
172 * If the `frame' is non-NULL then that SilcStackFrame is used as
173 * stack frame. Usually `frame' is set to NULL by user. Statically
174 * allocated SilcStackFrame should be used when using silc_stack_push
175 * in recursive function and the recursion may become deep. In this
176 * case using statically allocated SilcStackFrame is recommended since
177 * it assures that frames never run out. If your routine is not recursive
178 * then setting `frame' to NULL is recommended.
180 * This function is used when a routine is doing frequent allocations
181 * from the stack. If the stack is not pushed and later popped all
182 * allocations are made from the stack and the stack eventually runs out
183 * (it gets enlarged by normal memory allocation). By pushing and then
184 * later popping the frequent allocations does not consume the stack.
186 * If `stack' is NULL this call has no effect. This function does not
187 * allocate any memory.
191 * All memory allocations in silc_foo_parse_packet will be done in
192 * a fresh stack frame and that data is freed after the parsing is
195 * silc_stack_push(stack, NULL);
196 * silc_foo_parse_packet(packet, stack);
197 * silc_stack_pop(stack);
199 * Another example with recursion and using statically allocated
200 * SilcStackFrame. After popping the statically allocated frame can
201 * be reused if necessary.
203 * void silc_foo_this_function(SilcStack stack)
205 * SilcStackFrame frame;
207 * silc_stack_push(stack, &frame);
208 * silc_foo_this_function(stack); // Call recursively
209 * silc_stack_pop(stack);
214 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
216 /****f* silcutil/silc_stack_pop
220 * SilcUInt32 silc_stack_pop(SilcStack stack);
224 * Pop the top of the stack to remove the previous stack frame and use
225 * previous frame as top of the stack. After popping, memory allocated in
226 * the old frame is freed. For each silc_stack_push call there must be
227 * silc_stack_pop call to free all memory (in reality any memory is not
228 * freed but within the stack it is). This returns the stack pointer of
229 * old frame after popping and caller may check that it is same as
230 * returned by the silc_stack_push. If it they differ, some routine
231 * has called silc_stack_push but has not called silc_stack_pop, or
232 * silc_stack_pop has been called too many times. Application should
233 * treat this as a fatal error, as it is a bug in the application code.
235 * If `stack' is NULL this call has no effect. This function does not
236 * allocate any memory.
240 * This example saves the stack pointer which is checked when popping
241 * the current stack frame. If the stack pointer differs then someone
242 * has pushed the stack frame but forgot to pop it (or has called it
245 * sp = silc_stack_push(stack, NULL);
246 * silc_foo_parse_packet(packet, stack);
247 * if (silc_stack_pop(stack) != sp)
248 * fatal("corrupted stack");
251 SilcUInt32 silc_stack_pop(SilcStack stack);
253 /****f* silcutil/silc_stack_malloc
257 * void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
261 * Low level memory allocation routine. Allocates memory block of size of
262 * `size' from the `stack'. The allocated memory is aligned so it can be
263 * used to allocate memory for structures, for example. Returns the
264 * allocated memory address or NULL if memory could not be allocated from
269 * This function should be used only if low level memory allocation with
270 * SilcStack is needed. Instead, silc_smalloc and silc_scalloc could
274 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
276 /****f* silcutil/silc_stack_realloc
280 * void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
281 * void *ptr, SilcUInt32 size);
285 * Attempts to reallocate memory by changing the size of the `ptr' into
286 * `size'. This routine works only if the previous allocation to `stack'
287 * was `ptr'. If there is another memory allocation between allocating
288 * `ptr' and this call this routine will return NULL (and silc_errno is
289 * set to SILC_ERR_INVALID_ARGUMENT). NULL is also returned if the `size'
290 * does not fit into the current stack block. If NULL is returned the old
291 * memory remains intact.
295 * This function should be used only if low level memory allocation with
296 * SilcStack is needed. Instead, silc_srealloc could be used which can
297 * handle failed reallocation by allocating new block.
300 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
301 void *ptr, SilcUInt32 size);
303 /****f* silcutil/silc_stack_set_oom_handler
307 * void silc_stack_set_oom_handler(SilcStack stack,
308 * SilcStackOomHandler oom_handler,
313 * Sets Out of Memory handler `oom_handler' to `stack' to be called
314 * if memory allocation from `stack' fails. The `context' is delivered
317 * Usually Out of Memory handler is set only when failed memory allocation
318 * is a fatal error. In this case the application would abort() inside
319 * the `oom_handler'. It may also be set if in case of failed allocation
320 * application wants to do clean up properly.
323 void silc_stack_set_oom_handler(SilcStack stack,
324 SilcStackOomHandler oom_handler,
327 /****f* silcutil/silc_stack_set_alignment
331 * void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
335 * Sets/changes the memory alignment in the `stack' to `alignment' which
336 * is the alignment in bytes. By default, the SilcStack will use alignment
337 * suited for the platform where it is used. This function can be used
338 * to change this alignment, if such change is needed. You may check the
339 * current alignment by calling silc_stack_get_alignment.
343 * It is not mandatory to call this function. By default the SilcStack
344 * will always use alignment suited for the used platform. This function
345 * should be called only if the alignment needs to be changed to something
346 * other than the default on the used platform. For example, some
347 * hardware device, such as crypto accelerator, may require special
351 void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
353 /****f* silcutil/silc_stack_get_alignment
357 * SilcUInt32 silc_stack_get_alignment(SilcStack stack);
361 * Returns the memory alignment used with `stack'. The alignment is in
365 SilcUInt32 silc_stack_get_alignment(SilcStack stack);
367 /****f* silcutil/silc_stack_purge
371 * SilcBool silc_stack_purge(SilcStack stack);
375 * Purges the `stack' from extra unused memory. This purges only `stack'
376 * and not its parent if `stack' is a child. This purges only large
377 * allocations. The 1024, 2048, 4096 and 8192 bytes of allocations remain.
378 * Call this multiple times to purge even more. Returns FALSE when there
379 * is no more to purge. This does not purge memory blocks that currently
380 * have allocations. No memory allocations from the stack are lost, so
381 * this is always safe to call.
384 SilcBool silc_stack_purge(SilcStack stack);
386 /****f* silcutil/silc_stack_set_global
390 * void silc_stack_set_global(SilcStack stack);
394 * Sets global SilcStack `stack' that can be retrieved at any time
395 * by using silc_stack_get_global. The global stack is global only
396 * to the current thread. Each thread can have their own global stack.
397 * If each thread must have own stack this must be called in each
398 * thread. If the global stack has been set already, new call will
399 * replace the old one.
401 * This routine is provided only as a convenience function to store
402 * program's or thread's stack in one global place. It is not mandatory
403 * to call this function in order to use SilcStack.
406 void silc_stack_set_global(SilcStack stack);
408 /****f* silcutil/silc_stack_get_global
412 * SilcStack silc_stack_get_global(void);
416 * Returns the thread's global stack that was set by calling the
417 * silc_stack_set_global or NULL if global stack has not been set.
420 SilcStack silc_stack_get_global(void);
422 #include "silcstack_i.h"
424 #endif /* SILCSTACK_H */