104
113
static void *null_context;
105
114
static void *autofree_context;
116
/* used to enable fill of memory on free, which can be useful for
117
* catching use after free errors when valgrind is too slow
125
#define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
128
* do not wipe the header, to allow the
129
* double-free logic to still work
131
#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
132
if (unlikely(talloc_fill.enabled)) { \
133
size_t _flen = (_tc)->size; \
134
char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
135
memset(_fptr, talloc_fill.fill_value, _flen); \
139
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
140
/* Mark the whole chunk as not accessable */
141
#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
142
size_t _flen = TC_HDR_SIZE + (_tc)->size; \
143
char *_fptr = (char *)(_tc); \
144
VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
147
#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
150
#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
151
TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
152
TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
155
#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
156
if (unlikely(talloc_fill.enabled)) { \
157
size_t _flen = (_tc)->size - (_new_size); \
158
char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
159
_fptr += (_new_size); \
160
memset(_fptr, talloc_fill.fill_value, _flen); \
164
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
165
/* Mark the unused bytes not accessable */
166
#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
167
size_t _flen = (_tc)->size - (_new_size); \
168
char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
169
_fptr += (_new_size); \
170
VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
173
#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
176
#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
177
TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
178
TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
181
#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
182
if (unlikely(talloc_fill.enabled)) { \
183
size_t _flen = (_tc)->size - (_new_size); \
184
char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
185
_fptr += (_new_size); \
186
memset(_fptr, talloc_fill.fill_value, _flen); \
190
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
191
/* Mark the unused bytes as undefined */
192
#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
193
size_t _flen = (_tc)->size - (_new_size); \
194
char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
195
_fptr += (_new_size); \
196
VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
199
#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
202
#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
203
TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
204
TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
207
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
208
/* Mark the new bytes as undefined */
209
#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
210
size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
211
size_t _new_used = TC_HDR_SIZE + (_new_size); \
212
size_t _flen = _new_used - _old_used; \
213
char *_fptr = _old_used + (char *)(_tc); \
214
VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
217
#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
220
#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
221
TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
107
224
struct talloc_reference_handle {
108
225
struct talloc_reference_handle *next, *prev;
138
255
/* 16 byte alignment seems to keep everyone happy */
139
#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
256
#define TC_ALIGN16(s) (((s)+15)&~15)
257
#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
140
258
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
142
int talloc_version_major(void)
260
_PUBLIC_ int talloc_version_major(void)
144
262
return TALLOC_VERSION_MAJOR;
147
int talloc_version_minor(void)
265
_PUBLIC_ int talloc_version_minor(void)
149
267
return TALLOC_VERSION_MINOR;
152
270
static void (*talloc_log_fn)(const char *message);
154
void talloc_set_log_fn(void (*log_fn)(const char *message))
272
_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
156
274
talloc_log_fn = log_fn;
322
440
#define TALLOC_POOL_HDR_SIZE 16
442
#define TC_POOL_SPACE_LEFT(_pool_tc) \
443
PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \
446
#define TC_POOL_FIRST_CHUNK(_pool_tc) \
447
((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc)))
449
#define TC_POOLMEM_CHUNK_SIZE(_tc) \
450
TC_ALIGN16(TC_HDR_SIZE + (_tc)->size)
452
#define TC_POOLMEM_NEXT_CHUNK(_tc) \
453
((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc)))
455
/* Mark the whole remaining pool as not accessable */
456
#define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \
457
if (unlikely(talloc_fill.enabled)) { \
458
size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
459
char *_fptr = (char *)(_pool_tc)->pool; \
460
memset(_fptr, talloc_fill.fill_value, _flen); \
464
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
465
/* Mark the whole remaining pool as not accessable */
466
#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \
467
size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
468
char *_fptr = (char *)(_pool_tc)->pool; \
469
VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
472
#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0)
475
#define TC_INVALIDATE_POOL(_pool_tc) do { \
476
TC_INVALIDATE_FILL_POOL(_pool_tc); \
477
TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \
324
480
static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
326
return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
482
return (unsigned int *)((char *)tc + TC_HDR_SIZE);
557
710
static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
712
static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
713
const char *location)
715
struct talloc_chunk *pool;
717
unsigned int *pool_object_count;
719
pool = (struct talloc_chunk *)tc->pool;
720
next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
722
tc->flags |= TALLOC_FLAG_FREE;
724
/* we mark the freed memory with where we called the free
725
* from. This means on a double free error we can report where
726
* the first free came from
730
TC_INVALIDATE_FULL_CHUNK(tc);
732
pool_object_count = talloc_pool_objectcount(pool);
734
if (unlikely(*pool_object_count == 0)) {
735
talloc_abort("Pool object count zero!");
739
*pool_object_count -= 1;
741
if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) {
743
* if there is just one object left in the pool
744
* and pool->flags does not have TALLOC_FLAG_FREE,
745
* it means this is the pool itself and
746
* the rest is available for new objects
749
pool->pool = TC_POOL_FIRST_CHUNK(pool);
750
TC_INVALIDATE_POOL(pool);
751
} else if (unlikely(*pool_object_count == 0)) {
753
* we mark the freed memory with where we called the free
754
* from. This means on a double free error we can report where
755
* the first free came from
757
pool->name = location;
759
TC_INVALIDATE_FULL_CHUNK(pool);
761
} else if (pool->pool == next_tc) {
763
* if pool->pool still points to end of
764
* 'tc' (which is stored in the 'next_tc' variable),
765
* we can reclaim the memory of 'tc'.
771
static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
773
const char *location);
560
776
internal talloc_free call
786
/* possibly initialised the talloc fill value */
787
if (unlikely(!talloc_fill.initialised)) {
788
const char *fill = getenv(TALLOC_FILL_ENV);
790
talloc_fill.enabled = true;
791
talloc_fill.fill_value = strtoul(fill, NULL, 0);
793
talloc_fill.initialised = true;
570
796
tc = talloc_chunk_from_ptr(ptr);
572
798
if (unlikely(tc->refs)) {
574
/* check this is a reference from a child or grantchild
575
* back to it's parent or grantparent
800
/* check if this is a reference from a child or
801
* grandchild back to it's parent or grandparent
577
803
* in that case we need to remove the reference and
578
804
* call another instance of talloc_free() on the current
613
839
if (tc->prev) tc->prev->next = tc->next;
614
840
if (tc->next) tc->next->prev = tc->prev;
841
tc->prev = tc->next = NULL;
617
844
tc->flags |= TALLOC_FLAG_LOOP;
620
/* we need to work out who will own an abandoned child
621
if it cannot be freed. In priority order, the first
622
choice is owner of any remaining reference to this
623
pointer, the second choice is our parent, and the
624
final choice is the null context. */
625
void *child = TC_PTR_FROM_CHUNK(tc->child);
626
const void *new_parent = null_context;
627
if (unlikely(tc->child->refs)) {
628
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
629
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
631
if (unlikely(_talloc_free_internal(child, location) == -1)) {
632
if (new_parent == null_context) {
633
struct talloc_chunk *p = talloc_parent_chunk(ptr);
634
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
636
_talloc_steal_internal(new_parent, child);
846
_talloc_free_children_internal(tc, ptr, location);
640
848
tc->flags |= TALLOC_FLAG_FREE;
646
854
tc->name = location;
648
if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
649
struct talloc_chunk *pool;
856
if (tc->flags & TALLOC_FLAG_POOL) {
650
857
unsigned int *pool_object_count;
652
pool = (tc->flags & TALLOC_FLAG_POOL)
653
? tc : (struct talloc_chunk *)tc->pool;
655
pool_object_count = talloc_pool_objectcount(pool);
657
if (*pool_object_count == 0) {
859
pool_object_count = talloc_pool_objectcount(tc);
861
if (unlikely(*pool_object_count == 0)) {
658
862
talloc_abort("Pool object count zero!");
662
866
*pool_object_count -= 1;
664
if (*pool_object_count == 0) {
868
if (unlikely(*pool_object_count == 0)) {
869
TC_INVALIDATE_FULL_CHUNK(tc);
872
} else if (tc->flags & TALLOC_FLAG_POOLMEM) {
873
_talloc_free_poolmem(tc, location);
875
TC_INVALIDATE_FULL_CHUNK(tc);
1239
static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1241
const char *location)
1244
/* we need to work out who will own an abandoned child
1245
if it cannot be freed. In priority order, the first
1246
choice is owner of any remaining reference to this
1247
pointer, the second choice is our parent, and the
1248
final choice is the null context. */
1249
void *child = TC_PTR_FROM_CHUNK(tc->child);
1250
const void *new_parent = null_context;
1251
struct talloc_chunk *old_parent = NULL;
1252
if (unlikely(tc->child->refs)) {
1253
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1254
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1256
if (unlikely(_talloc_free_internal(child, location) == -1)) {
1257
if (new_parent == null_context) {
1258
struct talloc_chunk *p = talloc_parent_chunk(ptr);
1259
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1261
_talloc_steal_internal(new_parent, child);
1031
1267
this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1032
1268
should probably not be used in new code. It's in here to keep the talloc
1033
1269
code consistent across Samba 3 and 4.
1035
void talloc_free_children(void *ptr)
1271
_PUBLIC_ void talloc_free_children(void *ptr)
1273
struct talloc_chunk *tc_name = NULL;
1037
1274
struct talloc_chunk *tc;
1039
1276
if (unlikely(ptr == NULL)) {
1043
1280
tc = talloc_chunk_from_ptr(ptr);
1046
/* we need to work out who will own an abandoned child
1047
if it cannot be freed. In priority order, the first
1048
choice is owner of any remaining reference to this
1049
pointer, the second choice is our parent, and the
1050
final choice is the null context. */
1051
void *child = TC_PTR_FROM_CHUNK(tc->child);
1052
const void *new_parent = null_context;
1053
if (unlikely(tc->child->refs)) {
1054
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1055
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1282
/* we do not want to free the context name if it is a child .. */
1283
if (likely(tc->child)) {
1284
for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1285
if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1057
if (unlikely(talloc_free(child) == -1)) {
1058
if (new_parent == null_context) {
1059
struct talloc_chunk *p = talloc_parent_chunk(ptr);
1060
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1288
_TLIST_REMOVE(tc->child, tc_name);
1290
tc->child->parent = tc;
1062
_talloc_steal_internal(new_parent, child);
1066
if ((tc->flags & TALLOC_FLAG_POOL)
1067
&& (*talloc_pool_objectcount(tc) == 1)) {
1068
tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
1069
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
1070
VALGRIND_MAKE_MEM_NOACCESS(
1071
tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
1295
_talloc_free_children_internal(tc, ptr, __location__);
1297
/* .. so we put it back after all other children have been freed */
1300
tc->child->parent = NULL;
1302
tc_name->parent = tc;
1303
_TLIST_ADD(tc->child, tc_name);
1077
1308
Allocate a bit of memory as a child of an existing pointer
1079
void *_talloc(const void *context, size_t size)
1310
_PUBLIC_ void *_talloc(const void *context, size_t size)
1081
1312
return __talloc(context, size);
1414
/* don't let anybody try to realloc a talloc_pool */
1415
if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1416
pool_tc = (struct talloc_chunk *)tc->pool;
1419
#if (ALWAYS_REALLOC == 0)
1175
1420
/* don't shrink if we have less than 1k to gain */
1176
if ((size < tc->size) && ((tc->size - size) < 1024)) {
1421
if (size < tc->size) {
1423
void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
1424
TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1426
if (next_tc == pool_tc->pool) {
1427
pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
1430
} else if ((tc->size - size) < 1024) {
1432
* if we call TC_INVALIDATE_SHRINK_CHUNK() here
1433
* we would need to call TC_UNDEFINE_GROW_CHUNK()
1434
* after each realloc call, which slows down
1435
* testing a lot :-(.
1437
* That is why we only mark memory as undefined here.
1439
TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1441
/* do not shrink if we have less than 1k to gain */
1445
} else if (tc->size == size) {
1447
* do not change the pointer if it is exactly
1181
1454
/* by resetting magic we catch users of the old memory */
1182
1455
tc->flags |= TALLOC_FLAG_FREE;
1184
1457
#if ALWAYS_REALLOC
1185
new_ptr = malloc(size + TC_HDR_SIZE);
1187
memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1459
new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1460
*talloc_pool_objectcount(pool_tc) -= 1;
1462
if (new_ptr == NULL) {
1463
new_ptr = malloc(TC_HDR_SIZE+size);
1468
memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1469
TC_INVALIDATE_FULL_CHUNK(tc);
1472
new_ptr = malloc(size + TC_HDR_SIZE);
1474
memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1191
if (tc->flags & TALLOC_FLAG_POOLMEM) {
1480
void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
1481
size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc);
1482
size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1483
size_t space_needed;
1485
unsigned int chunk_count = *talloc_pool_objectcount(pool_tc);
1487
if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
1491
if (chunk_count == 1) {
1493
* optimize for the case where 'tc' is the only
1494
* chunk in the pool.
1496
space_needed = new_chunk_size;
1497
space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE;
1499
if (space_left >= space_needed) {
1500
size_t old_used = TC_HDR_SIZE + tc->size;
1501
size_t new_used = TC_HDR_SIZE + size;
1502
pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc);
1503
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
1505
* we need to prepare the memmove into
1506
* the unaccessable area.
1509
size_t diff = PTR_DIFF(tc, pool_tc->pool);
1510
size_t flen = MIN(diff, old_used);
1511
char *fptr = (char *)pool_tc->pool;
1512
VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen);
1515
memmove(pool_tc->pool, tc, old_used);
1516
new_ptr = pool_tc->pool;
1518
tc = (struct talloc_chunk *)new_ptr;
1519
TC_UNDEFINE_GROW_CHUNK(tc, size);
1522
* first we do not align the pool pointer
1523
* because we want to invalidate the padding
1526
pool_tc->pool = new_used + (char *)new_ptr;
1527
TC_INVALIDATE_POOL(pool_tc);
1529
/* now the aligned pointer */
1530
pool_tc->pool = new_chunk_size + (char *)new_ptr;
1537
if (new_chunk_size == old_chunk_size) {
1538
TC_UNDEFINE_GROW_CHUNK(tc, size);
1539
tc->flags &= ~TALLOC_FLAG_FREE;
1544
if (next_tc == pool_tc->pool) {
1546
* optimize for the case where 'tc' is the last
1547
* chunk in the pool.
1549
space_needed = new_chunk_size - old_chunk_size;
1550
space_left = TC_POOL_SPACE_LEFT(pool_tc);
1552
if (space_left >= space_needed) {
1553
TC_UNDEFINE_GROW_CHUNK(tc, size);
1554
tc->flags &= ~TALLOC_FLAG_FREE;
1556
pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
1193
1561
new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1194
*talloc_pool_objectcount((struct talloc_chunk *)
1197
1563
if (new_ptr == NULL) {
1198
1564
new_ptr = malloc(TC_HDR_SIZE+size);