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.
22 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
24 This program is free software; you can redistribute it and/or
25 modify it under the terms of the GNU General Public License as
26 published by the Free Software Foundation; either version 2 of
27 the License, or (at your option) any later version.
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 General Public License for more details.
34 You should have received a copy of the GNU General Public
35 License along with this program; if not, write to the Free
36 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
44 size_t size; /* default size */
45 size_t max_size; /* max allocated */
46 size_t max_used; /* max buffers used */
47 size_t in_use; /* number in use */
48 struct abufhead *free_buf; /* pointer to free buffers */
51 static struct s_pool_ctl pool_ctl[] = {
52 { 256, 256, 0, 0, NULL }, /* PM_NOPOOL no pooling */
53 { 256, 256, 0, 0, NULL }, /* PM_FNAME filename buffers */
54 { 512, 512, 0, 0, NULL }, /* PM_MESSAGE message buffer */
55 { 1024, 1024, 0, 0, NULL } /* PM_EMSG error message buffer */
58 /* Memory allocation control structures and storage. */
60 size_t ablen; /* Buffer length in bytes */
61 int32_t pool; /* pool */
62 struct abufhead *next; /* pointer to next free buffer */
65 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
72 extern POOLMEM *sm_malloc(char *fname, int lineno, int nbytes);
74 POOLMEM *sm_get_pool_memory(char *fname, int lineno, int pool)
78 sm_check(fname, lineno, True);
80 Emsg2(M_ABORT, 0, "MemPool index %d larger than max %d\n", pool, PM_MAX);
83 if (pool_ctl[pool].free_buf) {
84 buf = pool_ctl[pool].free_buf;
85 pool_ctl[pool].free_buf = buf->next;
86 pool_ctl[pool].in_use++;
87 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
88 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
91 Dmsg3(150, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
92 sm_new_owner(fname, lineno, (char *)buf);
93 return (POOLMEM *)((char *)buf+HEAD_SIZE);
96 if ((buf = (struct abufhead *) sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
98 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
100 buf->ablen = pool_ctl[pool].size;
102 pool_ctl[pool].in_use++;
103 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
104 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
107 Dmsg3(150, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
108 return (POOLMEM *)((char *)buf+HEAD_SIZE);
111 /* Get nonpool memory of size requested */
112 POOLMEM *sm_get_memory(char *fname, int lineno, size_t size)
114 struct abufhead *buf;
117 sm_check(fname, lineno, True);
118 if ((buf = (struct abufhead *) sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
119 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
124 pool_ctl[pool].in_use++;
125 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used)
126 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
127 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
132 POOLMEM *get_pool_memory(int pool)
134 struct abufhead *buf;
137 if (pool_ctl[pool].free_buf) {
138 buf = pool_ctl[pool].free_buf;
139 pool_ctl[pool].free_buf = buf->next;
141 return (POOLMEM *)((char *)buf+HEAD_SIZE);
144 if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
146 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", pool_ctl[pool].size);
148 buf->ablen = pool_ctl[pool].size;
151 pool_ctl[pool].in_use++;
152 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
153 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
156 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
159 /* Get nonpool memory of size requested */
160 POOLMEM *get_memory(size_t size)
162 struct abufhead *buf;
165 if ((buf=malloc(size+HEAD_SIZE)) == NULL) {
166 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
171 pool_ctl[pool].in_use++;
172 if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
173 pool_ctl[pool].max_used = pool_ctl[pool].in_use;
175 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
177 #endif /* SMARTALLOC */
181 /* Free a memory buffer */
182 void free_pool_memory(POOLMEM *obuf)
184 struct abufhead *buf;
187 sm_check(__FILE__, __LINE__, False);
190 buf = (struct abufhead *)((char *)obuf - HEAD_SIZE);
192 pool_ctl[pool].in_use--;
194 free((char *)buf); /* free nonpooled memory */
195 } else { /* otherwise link it to the free pool chain */
196 buf->next = pool_ctl[pool].free_buf;
197 pool_ctl[pool].free_buf = buf;
199 Dmsg2(150, "free_pool_memory %x pool=%d\n", buf, pool);
204 /* Return the size of a memory buffer */
205 size_t sizeof_pool_memory(POOLMEM *obuf)
207 char *cp = (char *)obuf;
209 sm_check(__FILE__, __LINE__, False);
212 return ((struct abufhead *)cp)->ablen;
215 /* Realloc pool memory buffer */
216 POOLMEM *realloc_pool_memory(POOLMEM *obuf, size_t size)
218 char *cp = (char *)obuf;
222 sm_check(__FILE__, __LINE__, False);
226 buf = realloc(cp, size+HEAD_SIZE);
229 Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
231 ((struct abufhead *)buf)->ablen = size;
232 pool = ((struct abufhead *)buf)->pool;
233 if (size > pool_ctl[pool].max_size) {
234 pool_ctl[pool].max_size = size;
237 sm_check(__FILE__, __LINE__, False);
238 return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
241 POOLMEM *check_pool_memory_size(POOLMEM *obuf, size_t size)
243 sm_check(__FILE__, __LINE__, False);
245 if (size <= sizeof_pool_memory(obuf)) {
248 return realloc_pool_memory(obuf, size);
251 /* Release all pooled memory */
252 void close_memory_pool()
254 struct abufhead *buf, *next;
257 sm_check(__FILE__, __LINE__, False);
259 for (i=1; i<=PM_MAX; i++) {
260 buf = pool_ctl[i].free_buf;
266 pool_ctl[i].free_buf = NULL;
273 static char *pool_name(int pool)
275 static char *name[] = {"NoPool", "FNAME ", "MSG ", "EMSG "};
278 if (pool >= 0 && pool <= PM_MAX) {
281 sprintf(buf, "%-6d", pool);
285 /* Print staticstics on memory pool usage
287 void print_memory_pool_stats()
291 Dmsg0(-1, "Pool Maxsize Maxused Inuse\n");
292 for (i=0; i<=PM_MAX; i++)
293 Dmsg4(-1, "%5s %7d %7d %5d\n", pool_name(i), pool_ctl[i].max_size,
294 pool_ctl[i].max_used, pool_ctl[i].in_use);
300 void print_memory_pool_stats() {}