r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/samba.git] / source / lib / talloc.c
1 /* 
2    Samba Unix SMB/CIFS implementation.
3    Samba temporary memory allocation functions
4    Copyright (C) Andrew Tridgell 2000
5    Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /**
23    @defgroup talloc Simple memory allocator
24    @{
25    
26    This is a very simple temporary memory allocator. To use it do the following:
27
28    1) when you first want to allocate a pool of meomry use
29    talloc_init() and save the resulting context pointer somewhere
30
31    2) to allocate memory use talloc()
32
33    3) when _all_ of the memory allocated using this context is no longer needed
34    use talloc_destroy()
35
36    talloc does not zero the memory. It guarantees memory of a
37    TALLOC_ALIGN alignment
38
39    @sa talloc.h
40 */
41
42 /**
43  * @todo We could allocate both the talloc_chunk structure, and the
44  * memory it contains all in one allocation, which might be a bit
45  * faster and perhaps use less memory overhead.
46  *
47  * That smells like a premature optimization, though.  -- mbp
48  **/
49
50 /**
51  * If you want testing for memory corruption, link with dmalloc or use
52  * Insure++.  It doesn't seem useful to duplicate them here.
53  **/
54
55 #include "includes.h"
56
57 /* Max allowable allococation - 256mb - 0x10000000 */
58 #define MAX_TALLOC_SIZE (1024*1024*256)
59
60 /**
61  * Start of linked list of all talloc pools.
62  *
63  * @todo We should turn the global list off when using Insure++,
64  * otherwise all the memory will be seen as still reachable.
65  **/
66 static TALLOC_CTX *list_head = NULL;
67
68
69 /**
70  * Add to the global list
71  **/
72 static void talloc_enroll(TALLOC_CTX *t)
73 {
74         t->next_ctx = list_head;
75         list_head = t;
76 }
77
78
79 static void talloc_disenroll(TALLOC_CTX *t)
80 {
81         TALLOC_CTX **ttmp;
82
83         /* Use a double-* so that no special case is required for the
84          * list head. */
85         for (ttmp = &list_head; *ttmp; ttmp = &((*ttmp)->next_ctx))
86                 if (*ttmp == t) {
87                         /* ttmp is the link that points to t, either
88                          * list_head or the next_ctx link in its
89                          * predecessor */
90                         *ttmp = t->next_ctx;
91                         t->next_ctx = NULL;     /* clobber */
92                         return;
93                 }
94         abort();                /* oops, this talloc was already
95                                  * clobbered or something else went
96                                  * wrong. */
97 }
98
99
100 /** Create a new talloc context. **/
101 static TALLOC_CTX *talloc_init_internal(void)
102 {
103         TALLOC_CTX *t;
104
105         t = (TALLOC_CTX *)SMB_MALLOC(sizeof(TALLOC_CTX));
106         if (t) {
107                 t->list = NULL;
108                 t->total_alloc_size = 0;
109                 t->name = NULL;
110                 talloc_enroll(t);
111         }
112
113         return t;
114 }
115
116
117
118 /**
119  * Create a new talloc context, with a name specifying its purpose.
120  **/
121
122  TALLOC_CTX *talloc_init(char const *fmt, ...) 
123 {
124         TALLOC_CTX *t;
125         va_list ap;
126
127         t = talloc_init_internal();
128         if (t && fmt) {
129                 /*
130                  * t->name must not be talloced.
131                  * as destroying the pool would destroy it. JRA.
132                  */
133                 t->name = NULL;
134                 va_start(ap, fmt);
135                 vasprintf(&t->name, fmt, ap);
136                 va_end(ap);
137                 if (!t->name) {
138                         talloc_destroy(t);
139                         t = NULL;
140                 }
141         }
142         
143         return t;
144 }
145
146
147 /** Allocate a bit of memory from the specified pool **/
148 #if defined(PARANOID_MALLOC_CHECKER)
149 void *talloc_(TALLOC_CTX *t, size_t size)
150 #else
151 void *talloc(TALLOC_CTX *t, size_t size)
152 #endif
153 {
154         void *p;
155         struct talloc_chunk *tc;
156
157         if (!t || size == 0) return NULL;
158
159         p = SMB_MALLOC(size);
160         if (p) {
161                 tc = SMB_MALLOC(sizeof(*tc));
162                 if (tc) {
163                         tc->ptr = p;
164                         tc->size = size;
165                         tc->next = t->list;
166                         t->list = tc;
167                         t->total_alloc_size += size;
168                 }
169                 else {
170                         SAFE_FREE(p);
171                 }
172         }
173         return p;
174 }
175
176 /** Allocate an array of count elements of size x */
177 #if defined(PARANOID_MALLOC_CHECKER)
178 void *talloc_array_(TALLOC_CTX *ctx, size_t el_size, unsigned int count)
179 #else
180 void *talloc_array(TALLOC_CTX *ctx, size_t el_size, unsigned int count)
181 #endif
182 {
183         if (count >= MAX_TALLOC_SIZE/el_size) {
184                 return NULL;
185         }
186         return TALLOC(ctx, el_size * count);
187 }
188
189 /** A talloc version of realloc */
190 #if defined(PARANOID_MALLOC_CHECKER)
191 void *talloc_realloc_(TALLOC_CTX *t, void *ptr, size_t size)
192 #else
193 void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size)
194 #endif
195 {
196         struct talloc_chunk *tc;
197         void *new_ptr;
198
199         /* size zero is equivalent to free() */
200         if (!t || size == 0)
201                 return NULL;
202
203         /* realloc(NULL) is equavalent to malloc() */
204         if (ptr == NULL)
205                 return TALLOC(t, size);
206
207         for (tc=t->list; tc; tc=tc->next) {
208                 if (tc->ptr == ptr) {
209                         new_ptr = SMB_REALLOC(ptr, size);
210                         if (new_ptr) {
211                                 t->total_alloc_size += (size - tc->size);
212                                 tc->size = size;
213                                 tc->ptr = new_ptr;
214                         }
215                         return new_ptr;
216                 }
217         }
218         return NULL;
219 }
220
221 /** Re-allocate an array of count elements of size x */
222 #if defined(PARANOID_MALLOC_CHECKER)
223 void *talloc_realloc_array_(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned int count)
224 #else
225 void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned int count)
226 #endif
227 {
228         if (count >= MAX_TALLOC_SIZE/el_size) {
229                 return NULL;
230         }
231         return TALLOC_REALLOC(ctx, ptr, el_size * count);
232 }
233
234 /** Destroy all the memory allocated inside @p t, but not @p t
235  * itself. */
236 void talloc_destroy_pool(TALLOC_CTX *t)
237 {
238         struct talloc_chunk *c;
239         
240         if (!t)
241                 return;
242
243         while (t->list) {
244                 c = t->list->next;
245                 SAFE_FREE(t->list->ptr);
246                 SAFE_FREE(t->list);
247                 t->list = c;
248         }
249
250         t->total_alloc_size = 0;
251 }
252
253 /** Destroy a whole pool including the context */
254 void talloc_destroy(TALLOC_CTX *t)
255 {
256         if (!t)
257                 return;
258
259         talloc_destroy_pool(t);
260         talloc_disenroll(t);
261         SAFE_FREE(t->name);
262         memset(t, 0, sizeof(TALLOC_CTX));
263         SAFE_FREE(t);
264 }
265
266 /** Return the current total size of the pool. */
267 size_t talloc_pool_size(TALLOC_CTX *t)
268 {
269         if (t)
270                 return t->total_alloc_size;
271         else
272                 return 0;
273 }
274
275 const char * talloc_pool_name(TALLOC_CTX const *t)
276 {
277         if (t)
278                 return t->name;
279         else
280                 return NULL;
281 }
282
283
284 /** talloc and zero memory. */
285 #if defined(PARANOID_MALLOC_CHECKER)
286 void *talloc_zero_(TALLOC_CTX *t, size_t size)
287 #else
288 void *talloc_zero(TALLOC_CTX *t, size_t size)
289 #endif
290 {
291         void *p = TALLOC(t, size);
292
293         if (p)
294                 memset(p, '\0', size);
295
296         return p;
297 }
298
299 #if defined(PARANOID_MALLOC_CHECKER)
300 void *talloc_zero_array_(TALLOC_CTX *t, size_t el_size, unsigned int count)
301 #else
302 void *talloc_zero_array(TALLOC_CTX *t, size_t el_size, unsigned int count)
303 #endif
304 {
305 #if defined(PARANOID_MALLOC_CHECKER)
306         void *p = talloc_array_(t, el_size, count);
307 #else
308         void *p = talloc_array(t, el_size, count);
309 #endif
310
311         if (p)
312                 memset(p, '\0', el_size*count);
313
314         return p;
315 }
316
317 /** memdup with a talloc. */
318 #if defined(PARANOID_MALLOC_CHECKER)
319 void *talloc_memdup_(TALLOC_CTX *t, const void *p, size_t size)
320 #else
321 void *talloc_memdup(TALLOC_CTX *t, const void *p, size_t size)
322 #endif
323 {
324         void *newp = TALLOC(t,size);
325
326         if (newp)
327                 memcpy(newp, p, size);
328
329         return newp;
330 }
331
332 /** strdup with a talloc */
333 char *talloc_strdup(TALLOC_CTX *t, const char *p)
334 {
335         if (p)
336                 return TALLOC_MEMDUP(t, p, strlen(p) + 1);
337         else
338                 return NULL;
339 }
340
341 /** strdup_upper with a talloc */
342 char *talloc_strdup_upper(TALLOC_CTX *t, const char *p)
343 {
344         char *r;
345         if (p) {
346                 char *q = strdup_upper(p);
347                 if (q) { 
348                         r = talloc_strdup(t, q);
349                         SAFE_FREE(q);
350                         return r;
351                 } else {
352                         return NULL;
353                 }
354         } else {
355                 return NULL;
356         }
357 }
358
359 /** strdup_w with a talloc */
360 smb_ucs2_t *talloc_strdup_w(TALLOC_CTX *t, const smb_ucs2_t *p)
361 {
362         if (p)
363                 return TALLOC_MEMDUP(t, p, (strlen_w(p) + 1) * sizeof(smb_ucs2_t));
364         else
365                 return NULL;
366 }
367
368 /**
369  * Perform string formatting, and return a pointer to newly allocated
370  * memory holding the result, inside a memory pool.
371  **/
372  char *talloc_asprintf(TALLOC_CTX *t, const char *fmt, ...)
373 {
374         va_list ap;
375         char *ret;
376
377         va_start(ap, fmt);
378         ret = talloc_vasprintf(t, fmt, ap);
379         va_end(ap);
380         return ret;
381 }
382
383
384  char *talloc_vasprintf(TALLOC_CTX *t, const char *fmt, va_list ap)
385 {       
386         int len;
387         char *ret;
388         va_list ap2;
389         
390         VA_COPY(ap2, ap);
391
392         len = vsnprintf(NULL, 0, fmt, ap2);
393
394         ret = TALLOC(t, len+1);
395         if (ret) {
396                 VA_COPY(ap2, ap);
397                 vsnprintf(ret, len+1, fmt, ap2);
398         }
399
400         return ret;
401 }
402
403
404 /**
405  * Realloc @p s to append the formatted result of @p fmt and return @p
406  * s, which may have moved.  Good for gradually accumulating output
407  * into a string buffer.
408  **/
409  char *talloc_asprintf_append(TALLOC_CTX *t, char *s,
410                               const char *fmt, ...)
411 {
412         va_list ap;
413
414         va_start(ap, fmt);
415         s = talloc_vasprintf_append(t, s, fmt, ap);
416         va_end(ap);
417         return s;
418 }
419
420
421
422 /**
423  * Realloc @p s to append the formatted result of @p fmt and @p ap,
424  * and return @p s, which may have moved.  Good for gradually
425  * accumulating output into a string buffer.
426  **/
427  char *talloc_vasprintf_append(TALLOC_CTX *t, char *s,
428                                const char *fmt, va_list ap)
429 {       
430         int len, s_len;
431         va_list ap2;
432
433         VA_COPY(ap2, ap);
434
435         s_len = strlen(s);
436         len = vsnprintf(NULL, 0, fmt, ap2);
437
438         s = TALLOC_REALLOC(t, s, s_len + len+1);
439         if (!s) return NULL;
440
441         VA_COPY(ap2, ap);
442
443         vsnprintf(s+s_len, len+1, fmt, ap2);
444
445         return s;
446 }
447
448
449 /**
450  * Return a human-readable description of all talloc memory usage.
451  * The result is allocated from @p t.
452  **/
453 char *talloc_describe_all(TALLOC_CTX *rt)
454 {
455         int n_pools = 0, total_chunks = 0;
456         size_t total_bytes = 0;
457         TALLOC_CTX *it;
458         char *s;
459
460         if (!rt) return NULL;
461
462         s = talloc_asprintf(rt, "global talloc allocations in pid: %u\n",
463                             (unsigned) sys_getpid());
464         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
465                                    "name", "chunks", "bytes");
466         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
467                                    "----------------------------------------",
468                                    "--------",
469                                    "--------"); 
470         
471         for (it = list_head; it; it = it->next_ctx) {
472                 size_t bytes;
473                 int n_chunks;
474                 fstring what;
475                 
476                 n_pools++;
477                 
478                 talloc_get_allocation(it, &bytes, &n_chunks);
479
480                 if (it->name)
481                         fstrcpy(what, it->name);
482                 else
483                         slprintf(what, sizeof(what), "@%p", it);
484                 
485                 s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n",
486                                            what,
487                                            (unsigned) n_chunks,
488                                            (unsigned) bytes);
489                 total_bytes += bytes;
490                 total_chunks += n_chunks;
491         }
492
493         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
494                                    "----------------------------------------",
495                                    "--------",
496                                    "--------"); 
497
498         s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n",
499                                    "TOTAL",
500                                    (unsigned) total_chunks, (unsigned) total_bytes);
501
502         return s;
503 }
504
505
506
507 /**
508  * Return an estimated memory usage for the specified pool.  This does
509  * not include memory used by the underlying malloc implementation.
510  **/
511 void talloc_get_allocation(TALLOC_CTX *t,
512                            size_t *total_bytes,
513                            int *n_chunks)
514 {
515         struct talloc_chunk *chunk;
516
517         if (t) {
518                 *total_bytes = 0;
519                 *n_chunks = 0;
520
521                 for (chunk = t->list; chunk; chunk = chunk->next) {
522                         n_chunks[0]++;
523                         *total_bytes += chunk->size;
524                 }
525         }
526 }
527
528
529 /** @} */