SILC_ERR_INVALID_ARGUMENT is return by silc_stack_realloc if
[crypto.git] / lib / silcutil / silcstack.h
1 /*
2
3   silcstack.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2007 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 /****h* silcutil/SilcStack Interface
21  *
22  * DESCRIPTION
23  *
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
30  * is not an issue.
31  *
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.
38  *
39  * SilcStack is also a full featured memory pool which allows user to group
40  * together multiple stacks.  Child stacks may be created from a parent stack
41  * without consuming the parent stack.  When the child is freed, its memory
42  * is returned back to the parent and can be used again by other childs.
43  * It is also possible to create child stacks from another child stack.
44  *
45  * A basic set of utility functions are provided for application that wish
46  * to use the SilcStack as their primary memory allocation source.  The
47  * following functions support SilcStack:
48  *
49  * silc_smalloc, silc_smalloc, silc_scalloc, silc_srealloc, silc_smemdup,
50  * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
51  * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
52  * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
53  * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit,
54  * silc_dlist_sinit, silc_hash_table_alloc
55  *
56  * The SilcStack is not thread-safe so that same context could be used for
57  * allocations from multiple threads.  It is however safe to create and use
58  * child stacks in a different thread from the parent stack.  Each thread
59  * should allocate their own SilcStack, however they may be child stacks.
60  *
61  ***/
62
63 #ifndef SILCSTACK_H
64 #define SILCSTACK_H
65
66 /****s* silcutil/SilcStackAPI/SilcStack
67  *
68  * NAME
69  *
70  *    typedef struct SilcStackStruct *SilcStack;
71  *
72  * DESCRIPTION
73  *
74  *    This context represents the stack and it is allocated by
75  *    silc_stack_alloc and is destroyed with silc_stack_free functions.
76  *    The context is given as argument to all routines that use this
77  *    stack allocation library.
78  *
79  ***/
80 typedef struct SilcStackStruct *SilcStack;
81
82 /****s* silcutil/SilcStackAPI/SilcStackFrame
83  *
84  * NAME
85  *
86  *    typedef struct SilcStackFrameStruct SilcStackFrame;
87  *
88  * DESCRIPTION
89  *
90  *    Static stack frame context that optionally can be used as stack
91  *    frame in SilcStack.  By default silc_stack_push use pre-allocated
92  *    stack frame, but user may also use statically allocated SilcStackFrame
93  *    instead.  This is recommended when using SilcStack in recursive routine
94  *    and the recursion may become deep.  Using static frame assures that
95  *    during recursion frames never run out.
96  *
97  ***/
98 typedef struct SilcStackFrameStruct SilcStackFrame;
99
100 /****f* silcutil/SilcStackAPI/SilcStackOomHandler
101  *
102  * SYNOPSIS
103  *
104  *    typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
105  *
106  * DESCRIPTION
107  *
108  *    Callback of this type can be given to silc_stack_set_oom_handler
109  *    to set Out of Memory handler to `stack'.  If memory allocation from
110  *    `stack' fails this callback is called to indicate error.  The `context'
111  *    is the context given to silc_stack_set_oom_handler.
112  *
113  ***/
114 typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
115
116 /****f* silcutil/SilcStackAPI/silc_stack_alloc
117  *
118  * SYNOPSIS
119  *
120  *    SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
121  *
122  * DESCRIPTION
123  *
124  *    Allocates new data stack that can be used as stack for fast memory
125  *    allocation by various routines.  Returns the pointer to the stack
126  *    that must be freed with silc_stack_free function when it is not
127  *    needed anymore.  If the `stack_size' is zero (0) by default a
128  *    1 kilobyte (1024 bytes) stack is allocated.  If the `stack_size'
129  *    is non-zero the byte value must be multiple by 8.
130  *
131  *    If `parent' is non-NULL the created stack is a child of the `parent'
132  *    stack.  All of childs the memory is allocated from the `parent' and
133  *    will be returned back to the parent when the child is freed.  Note
134  *    that, even though child allocates memory from the parent, the parent's
135  *    stack is not consumed.
136  *
137  *    Returns NULL on error.
138  *
139  ***/
140 SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
141
142 /****f* silcutil/SilcStackAPI/silc_stack_free
143  *
144  * SYNOPSIS
145  *
146  *    void silc_stack_free(SilcStack stack);
147  *
148  * DESCRIPTION
149  *
150  *    Frees the data stack context.  The stack cannot be used anymore after
151  *    this and all allocated memory are freed.
152  *
153  *    If `stack' is a child stack, its memory is returned back to its
154  *    parent.  If `stack' is NULL this function does nothing.
155  *
156  ***/
157 void silc_stack_free(SilcStack stack);
158
159 /****f* silcutil/SilcStackAPI/silc_stack_push
160  *
161  * SYNOPSIS
162  *
163  *    SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
164  *
165  * DESCRIPTION
166  *
167  *    Push the top of the stack down which becomes the new top of the stack.
168  *    For every silc_stack_push call there must be silc_stack_pop call.  All
169  *    allocations between these two calls will be done from the top of the
170  *    stack and all allocated memory is freed after the next silc_stack_pop
171  *    is called.  This returns so called stack pointer for the new stack
172  *    frame, which the caller may use to check that all calls to
173  *    silc_stack_pop has been made.
174  *
175  *    If the `frame' is non-NULL then that SilcStackFrame is used as
176  *    stack frame.  Usually `frame' is set to NULL by user.  Statically
177  *    allocated SilcStackFrame should be used when using silc_stack_push
178  *    in recursive function and the recursion may become deep.  In this
179  *    case using statically allocated SilcStackFrame is recommended since
180  *    it assures that frames never run out.  If your routine is not recursive
181  *    then setting `frame' to NULL is recommended.
182  *
183  *    This function is used when a routine is doing frequent allocations
184  *    from the stack.  If the stack is not pushed and later popped all
185  *    allocations are made from the stack and the stack eventually runs out
186  *    (it gets enlarged by normal memory allocation).  By pushing and then
187  *    later popping the frequent allocations does not consume the stack.
188  *
189  *    If `stack' is NULL this call has no effect.  This function does not
190  *    allocate any memory.
191  *
192  * EXAMPLE
193  *
194  *    All memory allocations in silc_foo_parse_packet will be done in
195  *    a fresh stack frame and that data is freed after the parsing is
196  *    completed.
197  *
198  *    silc_stack_push(stack, NULL);
199  *    silc_foo_parse_packet(packet, stack);
200  *    silc_stack_pop(stack);
201  *
202  *    Another example with recursion and using statically allocated
203  *    SilcStackFrame.  After popping the statically allocated frame can
204  *    be reused if necessary.
205  *
206  *    void silc_foo_this_function(SilcStack stack)
207  *    {
208  *      SilcStackFrame frame;
209  *      ...
210  *      silc_stack_push(stack, &frame);
211  *      silc_foo_this_function(stack);   // Call recursively
212  *      silc_stack_pop(stack);
213  *      ...
214  *    }
215  *
216  ***/
217 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
218
219 /****f* silcutil/SilcStackAPI/silc_stack_pop
220  *
221  * SYNOPSIS
222  *
223  *    SilcUInt32 silc_stack_pop(SilcStack stack);
224  *
225  * DESCRIPTION
226  *
227  *    Pop the top of the stack which removes the previous stack frame and
228  *    becomes the top of the stack.  After popping, memory allocated in
229  *    the old frame is freed.  For each silc_stack_push call there must be
230  *    silc_stack_pop call to free all memory (in reality any memory is not
231  *    freed but within the stack it is).  This returns the stack pointer of
232  *    old frame after popping and caller may check that it is same as
233  *    returned by the silc_stack_push.  If it they differ, some routine
234  *    has called silc_stack_push but has not called silc_stack_pop, or
235  *    silc_stack_pop has been called too many times.  Application should
236  *    treat this as a fatal error, as it is a bug in the application code.
237  *
238  *    If `stack' is NULL this call has no effect.   This function does not
239  *    allocate any memory.
240  *
241  * EXAMPLE
242  *
243  *    This example saves the stack pointer which is checked when popping
244  *    the current stack frame.  If the stack pointer differs then someone
245  *    has pushed the stack frame but forgot to pop it (or has called it
246  *    too many times).
247  *
248  *    sp = silc_stack_push(stack, NULL);
249  *    silc_foo_parse_packet(packet, stack);
250  *    if (silc_stack_pop(stack) != sp)
251  *      fatal("corrupted stack");
252  *
253  ***/
254 SilcUInt32 silc_stack_pop(SilcStack stack);
255
256 /****f* silcutil/SilcStackAPI/silc_stack_malloc
257  *
258  * SYNOPSIS
259  *
260  *    void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
261  *
262  * DESCRIPTION
263  *
264  *    Low level memory allocation routine.  Allocates memory block of size of
265  *    `size' from the `stack'.  The allocated memory is aligned so it can be
266  *    used to allocate memory for structures, for example.  Returns the
267  *    allocated memory address or NULL if memory could not be allocated from
268  *    the `stack'.
269  *
270  * NOTES
271  *
272  *    This function should be used only if low level memory allocation with
273  *    SilcStack is needed.  Instead, silc_smalloc and silc_scalloc could
274  *    be used.
275  *
276  ***/
277 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
278
279 /****f* silcutil/SilcStackAPI/silc_stack_realloc
280  *
281  * SYNOPSIS
282  *
283  *    void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
284  *                             void *ptr, SilcUInt32 size);
285  *
286  * DESCRIPTION
287  *
288  *    Attempts to reallocate memory by changing the size of the `ptr' into
289  *    `size'.  This routine works only if the previous allocation to `stack'
290  *    was `ptr'.  If there is another memory allocation between allocating
291  *    `ptr' and this call this routine will return NULL (and silc_errno is
292  *    set to SILC_ERR_INVALID_ARGUMENT).  NULL is also returned if the `size'
293  *    does not fit into the current stack block.  If NULL is returned the old
294  *    memory remains intact.
295  *
296  * NOTES
297  *
298  *    This function should be used only if low level memory allocation with
299  *    SilcStack is needed.  Instead, silc_srealloc could be used.
300  *
301  ***/
302 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
303                          void *ptr, SilcUInt32 size);
304
305 /****f* silcutil/SilcStackAPI/silc_stack_set_oom_handler
306  *
307  * SYNOPSIS
308  *
309  *    void silc_stack_set_oom_handler(SilcStack stack,
310  *                                    SilcStackOomHandler oom_handler,
311  *                                    void *context);
312  *
313  * DESCRIPTION
314  *
315  *    Sets Out of Memory handler `oom_handler' to `stack' to be called
316  *    if memory allocation from `stack' fails.  The `context' is delivered
317  *    to `oom_handler'.
318  *
319  *    Usually Out of Memory handler is set only when failed memory allocation
320  *    is a fatal error.  In this case the application would abort() inside
321  *    the `oom_handler'.  It may also be set if in case of failed allocation
322  *    application wants to do clean up properly.
323  *
324  ***/
325 void silc_stack_set_oom_handler(SilcStack stack,
326                                 SilcStackOomHandler oom_handler,
327                                 void *context);
328
329 /****f* silcutil/SilcStackAPI/silc_stack_set_alignment
330  *
331  * SYNOPSIS
332  *
333  *    void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
334  *
335  * DESCRIPTION
336  *
337  *    Sets/changes the memory alignment in the `stack' to `alignment' which
338  *    is the alignment in bytes.  By default, the SilcStack will use alignment
339  *    suited for the platform where it is used.  This function can be used
340  *    to change this alignment, if such change is needed.  You may check the
341  *    current alignment by calling silc_stack_get_alignment.
342  *
343  * NOTES
344  *
345  *    It is not mandatory to call this function.  By default the SilcStack
346  *    will always use alignment suited for the used platform.  This function
347  *    should be called only if the alignment needs to be changed to something
348  *    other than the default on the used platform.  For example, some
349  *    hardware device, such as crypto accelerator, may require special
350  *    alignment.
351  *
352  ***/
353 void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
354
355 /****f* silcutil/SilcStackAPI/silc_stack_get_alignment
356  *
357  * SYNOPSIS
358  *
359  *    SilcUInt32 silc_stack_get_alignment(SilcStack stack);
360  *
361  * DESCRIPTION
362  *
363  *    Returns the memory alignment used with `stack'.  The alignment is in
364  *    bytes.
365  *
366  ***/
367 SilcUInt32 silc_stack_get_alignment(SilcStack stack);
368
369 /****f* silcutil/SilcStackAPI/silc_stack_purge
370  *
371  * SYNOPSIS
372  *
373  *    SilcBool silc_stack_purge(SilcStack stack);
374  *
375  * DESCRIPTION
376  *
377  *    Purges the `stack' from extra unused memory.  This purges only `stack'
378  *    and not its parent if `stack' is a child.  This purges only large
379  *    allocations.  The 1024, 2048, 4096 and 8192 bytes of allocations remain.
380  *    Call this multiple times to purge even more.  Returns FALSE when there
381  *    is no more to purge.  This does not purge memory blocks that currently
382  *    have allocations.  No memory allocations from the stack are lost, so
383  *    this is always safe to call.
384  *
385  ***/
386 SilcBool silc_stack_purge(SilcStack stack);
387
388 #include "silcstack_i.h"
389
390 #endif /* SILCSTACK_H */