5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 - 2007 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/SilcStack Interface
24 * Implementation of data stack which can be used to allocate memory from
25 * the stack. Basically SilcStack is a pre-allocated memory pool system
26 * which allows fast memory allocation for routines and applications that
27 * frequently allocate small amounts of memory. Other advantage of this
28 * system is that there are no memory leaks, as long as the stack is
29 * freed eventually. Since the stack is usually allocated only once this
32 * SilcStack supports stack pushing and popping allowing to push the stack,
33 * allocate memory and then pop it to free the allocated memory. The freeing
34 * does not actually do any real memory freeing so it is optimized for
35 * performance. The memory alignment may also be specified by user for
36 * the stack. This allows the caller to use special alignment for memory
37 * allocations, if needed.
39 * A basic set of utility functions are provided for application that wish
40 * to use the SilcStack as their primary memory allocation source. The
41 * following functions support SilcStack:
43 * silc_smalloc, silc_smalloc, silc_scalloc, silc_srealloc, silc_smemdup,
44 * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
45 * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
46 * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
47 * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit
49 * The SilcStack context is not thread-safe. If the same SilcStack must be
50 * used in multithreaded environment concurrency control must be employed.
51 * Each thread should allocate their own SilcStack.
58 /****s* silcutil/SilcStackAPI/SilcStack
62 * typedef struct SilcStackStruct *SilcStack;
66 * This context represents the stack and it is allocated by
67 * silc_stack_alloc and is destroyed with silc_stack_free functions.
68 * The context is given as argument to all routines that use this
69 * stack allocation library.
72 typedef struct SilcStackStruct *SilcStack;
74 /****s* silcutil/SilcStackAPI/SilcStackFrame
78 * typedef struct SilcStackFrameStruct SilcStackFrame;
82 * Static stack frame context that optionally can be used as stack
83 * frame in SilcStack. By default silc_stack_push use pre-allocated
84 * stack frame (or allocates new one if all frames are reserved), but
85 * user may also use statically allocated SilcStackFrame instead. This
86 * is recommended when using SilcStack in recursive routine and the
87 * recursion may become deep. Using static frame assures that during
88 * recursion frames never run out and silc_stack_push never allocates
89 * any memory. In other normal usage statically allocated SilcStackFrame
90 * is not needed, unless performance is critical.
93 typedef struct SilcStackFrameStruct SilcStackFrame;
95 /****f* silcutil/SilcStackAPI/silc_stack_alloc
99 * SilcStack silc_stack_alloc(SilcUInt32 stack_size);
103 * Allocates new data stack that can be used as stack for fast memory
104 * allocation by various routines. Returns the pointer to the stack
105 * that must be freed with silc_stack_free function when it is not
106 * needed anymore. If the `stack_size' is zero (0) by default a
107 * 1 kilobyte (1024 bytes) stack is allocated. If the `stack_size'
108 * is non-zero the byte value must be multiple by 8.
111 SilcStack silc_stack_alloc(SilcUInt32 stack_size);
113 /****f* silcutil/SilcStackAPI/silc_stack_free
117 * void silc_stack_free(SilcStack stack);
121 * Frees the data stack context. The stack cannot be used anymore after
122 * this and all allocated memory are freed.
125 void silc_stack_free(SilcStack stack);
127 /****f* silcutil/SilcStackAPI/silc_stack_push
131 * SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
135 * Push the top of the stack down which becomes the new top of the stack.
136 * For every silc_stack_push call there must be silc_stack_pop call. All
137 * allocations between these two calls will be done from the top of the
138 * stack and all allocated memory is freed after the next silc_stack_pop
139 * is called. This returns so called stack pointer for the new stack
140 * frame, which the caller may use to check that all calls to
141 * silc_stack_pop has been made. This call may do a small memory
142 * allocation in some cases, but usually it does not allocate any memory.
143 * If this returns zero (0) the system is out of memory.
145 * If the `frame' is non-NULL then that SilcStackFrame is used as
146 * stack frame. Usually `frame' is set to NULL by user. Statically
147 * allocated SilcStackFrame should be used when using silc_stack_push
148 * in recursive function and the recursion may become deep. In this
149 * case using statically allocated SilcStackFrame is recommended since
150 * it assures that frames never run out and silc_stack_push never
151 * allocates any memory. If your routine is not recursive then
152 * setting `frame' to NULL is recommended, unless performance is
155 * This function is used when a routine is doing frequent allocations
156 * from the stack. If the stack is not pushed and later popped all
157 * allocations are made from the stack and the stack eventually runs out
158 * (it gets enlarged by normal memory allocation). By pushing and then
159 * later popping the frequent allocations does not consume the stack.
161 * If `stack' is NULL this call has no effect.
165 * All memory allocations in silc_foo_parse_packet will be done in
166 * a fresh stack frame and that data is freed after the parsing is
169 * silc_stack_push(stack, NULL);
170 * silc_foo_parse_packet(packet, stack);
171 * silc_stack_pop(stack);
173 * Another example with recursion and using statically allocated
174 * SilcStackFrame. After popping the statically allocated frame can
175 * be reused if necessary.
177 * void silc_foo_this_function(SilcStack stack)
179 * SilcStackFrame frame;
181 * silc_stack_push(stack, &frame);
182 * silc_foo_this_function(stack); // Call recursively
183 * silc_stack_pop(stack);
188 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
190 /****f* silcutil/SilcStackAPI/silc_stack_pop
194 * SilcUInt32 silc_stack_pop(SilcStack stack);
198 * Pop the top of the stack upwards which reveals the previous stack frame
199 * and becomes the top of the stack. After popping, memory allocated in
200 * the old frame is freed. For each silc_stack_push call there must be
201 * silc_stack_pop call to free all memory (in reality any memory is not
202 * freed but within the stack it is). This returns the stack pointer of
203 * old frame after popping and caller may check that it is same as
204 * returned by the silc_stack_push. If it they differ, some routine
205 * has called silc_stack_push but has not called silc_stack_pop, or
206 * silc_stack_pop has been called too many times. Application should
207 * treat this as a fatal error, as it is a bug in the application code.
209 * If `stack' is NULL this call has no effect.
213 * This example saves the stack pointer which is checked when popping
214 * the current stack frame. If the stack pointer differs then someone
215 * has pushed the stack frame but forgot to pop it (or has called it
218 * sp = silc_stack_push(stack, NULL);
219 * silc_foo_parse_packet(packet, stack);
220 * if (silc_stack_pop(stack) != sp)
221 * fatal("corrupted stack");
224 SilcUInt32 silc_stack_pop(SilcStack stack);
226 /****f* silcutil/SilcStackAPI/silc_stack_malloc
230 * void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
234 * Low level memory allocation routine. Allocates memor block of size of
235 * `size' from the `stack'. The allocated memory is aligned so it can be
236 * used to allocate memory for structures, for example. Returns the
237 * allocated memory address or NULL if memory could not be allocated from
242 * This function should be used only if low level memory allocation with
243 * SilcStack is needed. Instead, silc_smalloc, could be used.
246 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
248 /****f* silcutil/SilcStackAPI/silc_stack_realloc
252 * void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
253 * *void *ptr, SilcUInt32 size);
257 * Attempts to reallocate memory by changing the size of the `ptr' into
258 * `size'. This routine works only if the previous allocation to `stack'
259 * was `ptr'. If there is another memory allocation between allocating
260 * `ptr' and this call this routine will return NULL. NULL is also
261 * returned if the `size' does not fit into the current block. If NULL
262 * is returned the old memory remains intact.
266 * This function should be used only if low level memory allocation with
267 * SilcStack is needed. Instead, silc_srealloc, could be used.
270 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
271 void *ptr, SilcUInt32 size);
273 /****f* silcutil/SilcStackAPI/silc_stack_set_alignment
277 * void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
281 * Sets/changes the memory alignment in the `stack' to `alignment' which
282 * is the alignment in bytes. By default, the SilcStack will use alignment
283 * suited for the platform where it is used. This function can be used
284 * change this alignment, if such change is needed. You may check the
285 * current alignment by calling silc_stack_get_alignment.
289 * It is not mandatory to call this function. By default the SilcStack
290 * will always use alignment suited for the used platform. This function
291 * should be called only if the alignment needs to be changed to something
292 * other than the default on the used platform. For example, some
293 * hardware device, such as crypto accelerator, may require special
297 void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
299 /****f* silcutil/SilcStackAPI/silc_stack_get_alignment
303 * SilcUInt32 silc_stack_get_alignment(SilcStack stack);
307 * Returns the memory alignment used with `stack'. The alignment is in
311 SilcUInt32 silc_stack_get_alignment(SilcStack stack);
313 #include "silcstack_i.h"
315 #endif /* SILCSTACK_H */