Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[silc.git] / lib / silcutil / silcstack_i.h
1 /*
2
3   silcstack_i.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2005 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 #ifndef SILCSTACK_I_H
21 #define SILCSTACK_I_H
22
23 #ifndef SILCSTACK_H
24 #error "Do not include this header directly"
25 #endif
26
27 /* The default stack size when stack is created */
28 #define SILC_STACK_DEFAULT_SIZE       1024
29
30 /* Number of pre-allocated stack frames */
31 #define SILC_STACK_DEFAULT_NUM        8
32
33 /* Default alignment */
34 #define SILC_STACK_DEFAULT_ALIGN      sizeof(unsigned long)
35
36 /* Maximum allocation that can be made with SilcStack.  This is
37    SILC_STACK_DEFAULT_SIZE * (2 ^ (SILC_STACK_BLOCK_NUM - 1)). */
38 #define SILC_STACK_MAX_ALLOC          0x02000000
39 #define SILC_STACK_BLOCK_NUM          16
40
41 /* Stack frame data area */
42 typedef struct SilcStackDataStruct {
43   SilcUInt32 bytes_left;                      /* Free bytes in stack */
44   /* Stack data area starts here */
45 } *SilcStackData;
46
47 /* Stack frame */
48 struct SilcStackFrameStruct {
49   struct SilcStackFrameStruct *prev;          /* Pointer to previous frame */
50   SilcUInt32 bytes_used;                      /* Bytes used when pushed */
51   unsigned int sp : 27;                       /* Stack pointer */
52   unsigned int si : 5;                        /* Stack index */
53 };
54
55 /* The SilcStack context */
56 struct SilcStackStruct {
57   SilcStackData stack[SILC_STACK_BLOCK_NUM];  /* Allocated stack blocks */
58   SilcStackFrame *frames;                     /* Allocated stack frames */
59   SilcStackFrame *frame;                      /* Current stack frame */
60   SilcUInt32 stack_size;                      /* Default stack size */
61 #ifdef SILC_DIST_INPLACE
62   /* Statistics */
63   SilcUInt32 snum_malloc;
64   SilcUInt32 sbytes_malloc;
65   SilcUInt32 snum_errors;
66 #endif /* SILC_DIST_INPLACE */
67 };
68
69 /* Align the requested amount bytes.  The `align' defines the requested
70    alignment. */
71 #define SILC_STACK_ALIGN(bytes, align) (((bytes) + (align - 1)) & ~(align - 1))
72
73 /* Computes the size of stack block si. */
74 #define SILC_STACK_BLOCK_SIZE(stack, si)                \
75   (((si) == 0) ? stack->stack_size :                    \
76    SILC_STACK_DEFAULT_SIZE * (1L << ((si) - 1)) << 1);
77
78 /* Returns a pointer to the data in the frame */
79 #define SILC_STACK_DATA(stack, si, bsize)                                 \
80   (((unsigned char *)(stack)->stack[si]) +                                \
81    SILC_STACK_ALIGN(sizeof(**(stack)->stack), SILC_STACK_DEFAULT_ALIGN) + \
82    ((bsize) - (stack)->stack[si]->bytes_left))
83
84 #ifdef SILC_DIST_INPLACE
85 /* Statistics updating */
86 #define SILC_STACK_STAT(stack, stat, val) ((stack)->s ## stat += (val))
87 #define SILC_ST_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
88 #else /* !SILC_DIST_INPLACE */
89 #define SILC_STACK_STAT(stack, stat, val)
90 #define SILC_ST_DEBUG(fmt)
91 #endif /* SILC_DIST_INPLACE */
92
93 /* Allocate memory.  If the `aligned' is FALSE this allocates unaligned
94    memory, otherwise memory is aligned.  Returns pointer to the memory
95    or NULL on error. */
96 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size, SilcBool aligned);
97
98 /* Attempts to reallocate memory by changing the size of the `ptr' into
99    `size'.  This routine works only if the previous allocation to `stack'
100    was `ptr'.  If there is another memory allocation between allocating
101    `ptr' and this call this routine will return NULL.  NULL is also returned
102    if the `size' does not fit into the current block.  If NULL is returned
103    the old memory remains intact. */
104 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
105                          void *ptr, SilcUInt32 size, SilcBool aligned);
106
107 #ifdef SILC_DIST_INPLACE
108 /* Prints statistics of the usage of SilcStack to stdout. */
109 void silc_stack_stats(SilcStack stack);
110 #endif /* SILC_DIST_INPLACE */
111
112 #endif /* SILCSTACK_I_H */