2 * Bacula memory pool routines.
4 * The idea behind these routines is that there will be
5 * pools of memory that are pre-allocated for quick
6 * access. The pools will have a fixed memory size on allocation
7 * but if need be, the size can be increased. This is
8 * particularly useful for filename
9 * buffers where 256 bytes should be sufficient in 99.99%
10 * of the cases, but when it isn't we want to be able to
13 * A major advantage of the pool memory aside from the speed
14 * is that the buffer carrys around its size, so to ensure that
15 * there is enough memory, simply call the check_pool_memory_size()
16 * with the desired size and it will adjust only if necessary.
24 Copyright (C) 2000-2003 Kern Sibbald and John Walker
26 This program is free software; you can redistribute it and/or
27 modify it under the terms of the GNU General Public License as
28 published by the Free Software Foundation; either version 2 of
29 the License, or (at your option) any later version.
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 General Public License for more details.
36 You should have received a copy of the GNU General Public
37 License along with this program; if not, write to the Free
38 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
46 size_t size; /* default size */
47 size_t max_size; /* max allocated */
48 size_t max_used; /* max buffers used */
49 size_t in_use; /* number in use */
50 struct abufhead *free_buf; /* pointer to free buffers */
53 /* #define STRESS_TEST_POOL */
54 #ifndef STRESS_TEST_POOL
56 * Define default Pool buffer sizes
58 static struct s_pool_ctl pool_ctl[] = {
59 { 256, 256, 0, 0, NULL }, /* PM_NOPOOL no pooling */
60 { 256, 256, 0, 0, NULL }, /* PM_FNAME filename buffers */
61 { 512, 512, 0, 0, NULL }, /* PM_MESSAGE message buffer */
62 { 1024, 1024, 0, 0, NULL } /* PM_EMSG error message buffer */
66 /* This is used ONLY when stress testing the code */
67 static struct s_pool_ctl pool_ctl[] = {
68 { 20, 20, 0, 0, NULL }, /* PM_NOPOOL no pooling */
69 { 20, 20, 0, 0, NULL }, /* PM_FNAME filename buffers */
70 { 20, 20, 0, 0, NULL }, /* PM_MESSAGE message buffer */
71 { 20, 20, 0, 0, NULL } /* PM_EMSG error message buffer */
76 /* Memory allocation control structures and storage. */
78 size_t ablen; /* Buffer length in bytes */
79 int32_t pool; /* pool */
80 struct abufhead *next; /* pointer to next free buffer */
83 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
88 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
90 extern POOLMEM *sm_malloc(char *fname, int lineno, int nbytes);
92 POOLMEM *sm_get_pool_memory(char *fname, int lineno, int pool)
96 sm_check(fname, lineno, True);
98 Emsg2(M_ABORT, 0, "MemPool index %d larger than max %d\n", pool, PM_MAX);
101 if (pool_ctl[pool].free_buf) {
102 buf = pool_ctl[pool].free_buf;
103 pool_ctl[pool].free_buf = buf->next;
104 pool_ctl[pool].in_use++;
105 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
106 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
109 Dmsg3(150, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
110 sm_new_owner(fname, lineno, (char *)buf);
111 return (POOLMEM *)((char *)buf+HEAD_SIZE);
114 if ((buf = (struct abufhead *) sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
116 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
118 buf->ablen = pool_ctl[pool].size;
120 pool_ctl[pool].in_use++;
121 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
122 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
125 Dmsg3(150, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
126 return (POOLMEM *)((char *)buf+HEAD_SIZE);
129 /* Get nonpool memory of size requested */
130 POOLMEM *sm_get_memory(char *fname, int lineno, size_t size)
132 struct abufhead *buf;
135 sm_check(fname, lineno, True);
136 if ((buf = (struct abufhead *) sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
137 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
142 pool_ctl[pool].in_use++;
143 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used)
144 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
145 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
149 /* Return the size of a memory buffer */
150 size_t sm_sizeof_pool_memory(char *fname, int lineno, POOLMEM *obuf)
152 char *cp = (char *)obuf;
154 sm_check(fname, lineno, False);
157 return ((struct abufhead *)cp)->ablen;
160 /* Realloc pool memory buffer */
161 POOLMEM *sm_realloc_pool_memory(char *fname, int lineno, POOLMEM *obuf, size_t size)
163 char *cp = (char *)obuf;
167 sm_check(fname, lineno, False);
171 buf = sm_realloc(fname, lineno, cp, size+HEAD_SIZE);
172 sm_check(fname, lineno, True);
175 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
177 ((struct abufhead *)buf)->ablen = size;
178 pool = ((struct abufhead *)buf)->pool;
179 if (size > pool_ctl[pool].max_size) {
180 pool_ctl[pool].max_size = size;
183 sm_check(fname, lineno, False);
184 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
187 POOLMEM *sm_check_pool_memory_size(char *fname, int lineno, POOLMEM *obuf, size_t size)
189 sm_check(fname, lineno, False);
191 if (size <= sizeof_pool_memory(obuf)) {
194 return realloc_pool_memory(obuf, size);
197 /* Free a memory buffer */
198 void sm_free_pool_memory(char *fname, int lineno, POOLMEM *obuf)
200 struct abufhead *buf;
203 sm_check(fname, lineno, True);
206 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
208 pool_ctl[pool].in_use--;
210 free((char *)buf); /* free nonpooled memory */
211 } else { /* otherwise link it to the free pool chain */
213 struct abufhead *next;
214 /* Don't let him free the same buffer twice */
215 for (next=pool_ctl[pool].free_buf; next; next=next->next) {
216 ASSERT(next != buf); /* attempt to free twice */
219 buf->next = pool_ctl[pool].free_buf;
220 pool_ctl[pool].free_buf = buf;
222 Dmsg2(150, "free_pool_memory %x pool=%d\n", buf, pool);
229 /* =================================================================== */
231 POOLMEM *get_pool_memory(int pool)
233 struct abufhead *buf;
236 if (pool_ctl[pool].free_buf) {
237 buf = pool_ctl[pool].free_buf;
238 pool_ctl[pool].free_buf = buf->next;
240 return (POOLMEM *)((char *)buf+HEAD_SIZE);
243 if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
245 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
247 buf->ablen = pool_ctl[pool].size;
250 pool_ctl[pool].in_use++;
251 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
252 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
255 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
258 /* Get nonpool memory of size requested */
259 POOLMEM *get_memory(size_t size)
261 struct abufhead *buf;
264 if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
265 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
270 pool_ctl[pool].in_use++;
271 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
272 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
274 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
278 /* Return the size of a memory buffer */
279 size_t sizeof_pool_memory(POOLMEM *obuf)
281 char *cp = (char *)obuf;
285 return ((struct abufhead *)cp)->ablen;
288 /* Realloc pool memory buffer */
289 POOLMEM *realloc_pool_memory(POOLMEM *obuf, size_t size)
291 char *cp = (char *)obuf;
298 buf = realloc(cp, size+HEAD_SIZE);
301 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
303 ((struct abufhead *)buf)->ablen = size;
304 pool = ((struct abufhead *)buf)->pool;
305 if (size > pool_ctl[pool].max_size) {
306 pool_ctl[pool].max_size = size;
309 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
312 POOLMEM *check_pool_memory_size(POOLMEM *obuf, size_t size)
315 if (size <= sizeof_pool_memory(obuf)) {
318 return realloc_pool_memory(obuf, size);
321 /* Free a memory buffer */
322 void free_pool_memory(POOLMEM *obuf)
324 struct abufhead *buf;
327 sm_check(__FILE__, __LINE__, False);
330 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
332 pool_ctl[pool].in_use--;
334 free((char *)buf); /* free nonpooled memory */
335 } else { /* otherwise link it to the free pool chain */
337 struct abufhead *next;
338 /* Don't let him free the same buffer twice */
339 for (next=pool_ctl[pool].free_buf; next; next=next->next) {
340 ASSERT(next != buf); /* attempt to free twice */
343 buf->next = pool_ctl[pool].free_buf;
344 pool_ctl[pool].free_buf = buf;
346 Dmsg2(150, "free_pool_memory %x pool=%d\n", buf, pool);
350 #endif /* SMARTALLOC */
357 /* Release all pooled memory */
358 void close_memory_pool()
360 struct abufhead *buf, *next;
363 sm_check(__FILE__, __LINE__, False);
365 for (i=1; i<=PM_MAX; i++) {
366 buf = pool_ctl[i].free_buf;
372 pool_ctl[i].free_buf = NULL;
379 static char *pool_name(int pool)
381 static char *name[] = {"NoPool", "FNAME ", "MSG ", "EMSG "};
384 if (pool >= 0 && pool <= PM_MAX) {
387 sprintf(buf, "%-6d", pool);
391 /* Print staticstics on memory pool usage
393 void print_memory_pool_stats()
397 Dmsg0(-1, "Pool Maxsize Maxused Inuse\n");
398 for (i=0; i<=PM_MAX; i++)
399 Dmsg4(-1, "%5s %7d %7d %5d\n", pool_name(i), pool_ctl[i].max_size,
400 pool_ctl[i].max_used, pool_ctl[i].in_use);
406 void print_memory_pool_stats() {}