Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/mempool-alloconly.c @ 941:4d6b69558add HEAD
Added old_size parameter to p_realloc() - we rarely need it and this way
each allocation takes 8 bytes less memory.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 10 Jan 2003 22:58:28 +0200 |
parents | fd8888f6f037 |
children | 4f38538aa4a1 |
rev | line source |
---|---|
0 | 1 /* |
2 mempool-alloconly.c : Memory pool for fast allocation of memory without | |
3 need to free it in small blocks | |
4 | |
5 Copyright (c) 2002 Timo Sirainen | |
6 | |
7 Permission is hereby granted, free of charge, to any person obtaining | |
8 a copy of this software and associated documentation files (the | |
9 "Software"), to deal in the Software without restriction, including | |
10 without limitation the rights to use, copy, modify, merge, publish, | |
11 distribute, sublicense, and/or sell copies of the Software, and to | |
12 permit persons to whom the Software is furnished to do so, subject to | |
13 the following conditions: | |
14 | |
15 The above copyright notice and this permission notice shall be | |
16 included in all copies or substantial portions of the Software. | |
17 | |
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
21 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
22 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
25 */ | |
26 | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
699
diff
changeset
|
27 /* @UNSAFE: whole file */ |
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
699
diff
changeset
|
28 |
0 | 29 #include "lib.h" |
30 #include "mempool.h" | |
31 | |
32 #include <stdlib.h> | |
33 | |
183
4a7ab9e94f25
size_t fixes for lib/. Changed OFF_T_FORMAT to PRIuOFF_T which is more
Timo Sirainen <tss@iki.fi>
parents:
72
diff
changeset
|
34 #define MAX_ALLOC_SIZE SSIZE_T_MAX |
0 | 35 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
36 struct alloconly_pool { |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
37 struct pool pool; |
0 | 38 int refcount; |
39 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
40 struct pool_block *block; |
0 | 41 |
42 char name[MEM_ALIGN_SIZE]; /* variable size */ | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
43 }; |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
44 #define SIZEOF_ALLOCONLYPOOL (sizeof(struct alloconly_pool)-MEM_ALIGN_SIZE) |
0 | 45 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
46 struct pool_block { |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
47 struct pool_block *prev; |
0 | 48 |
183
4a7ab9e94f25
size_t fixes for lib/. Changed OFF_T_FORMAT to PRIuOFF_T which is more
Timo Sirainen <tss@iki.fi>
parents:
72
diff
changeset
|
49 size_t size; |
4a7ab9e94f25
size_t fixes for lib/. Changed OFF_T_FORMAT to PRIuOFF_T which is more
Timo Sirainen <tss@iki.fi>
parents:
72
diff
changeset
|
50 size_t left; |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
51 size_t last_alloc_size; |
0 | 52 |
72 | 53 /* unsigned char data[]; */ |
0 | 54 }; |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
55 #define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block))) |
72 | 56 |
57 #define POOL_BLOCK_DATA(block) \ | |
58 ((char *) (block) + SIZEOF_POOLBLOCK) | |
0 | 59 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
60 static void pool_alloconly_ref(pool_t pool); |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
61 static void pool_alloconly_unref(pool_t pool); |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
62 static void *pool_alloconly_malloc(pool_t pool, size_t size); |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
63 static void pool_alloconly_free(pool_t pool, void *mem); |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
64 static void *pool_alloconly_realloc(pool_t pool, void *mem, |
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
65 size_t old_size, size_t new_size); |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
66 static void pool_alloconly_clear(pool_t pool); |
0 | 67 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
68 static void block_alloc(struct alloconly_pool *pool, size_t size); |
330 | 69 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
70 static struct pool static_alloconly_pool = { |
330 | 71 pool_alloconly_ref, |
72 pool_alloconly_unref, | |
73 | |
74 pool_alloconly_malloc, | |
75 pool_alloconly_free, | |
76 | |
77 pool_alloconly_realloc, | |
78 | |
79 pool_alloconly_clear | |
80 }; | |
0 | 81 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
82 pool_t pool_alloconly_create(const char *name, size_t size) |
0 | 83 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
84 struct alloconly_pool *apool; |
0 | 85 int len; |
86 | |
87 len = strlen(name); | |
88 | |
89 apool = calloc(SIZEOF_ALLOCONLYPOOL + len+1, 1); | |
409
849f3846212a
Check return values for malloc()s and calloc()s.
Timo Sirainen <tss@iki.fi>
parents:
330
diff
changeset
|
90 if (apool == NULL) |
849f3846212a
Check return values for malloc()s and calloc()s.
Timo Sirainen <tss@iki.fi>
parents:
330
diff
changeset
|
91 i_panic("pool_alloconly_create(): Out of memory"); |
0 | 92 apool->pool = static_alloconly_pool; |
93 apool->refcount = 1; | |
807
35abd7a5d381
Buffer related cleanups. Use PATH_MAX instead of hardcoded 1024 for paths.
Timo Sirainen <tss@iki.fi>
parents:
805
diff
changeset
|
94 memcpy(apool->name, name, len+1); |
0 | 95 |
96 block_alloc(apool, size); | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
97 return (struct pool *) apool; |
0 | 98 } |
99 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
100 static void pool_alloconly_destroy(struct alloconly_pool *apool) |
0 | 101 { |
102 /* destroy all but the last block */ | |
103 pool_alloconly_clear(&apool->pool); | |
104 | |
105 /* destroy the last block */ | |
106 free(apool->block); | |
107 free(apool); | |
108 } | |
109 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
110 static void pool_alloconly_ref(pool_t pool) |
0 | 111 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
112 struct alloconly_pool *apool = (struct alloconly_pool *) pool; |
0 | 113 |
114 apool->refcount++; | |
115 } | |
116 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
117 static void pool_alloconly_unref(pool_t pool) |
0 | 118 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
119 struct alloconly_pool *apool = (struct alloconly_pool *) pool; |
0 | 120 |
121 if (--apool->refcount == 0) | |
122 pool_alloconly_destroy(apool); | |
123 } | |
124 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
125 static void block_alloc(struct alloconly_pool *apool, size_t size) |
0 | 126 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
127 struct pool_block *block; |
0 | 128 |
129 /* each block is at least twice the size of the previous one */ | |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
130 if (apool->block != NULL && size <= apool->block->size) |
0 | 131 size += apool->block->size; |
132 | |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
133 size = nearest_power(size + SIZEOF_POOLBLOCK); |
0 | 134 |
826 | 135 #ifdef DEBUG |
136 if (apool->block != NULL) { | |
137 i_warning("Growing pool '%s' with: %"PRIuSIZE_T, | |
138 apool->name, size); | |
139 } | |
140 #endif | |
141 | |
0 | 142 block = calloc(size, 1); |
409
849f3846212a
Check return values for malloc()s and calloc()s.
Timo Sirainen <tss@iki.fi>
parents:
330
diff
changeset
|
143 if (block == NULL) |
849f3846212a
Check return values for malloc()s and calloc()s.
Timo Sirainen <tss@iki.fi>
parents:
330
diff
changeset
|
144 i_panic("block_alloc(): Out of memory"); |
0 | 145 block->prev = apool->block; |
146 apool->block = block; | |
147 | |
148 block->size = size - SIZEOF_POOLBLOCK; | |
149 block->left = block->size; | |
150 } | |
151 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
152 static void *pool_alloconly_malloc(pool_t pool, size_t size) |
0 | 153 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
154 struct alloconly_pool *apool = (struct alloconly_pool *) pool; |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
155 void *mem; |
0 | 156 |
839
34cb1d196d2b
String function cleanups. Allocating 0 bytes of memory is treated as error
Timo Sirainen <tss@iki.fi>
parents:
826
diff
changeset
|
157 if (size == 0 || size > SSIZE_T_MAX) |
34cb1d196d2b
String function cleanups. Allocating 0 bytes of memory is treated as error
Timo Sirainen <tss@iki.fi>
parents:
826
diff
changeset
|
158 i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size); |
34cb1d196d2b
String function cleanups. Allocating 0 bytes of memory is treated as error
Timo Sirainen <tss@iki.fi>
parents:
826
diff
changeset
|
159 |
0 | 160 size = MEM_ALIGN(size); |
161 | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
162 if (apool->block->left < size) { |
0 | 163 /* we need a new block */ |
164 block_alloc(apool, size); | |
165 } | |
166 | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
167 mem = POOL_BLOCK_DATA(apool->block) + |
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
168 (apool->block->size - apool->block->left); |
0 | 169 |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
170 apool->block->left -= size; |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
171 apool->block->last_alloc_size = size; |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
172 return mem; |
0 | 173 } |
174 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
175 static void pool_alloconly_free(pool_t pool __attr_unused__, |
0 | 176 void *mem __attr_unused__) |
177 { | |
178 /* ignore */ | |
179 } | |
180 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
181 static int pool_try_grow(struct alloconly_pool *apool, void *mem, size_t size) |
0 | 182 { |
183 /* see if we want to grow the memory we allocated last */ | |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
184 if (POOL_BLOCK_DATA(apool->block) + |
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
185 (apool->block->size - apool->block->left - |
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
186 apool->block->last_alloc_size) == mem) { |
0 | 187 /* yeah, see if we can grow */ |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
188 if (apool->block->left >= size-apool->block->last_alloc_size) { |
0 | 189 /* just shrink the available size */ |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
190 apool->block->left -= |
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
191 size - apool->block->last_alloc_size; |
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
192 apool->block->last_alloc_size = size; |
0 | 193 return TRUE; |
194 } | |
195 } | |
196 | |
197 return FALSE; | |
198 } | |
199 | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
200 static void *pool_alloconly_realloc(pool_t pool, void *mem, |
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
201 size_t old_size, size_t new_size) |
0 | 202 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
203 struct alloconly_pool *apool = (struct alloconly_pool *) pool; |
0 | 204 unsigned char *new_mem; |
205 | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
206 if (new_size == 0 || new_size > SSIZE_T_MAX) |
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
207 i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size); |
839
34cb1d196d2b
String function cleanups. Allocating 0 bytes of memory is treated as error
Timo Sirainen <tss@iki.fi>
parents:
826
diff
changeset
|
208 |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
209 if (mem == NULL) |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
210 return pool_alloconly_malloc(pool, new_size); |
0 | 211 |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
212 if (new_size <= old_size) |
0 | 213 return mem; |
214 | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
215 new_size = MEM_ALIGN(new_size); |
0 | 216 |
217 /* see if we can directly grow it */ | |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
218 if (!pool_try_grow(apool, mem, new_size)) { |
422 | 219 /* slow way - allocate + copy */ |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
220 new_mem = pool_alloconly_malloc(pool, new_size); |
422 | 221 memcpy(new_mem, mem, old_size); |
222 mem = new_mem; | |
223 } | |
0 | 224 |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
225 if (old_size < new_size) { |
0 | 226 /* clear new data */ |
941
4d6b69558add
Added old_size parameter to p_realloc() - we rarely need it and this way
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
227 memset((char *) mem + old_size, 0, new_size - old_size); |
0 | 228 } |
229 | |
422 | 230 return mem; |
0 | 231 } |
232 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
233 static void pool_alloconly_clear(pool_t pool) |
0 | 234 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
235 struct alloconly_pool *apool = (struct alloconly_pool *) pool; |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
857
diff
changeset
|
236 struct pool_block *block; |
0 | 237 |
238 /* destroy all blocks but the last, which is the largest */ | |
239 while (apool->block->prev != NULL) { | |
240 block = apool->block; | |
241 apool->block = block->prev; | |
242 | |
243 free(block); | |
244 } | |
245 | |
246 /* clear the last block */ | |
72 | 247 memset(POOL_BLOCK_DATA(apool->block), 0, |
248 apool->block->size - apool->block->left); | |
0 | 249 apool->block->left = apool->block->size; |
857
3d437b1e5257
Removed pool->realloc_min() which nothing used. A few small fixes to
Timo Sirainen <tss@iki.fi>
parents:
839
diff
changeset
|
250 apool->block->last_alloc_size = 0; |
0 | 251 } |