r6014: rather large change set....
[samba.git] / source3 / 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 /* strndup with a talloc */
342 char *talloc_strndup(TALLOC_CTX *mem_ctx, const char *str, size_t maxlen)
343 {
344         size_t len = strnlen(str, maxlen);
345         void *ret = TALLOC(mem_ctx, len+1);
346
347         if (ret != NULL) {
348                 memcpy(ret, str, len);
349                 ((char *)ret)[len] = '\0';
350         }
351         return ret;
352 }
353
354 /** strdup_upper with a talloc */
355 char *talloc_strdup_upper(TALLOC_CTX *t, const char *p)
356 {
357         char *r;
358         if (p) {
359                 char *q = strdup_upper(p);
360                 if (q) { 
361                         r = talloc_strdup(t, q);
362                         SAFE_FREE(q);
363                         return r;
364                 } else {
365                         return NULL;
366                 }
367         } else {
368                 return NULL;
369         }
370 }
371
372 /** strdup_w with a talloc */
373 smb_ucs2_t *talloc_strdup_w(TALLOC_CTX *t, const smb_ucs2_t *p)
374 {
375         if (p)
376                 return TALLOC_MEMDUP(t, p, (strlen_w(p) + 1) * sizeof(smb_ucs2_t));
377         else
378                 return NULL;
379 }
380
381 /**
382  * Perform string formatting, and return a pointer to newly allocated
383  * memory holding the result, inside a memory pool.
384  **/
385  char *talloc_asprintf(TALLOC_CTX *t, const char *fmt, ...)
386 {
387         va_list ap;
388         char *ret;
389
390         va_start(ap, fmt);
391         ret = talloc_vasprintf(t, fmt, ap);
392         va_end(ap);
393         return ret;
394 }
395
396
397  char *talloc_vasprintf(TALLOC_CTX *t, const char *fmt, va_list ap)
398 {       
399         int len;
400         char *ret;
401         va_list ap2;
402         
403         VA_COPY(ap2, ap);
404
405         len = vsnprintf(NULL, 0, fmt, ap2);
406
407         ret = TALLOC(t, len+1);
408         if (ret) {
409                 VA_COPY(ap2, ap);
410                 vsnprintf(ret, len+1, fmt, ap2);
411         }
412
413         return ret;
414 }
415
416
417 /**
418  * Realloc @p s to append the formatted result of @p fmt and return @p
419  * s, which may have moved.  Good for gradually accumulating output
420  * into a string buffer.
421  **/
422  char *talloc_asprintf_append(TALLOC_CTX *t, char *s,
423                               const char *fmt, ...)
424 {
425         va_list ap;
426
427         va_start(ap, fmt);
428         s = talloc_vasprintf_append(t, s, fmt, ap);
429         va_end(ap);
430         return s;
431 }
432
433
434
435 /**
436  * Realloc @p s to append the formatted result of @p fmt and @p ap,
437  * and return @p s, which may have moved.  Good for gradually
438  * accumulating output into a string buffer.
439  **/
440  char *talloc_vasprintf_append(TALLOC_CTX *t, char *s,
441                                const char *fmt, va_list ap)
442 {       
443         int len, s_len;
444         va_list ap2;
445
446         VA_COPY(ap2, ap);
447
448         s_len = strlen(s);
449         len = vsnprintf(NULL, 0, fmt, ap2);
450
451         s = TALLOC_REALLOC(t, s, s_len + len+1);
452         if (!s) return NULL;
453
454         VA_COPY(ap2, ap);
455
456         vsnprintf(s+s_len, len+1, fmt, ap2);
457
458         return s;
459 }
460
461
462 /**
463  * Return a human-readable description of all talloc memory usage.
464  * The result is allocated from @p t.
465  **/
466 char *talloc_describe_all(TALLOC_CTX *rt)
467 {
468         int n_pools = 0, total_chunks = 0;
469         size_t total_bytes = 0;
470         TALLOC_CTX *it;
471         char *s;
472
473         if (!rt) return NULL;
474
475         s = talloc_asprintf(rt, "global talloc allocations in pid: %u\n",
476                             (unsigned) sys_getpid());
477         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
478                                    "name", "chunks", "bytes");
479         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
480                                    "----------------------------------------",
481                                    "--------",
482                                    "--------"); 
483         
484         for (it = list_head; it; it = it->next_ctx) {
485                 size_t bytes;
486                 int n_chunks;
487                 fstring what;
488                 
489                 n_pools++;
490                 
491                 talloc_get_allocation(it, &bytes, &n_chunks);
492
493                 if (it->name)
494                         fstrcpy(what, it->name);
495                 else
496                         slprintf(what, sizeof(what), "@%p", it);
497                 
498                 s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n",
499                                            what,
500                                            (unsigned) n_chunks,
501                                            (unsigned) bytes);
502                 total_bytes += bytes;
503                 total_chunks += n_chunks;
504         }
505
506         s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n",
507                                    "----------------------------------------",
508                                    "--------",
509                                    "--------"); 
510
511         s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n",
512                                    "TOTAL",
513                                    (unsigned) total_chunks, (unsigned) total_bytes);
514
515         return s;
516 }
517
518
519
520 /**
521  * Return an estimated memory usage for the specified pool.  This does
522  * not include memory used by the underlying malloc implementation.
523  **/
524 void talloc_get_allocation(TALLOC_CTX *t,
525                            size_t *total_bytes,
526                            int *n_chunks)
527 {
528         struct talloc_chunk *chunk;
529
530         if (t) {
531                 *total_bytes = 0;
532                 *n_chunks = 0;
533
534                 for (chunk = t->list; chunk; chunk = chunk->next) {
535                         n_chunks[0]++;
536                         *total_bytes += chunk->size;
537                 }
538         }
539 }
540
541
542 /** @} */