Changeset 740 for vendor/current/lib/talloc/talloc.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified vendor/current/lib/talloc/talloc.c ¶
r414 r740 46 46 #endif 47 47 48 /* Special macros that are no-ops except when run under Valgrind on 49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */ 50 #ifdef HAVE_VALGRIND_MEMCHECK_H 51 /* memcheck.h includes valgrind.h */ 52 #include <valgrind/memcheck.h> 53 #elif defined(HAVE_VALGRIND_H) 54 #include <valgrind.h> 55 #endif 56 48 57 /* use this to force every realloc to change the pointer, to stress test 49 58 code that might not cope */ … … 104 113 static void *null_context; 105 114 static void *autofree_context; 115 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 118 */ 119 static struct { 120 bool initialised; 121 bool enabled; 122 uint8_t fill_value; 123 } talloc_fill; 124 125 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL" 126 127 /* 128 * do not wipe the header, to allow the 129 * double-free logic to still work 130 */ 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); \ 136 } \ 137 } while (0) 138 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); \ 145 } while(0) 146 #else 147 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0) 148 #endif 149 150 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \ 151 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \ 152 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \ 153 } while (0) 154 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); \ 161 } \ 162 } while (0) 163 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); \ 171 } while (0) 172 #else 173 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 174 #endif 175 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); \ 179 } while (0) 180 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); \ 187 } \ 188 } while (0) 189 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); \ 197 } while (0) 198 #else 199 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 200 #endif 201 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); \ 205 } while (0) 206 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); \ 215 } while (0) 216 #else 217 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) 218 #endif 219 220 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \ 221 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \ 222 } while (0) 106 223 107 224 struct talloc_reference_handle { … … 137 254 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)) 141 259 142 int talloc_version_major(void)260 _PUBLIC_ int talloc_version_major(void) 143 261 { 144 262 return TALLOC_VERSION_MAJOR; 145 263 } 146 264 147 int talloc_version_minor(void)265 _PUBLIC_ int talloc_version_minor(void) 148 266 { 149 267 return TALLOC_VERSION_MINOR; … … 152 270 static void (*talloc_log_fn)(const char *message); 153 271 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)) 155 273 { 156 274 talloc_log_fn = log_fn; … … 180 298 } 181 299 182 void talloc_set_log_stderr(void)300 _PUBLIC_ void talloc_set_log_stderr(void) 183 301 { 184 302 talloc_set_log_fn(talloc_log_stderr); … … 187 305 static void (*talloc_abort_fn)(const char *reason); 188 306 189 void talloc_set_abort_fn(void (*abort_fn)(const char *reason))307 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) 190 308 { 191 309 talloc_abort_fn = abort_fn; … … 214 332 } 215 333 216 static void talloc_abort_ double_free(void)217 { 218 talloc_abort("Bad talloc magic value - doublefree");334 static void talloc_abort_access_after_free(void) 335 { 336 talloc_abort("Bad talloc magic value - access after free"); 219 337 } 220 338 … … 236 354 237 355 if (tc->flags & TALLOC_FLAG_FREE) { 238 talloc_log("talloc: doublefree error - first free may be at %s\n", tc->name);239 talloc_abort_ double_free();356 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name); 357 talloc_abort_access_after_free(); 240 358 return NULL; 241 359 } else { … … 292 410 } 293 411 294 void *talloc_parent(const void *ptr)412 _PUBLIC_ void *talloc_parent(const void *ptr) 295 413 { 296 414 struct talloc_chunk *tc = talloc_parent_chunk(ptr); … … 301 419 find parents name 302 420 */ 303 const char *talloc_parent_name(const void *ptr)421 _PUBLIC_ const char *talloc_parent_name(const void *ptr) 304 422 { 305 423 struct talloc_chunk *tc = talloc_parent_chunk(ptr); … … 322 440 #define TALLOC_POOL_HDR_SIZE 16 323 441 442 #define TC_POOL_SPACE_LEFT(_pool_tc) \ 443 PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \ 444 (_pool_tc)->pool) 445 446 #define TC_POOL_FIRST_CHUNK(_pool_tc) \ 447 ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc))) 448 449 #define TC_POOLMEM_CHUNK_SIZE(_tc) \ 450 TC_ALIGN16(TC_HDR_SIZE + (_tc)->size) 451 452 #define TC_POOLMEM_NEXT_CHUNK(_tc) \ 453 ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc))) 454 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); \ 461 } \ 462 } while(0) 463 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); \ 470 } while(0) 471 #else 472 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0) 473 #endif 474 475 #define TC_INVALIDATE_POOL(_pool_tc) do { \ 476 TC_INVALIDATE_FILL_POOL(_pool_tc); \ 477 TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \ 478 } while (0) 479 324 480 static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) 325 481 { 326 return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));482 return (unsigned int *)((char *)tc + TC_HDR_SIZE); 327 483 } 328 484 … … 354 510 } 355 511 356 space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) 357 - ((char *)pool_ctx->pool); 512 space_left = TC_POOL_SPACE_LEFT(pool_ctx); 358 513 359 514 /* 360 515 * Align size to 16 bytes 361 516 */ 362 chunk_size = ((size + 15) & ~15);517 chunk_size = TC_ALIGN16(size); 363 518 364 519 if (space_left < chunk_size) { … … 439 594 */ 440 595 441 void *talloc_pool(const void *context, size_t size)596 _PUBLIC_ void *talloc_pool(const void *context, size_t size) 442 597 { 443 598 void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); … … 451 606 452 607 tc->flags |= TALLOC_FLAG_POOL; 453 tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;608 tc->pool = TC_POOL_FIRST_CHUNK(tc); 454 609 455 610 *talloc_pool_objectcount(tc) = 1; 456 611 457 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) 458 VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); 459 #endif 612 TC_INVALIDATE_POOL(tc); 460 613 461 614 return result; … … 468 621 be continued to be used 469 622 */ 470 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))623 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) 471 624 { 472 625 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 477 630 increase the reference count on a piece of memory. 478 631 */ 479 int talloc_increase_ref_count(const void *ptr)632 _PUBLIC_ int talloc_increase_ref_count(const void *ptr) 480 633 { 481 634 if (unlikely(!talloc_reference(null_context, ptr))) { … … 533 686 and in either order 534 687 */ 535 void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)688 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) 536 689 { 537 690 struct talloc_chunk *tc; … … 557 710 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); 558 711 712 static inline void _talloc_free_poolmem(struct talloc_chunk *tc, 713 const char *location) 714 { 715 struct talloc_chunk *pool; 716 void *next_tc; 717 unsigned int *pool_object_count; 718 719 pool = (struct talloc_chunk *)tc->pool; 720 next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 721 722 tc->flags |= TALLOC_FLAG_FREE; 723 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 727 */ 728 tc->name = location; 729 730 TC_INVALIDATE_FULL_CHUNK(tc); 731 732 pool_object_count = talloc_pool_objectcount(pool); 733 734 if (unlikely(*pool_object_count == 0)) { 735 talloc_abort("Pool object count zero!"); 736 return; 737 } 738 739 *pool_object_count -= 1; 740 741 if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) { 742 /* 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 747 * again. 748 */ 749 pool->pool = TC_POOL_FIRST_CHUNK(pool); 750 TC_INVALIDATE_POOL(pool); 751 } else if (unlikely(*pool_object_count == 0)) { 752 /* 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 756 */ 757 pool->name = location; 758 759 TC_INVALIDATE_FULL_CHUNK(pool); 760 free(pool); 761 } else if (pool->pool == next_tc) { 762 /* 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'. 766 */ 767 pool->pool = tc; 768 } 769 } 770 771 static inline void _talloc_free_children_internal(struct talloc_chunk *tc, 772 void *ptr, 773 const char *location); 774 559 775 /* 560 776 internal talloc_free call … … 568 784 } 569 785 786 /* possibly initialised the talloc fill value */ 787 if (unlikely(!talloc_fill.initialised)) { 788 const char *fill = getenv(TALLOC_FILL_ENV); 789 if (fill != NULL) { 790 talloc_fill.enabled = true; 791 talloc_fill.fill_value = strtoul(fill, NULL, 0); 792 } 793 talloc_fill.initialised = true; 794 } 795 570 796 tc = talloc_chunk_from_ptr(ptr); 571 797 572 798 if (unlikely(tc->refs)) { 573 799 int is_child; 574 /* check this is a reference from a child or grantchild575 * back to it's parent or grantparent800 /* check if this is a reference from a child or 801 * grandchild back to it's parent or grandparent 576 802 * 577 803 * in that case we need to remove the reference and … … 617 843 tc->flags |= TALLOC_FLAG_LOOP; 618 844 619 while (tc->child) { 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); 630 } 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); 635 } 636 _talloc_steal_internal(new_parent, child); 637 } 638 } 845 _talloc_free_children_internal(tc, ptr, location); 639 846 640 847 tc->flags |= TALLOC_FLAG_FREE; … … 646 853 tc->name = location; 647 854 648 if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { 649 struct talloc_chunk *pool; 855 if (tc->flags & TALLOC_FLAG_POOL) { 650 856 unsigned int *pool_object_count; 651 857 652 pool = (tc->flags & TALLOC_FLAG_POOL) 653 ? tc : (struct talloc_chunk *)tc->pool; 654 655 pool_object_count = talloc_pool_objectcount(pool); 656 657 if (*pool_object_count == 0) { 858 pool_object_count = talloc_pool_objectcount(tc); 859 860 if (unlikely(*pool_object_count == 0)) { 658 861 talloc_abort("Pool object count zero!"); 659 862 return 0; … … 662 865 *pool_object_count -= 1; 663 866 664 if (*pool_object_count == 0) { 665 free(pool); 666 } 667 } 668 else { 867 if (unlikely(*pool_object_count == 0)) { 868 TC_INVALIDATE_FULL_CHUNK(tc); 869 free(tc); 870 } 871 } else if (tc->flags & TALLOC_FLAG_POOLMEM) { 872 _talloc_free_poolmem(tc, location); 873 } else { 874 TC_INVALIDATE_FULL_CHUNK(tc); 669 875 free(tc); 670 876 } … … 734 940 passing NULL as ptr will always return NULL with no side effects. 735 941 */ 736 void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)942 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) 737 943 { 738 944 struct talloc_chunk *tc; … … 755 961 } 756 962 } 963 964 #if 0 965 /* this test is probably too expensive to have on in the 966 normal build, but it useful for debugging */ 967 if (talloc_is_parent(new_ctx, ptr)) { 968 talloc_log("WARNING: stealing into talloc child at %s\n", location); 969 } 970 #endif 757 971 758 972 return _talloc_steal_internal(new_ctx, ptr); … … 766 980 The old parent can be either a reference or a parent 767 981 */ 768 void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)982 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) 769 983 { 770 984 struct talloc_chunk *tc; … … 826 1040 controlled varient of talloc_free() 827 1041 */ 828 int talloc_unlink(const void *context, void *ptr)1042 _PUBLIC_ int talloc_unlink(const void *context, void *ptr) 829 1043 { 830 1044 struct talloc_chunk *tc_p, *new_p; … … 893 1107 add a name to an existing pointer 894 1108 */ 895 const char *talloc_set_name(const void *ptr, const char *fmt, ...)1109 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...) 896 1110 { 897 1111 const char *name; … … 909 1123 to name the pointer. 910 1124 */ 911 void *talloc_named(const void *context, size_t size, const char *fmt, ...)1125 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...) 912 1126 { 913 1127 va_list ap; … … 933 1147 return the name of a talloc ptr, or "UNNAMED" 934 1148 */ 935 const char *talloc_get_name(const void *ptr)1149 _PUBLIC_ const char *talloc_get_name(const void *ptr) 936 1150 { 937 1151 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 950 1164 otherwise return NULL 951 1165 */ 952 void *talloc_check_name(const void *ptr, const char *name)1166 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name) 953 1167 { 954 1168 const char *pname; … … 979 1193 } 980 1194 981 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)1195 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) 982 1196 { 983 1197 const char *pname; … … 1000 1214 this is for compatibility with older versions of talloc 1001 1215 */ 1002 void *talloc_init(const char *fmt, ...)1216 _PUBLIC_ void *talloc_init(const char *fmt, ...) 1003 1217 { 1004 1218 va_list ap; … … 1006 1220 const char *name; 1007 1221 1008 /*1009 * samba3 expects talloc_report_depth_cb(NULL, ...)1010 * reports all talloc'ed memory, so we need to enable1011 * null_tracking1012 */1013 talloc_enable_null_tracking();1014 1015 1222 ptr = __talloc(NULL, 0); 1016 1223 if (unlikely(ptr == NULL)) return NULL; … … 1028 1235 } 1029 1236 1030 /* 1031 this is a replacement for the Samba3 talloc_destroy_pool functionality. It 1032 should probably not be used in new code. It's in here to keep the talloc 1033 code consistent across Samba 3 and 4. 1034 */ 1035 void talloc_free_children(void *ptr) 1036 { 1037 struct talloc_chunk *tc; 1038 1039 if (unlikely(ptr == NULL)) { 1040 return; 1041 } 1042 1043 tc = talloc_chunk_from_ptr(ptr); 1044 1237 static inline void _talloc_free_children_internal(struct talloc_chunk *tc, 1238 void *ptr, 1239 const char *location) 1240 { 1045 1241 while (tc->child) { 1046 1242 /* we need to work out who will own an abandoned child … … 1051 1247 void *child = TC_PTR_FROM_CHUNK(tc->child); 1052 1248 const void *new_parent = null_context; 1249 struct talloc_chunk *old_parent = NULL; 1053 1250 if (unlikely(tc->child->refs)) { 1054 1251 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); 1055 1252 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 1056 1253 } 1057 if (unlikely(talloc_free(child) == -1)) { 1254 /* finding the parent here is potentially quite 1255 expensive, but the alternative, which is to change 1256 talloc to always have a valid tc->parent pointer, 1257 makes realloc more expensive where there are a 1258 large number of children. 1259 1260 The reason we need the parent pointer here is that 1261 if _talloc_free_internal() fails due to references 1262 or a failing destructor we need to re-parent, but 1263 the free call can invalidate the prev pointer. 1264 */ 1265 if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) { 1266 old_parent = talloc_parent_chunk(ptr); 1267 } 1268 if (unlikely(_talloc_free_internal(child, location) == -1)) { 1058 1269 if (new_parent == null_context) { 1059 struct talloc_chunk *p = talloc_parent_chunk(ptr);1270 struct talloc_chunk *p = old_parent; 1060 1271 if (p) new_parent = TC_PTR_FROM_CHUNK(p); 1061 1272 } … … 1063 1274 } 1064 1275 } 1065 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); 1072 #endif 1073 } 1276 } 1277 1278 /* 1279 this is a replacement for the Samba3 talloc_destroy_pool functionality. It 1280 should probably not be used in new code. It's in here to keep the talloc 1281 code consistent across Samba 3 and 4. 1282 */ 1283 _PUBLIC_ void talloc_free_children(void *ptr) 1284 { 1285 struct talloc_chunk *tc; 1286 1287 if (unlikely(ptr == NULL)) { 1288 return; 1289 } 1290 1291 tc = talloc_chunk_from_ptr(ptr); 1292 1293 _talloc_free_children_internal(tc, ptr, __location__); 1074 1294 } 1075 1295 … … 1077 1297 Allocate a bit of memory as a child of an existing pointer 1078 1298 */ 1079 void *_talloc(const void *context, size_t size)1299 _PUBLIC_ void *_talloc(const void *context, size_t size) 1080 1300 { 1081 1301 return __talloc(context, size); … … 1085 1305 externally callable talloc_set_name_const() 1086 1306 */ 1087 void talloc_set_name_const(const void *ptr, const char *name)1307 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name) 1088 1308 { 1089 1309 _talloc_set_name_const(ptr, name); … … 1095 1315 to name the pointer. 1096 1316 */ 1097 void *talloc_named_const(const void *context, size_t size, const char *name)1317 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name) 1098 1318 { 1099 1319 return _talloc_named_const(context, size, name); … … 1108 1328 any) returns non-zero 1109 1329 */ 1110 int _talloc_free(void *ptr, const char *location)1330 _PUBLIC_ int _talloc_free(void *ptr, const char *location) 1111 1331 { 1112 1332 struct talloc_chunk *tc; … … 1121 1341 struct talloc_reference_handle *h; 1122 1342 1343 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) { 1344 /* in this case we do know which parent should 1345 get this pointer, as there is really only 1346 one parent */ 1347 return talloc_unlink(null_context, ptr); 1348 } 1349 1123 1350 talloc_log("ERROR: talloc_free with references at %s\n", 1124 1351 location); … … 1140 1367 ptr is NULL 1141 1368 */ 1142 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)1369 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) 1143 1370 { 1144 1371 struct talloc_chunk *tc; 1145 1372 void *new_ptr; 1146 1373 bool malloced = false; 1374 struct talloc_chunk *pool_tc = NULL; 1147 1375 1148 1376 /* size zero is equivalent to free() */ … … 1173 1401 } 1174 1402 1403 /* don't let anybody try to realloc a talloc_pool */ 1404 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) { 1405 pool_tc = (struct talloc_chunk *)tc->pool; 1406 } 1407 1408 #if (ALWAYS_REALLOC == 0) 1175 1409 /* don't shrink if we have less than 1k to gain */ 1176 if ((size < tc->size) && ((tc->size - size) < 1024)) { 1177 tc->size = size; 1410 if (size < tc->size) { 1411 if (pool_tc) { 1412 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 1413 TC_INVALIDATE_SHRINK_CHUNK(tc, size); 1414 tc->size = size; 1415 if (next_tc == pool_tc->pool) { 1416 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); 1417 } 1418 return ptr; 1419 } else if ((tc->size - size) < 1024) { 1420 /* 1421 * if we call TC_INVALIDATE_SHRINK_CHUNK() here 1422 * we would need to call TC_UNDEFINE_GROW_CHUNK() 1423 * after each realloc call, which slows down 1424 * testing a lot :-(. 1425 * 1426 * That is why we only mark memory as undefined here. 1427 */ 1428 TC_UNDEFINE_SHRINK_CHUNK(tc, size); 1429 1430 /* do not shrink if we have less than 1k to gain */ 1431 tc->size = size; 1432 return ptr; 1433 } 1434 } else if (tc->size == size) { 1435 /* 1436 * do not change the pointer if it is exactly 1437 * the same size. 1438 */ 1178 1439 return ptr; 1179 1440 } 1441 #endif 1180 1442 1181 1443 /* by resetting magic we catch users of the old memory */ … … 1183 1445 1184 1446 #if ALWAYS_REALLOC 1185 new_ptr = malloc(size + TC_HDR_SIZE); 1186 if (new_ptr) { 1187 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); 1188 free(tc); 1189 } 1190 #else 1191 if (tc->flags & TALLOC_FLAG_POOLMEM) { 1192 1447 if (pool_tc) { 1193 1448 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); 1194 *talloc_pool_objectcount((struct talloc_chunk *) 1195 (tc->pool)) -= 1; 1449 *talloc_pool_objectcount(pool_tc) -= 1; 1196 1450 1197 1451 if (new_ptr == NULL) { … … 1202 1456 if (new_ptr) { 1203 1457 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); 1458 TC_INVALIDATE_FULL_CHUNK(tc); 1459 } 1460 } else { 1461 new_ptr = malloc(size + TC_HDR_SIZE); 1462 if (new_ptr) { 1463 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); 1464 free(tc); 1465 } 1466 } 1467 #else 1468 if (pool_tc) { 1469 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); 1470 size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc); 1471 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size); 1472 size_t space_needed; 1473 size_t space_left; 1474 unsigned int chunk_count = *talloc_pool_objectcount(pool_tc); 1475 1476 if (!(pool_tc->flags & TALLOC_FLAG_FREE)) { 1477 chunk_count -= 1; 1478 } 1479 1480 if (chunk_count == 1) { 1481 /* 1482 * optimize for the case where 'tc' is the only 1483 * chunk in the pool. 1484 */ 1485 space_needed = new_chunk_size; 1486 space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE; 1487 1488 if (space_left >= space_needed) { 1489 size_t old_used = TC_HDR_SIZE + tc->size; 1490 size_t new_used = TC_HDR_SIZE + size; 1491 pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc); 1492 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) 1493 /* 1494 * we need to prepare the memmove into 1495 * the unaccessable area. 1496 */ 1497 { 1498 size_t diff = PTR_DIFF(tc, pool_tc->pool); 1499 size_t flen = MIN(diff, old_used); 1500 char *fptr = (char *)pool_tc->pool; 1501 VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen); 1502 } 1503 #endif 1504 memmove(pool_tc->pool, tc, old_used); 1505 new_ptr = pool_tc->pool; 1506 1507 tc = (struct talloc_chunk *)new_ptr; 1508 TC_UNDEFINE_GROW_CHUNK(tc, size); 1509 1510 /* 1511 * first we do not align the pool pointer 1512 * because we want to invalidate the padding 1513 * too. 1514 */ 1515 pool_tc->pool = new_used + (char *)new_ptr; 1516 TC_INVALIDATE_POOL(pool_tc); 1517 1518 /* now the aligned pointer */ 1519 pool_tc->pool = new_chunk_size + (char *)new_ptr; 1520 goto got_new_ptr; 1521 } 1522 1523 next_tc = NULL; 1524 } 1525 1526 if (new_chunk_size == old_chunk_size) { 1527 TC_UNDEFINE_GROW_CHUNK(tc, size); 1528 tc->flags &= ~TALLOC_FLAG_FREE; 1529 tc->size = size; 1530 return ptr; 1531 } 1532 1533 if (next_tc == pool_tc->pool) { 1534 /* 1535 * optimize for the case where 'tc' is the last 1536 * chunk in the pool. 1537 */ 1538 space_needed = new_chunk_size - old_chunk_size; 1539 space_left = TC_POOL_SPACE_LEFT(pool_tc); 1540 1541 if (space_left >= space_needed) { 1542 TC_UNDEFINE_GROW_CHUNK(tc, size); 1543 tc->flags &= ~TALLOC_FLAG_FREE; 1544 tc->size = size; 1545 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); 1546 return ptr; 1547 } 1548 } 1549 1550 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); 1551 1552 if (new_ptr == NULL) { 1553 new_ptr = malloc(TC_HDR_SIZE+size); 1554 malloced = true; 1555 } 1556 1557 if (new_ptr) { 1558 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); 1559 1560 _talloc_free_poolmem(tc, __location__ "_talloc_realloc"); 1204 1561 } 1205 1562 } … … 1207 1564 new_ptr = realloc(tc, size + TC_HDR_SIZE); 1208 1565 } 1566 got_new_ptr: 1209 1567 #endif 1210 1568 if (unlikely(!new_ptr)) { … … 1242 1600 between two structures, and want the old pointer to be set to NULL 1243 1601 */ 1244 void *_talloc_move(const void *new_ctx, const void *_pptr)1602 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr) 1245 1603 { 1246 1604 const void **pptr = discard_const_p(const void *,_pptr); … … 1253 1611 return the total size of a talloc pool (subtree) 1254 1612 */ 1255 size_t talloc_total_size(const void *ptr)1613 _PUBLIC_ size_t talloc_total_size(const void *ptr) 1256 1614 { 1257 1615 size_t total = 0; … … 1288 1646 return the total number of blocks in a talloc pool (subtree) 1289 1647 */ 1290 size_t talloc_total_blocks(const void *ptr)1648 _PUBLIC_ size_t talloc_total_blocks(const void *ptr) 1291 1649 { 1292 1650 size_t total = 0; … … 1321 1679 return the number of external references to a pointer 1322 1680 */ 1323 size_t talloc_reference_count(const void *ptr)1681 _PUBLIC_ size_t talloc_reference_count(const void *ptr) 1324 1682 { 1325 1683 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); … … 1336 1694 report on memory usage by all children of a pointer, giving a full tree view 1337 1695 */ 1338 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,1696 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, 1339 1697 void (*callback)(const void *ptr, 1340 1698 int depth, int max_depth, … … 1420 1778 report on memory usage by all children of a pointer, giving a full tree view 1421 1779 */ 1422 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)1780 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) 1423 1781 { 1424 1782 if (f) { … … 1431 1789 report on memory usage by all children of a pointer, giving a full tree view 1432 1790 */ 1433 void talloc_report_full(const void *ptr, FILE *f)1791 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f) 1434 1792 { 1435 1793 talloc_report_depth_file(ptr, 0, -1, f); … … 1439 1797 report on memory usage by all children of a pointer 1440 1798 */ 1441 void talloc_report(const void *ptr, FILE *f)1799 _PUBLIC_ void talloc_report(const void *ptr, FILE *f) 1442 1800 { 1443 1801 talloc_report_depth_file(ptr, 0, 1, f); … … 1467 1825 enable tracking of the NULL context 1468 1826 */ 1469 void talloc_enable_null_tracking(void)1827 _PUBLIC_ void talloc_enable_null_tracking(void) 1470 1828 { 1471 1829 if (null_context == NULL) { … … 1481 1839 into the NULL context. This is needed for the talloc testsuite 1482 1840 */ 1483 void talloc_enable_null_tracking_no_autofree(void)1841 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void) 1484 1842 { 1485 1843 if (null_context == NULL) { … … 1491 1849 disable tracking of the NULL context 1492 1850 */ 1493 void talloc_disable_null_tracking(void)1851 _PUBLIC_ void talloc_disable_null_tracking(void) 1494 1852 { 1495 1853 if (null_context != NULL) { … … 1516 1874 enable leak reporting on exit 1517 1875 */ 1518 void talloc_enable_leak_report(void)1876 _PUBLIC_ void talloc_enable_leak_report(void) 1519 1877 { 1520 1878 talloc_enable_null_tracking(); … … 1525 1883 enable full leak reporting on exit 1526 1884 */ 1527 void talloc_enable_leak_report_full(void)1885 _PUBLIC_ void talloc_enable_leak_report_full(void) 1528 1886 { 1529 1887 talloc_enable_null_tracking(); … … 1534 1892 talloc and zero memory. 1535 1893 */ 1536 void *_talloc_zero(const void *ctx, size_t size, const char *name)1894 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name) 1537 1895 { 1538 1896 void *p = _talloc_named_const(ctx, size, name); … … 1548 1906 memdup with a talloc. 1549 1907 */ 1550 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)1908 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) 1551 1909 { 1552 1910 void *newp = _talloc_named_const(t, size, name); … … 1576 1934 strdup with a talloc 1577 1935 */ 1578 char *talloc_strdup(const void *t, const char *p)1936 _PUBLIC_ char *talloc_strdup(const void *t, const char *p) 1579 1937 { 1580 1938 if (unlikely(!p)) return NULL; … … 1585 1943 strndup with a talloc 1586 1944 */ 1587 char *talloc_strndup(const void *t, const char *p, size_t n)1945 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n) 1588 1946 { 1589 1947 if (unlikely(!p)) return NULL; … … 1610 1968 * Appends at the end of the string. 1611 1969 */ 1612 char *talloc_strdup_append(char *s, const char *a)1970 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a) 1613 1971 { 1614 1972 if (unlikely(!s)) { … … 1627 1985 * not the end of the string. 1628 1986 */ 1629 char *talloc_strdup_append_buffer(char *s, const char *a)1987 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a) 1630 1988 { 1631 1989 size_t slen; … … 1650 2008 * Appends at the end of the string. 1651 2009 */ 1652 char *talloc_strndup_append(char *s, const char *a, size_t n)2010 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n) 1653 2011 { 1654 2012 if (unlikely(!s)) { … … 1667 2025 * not the end of the string. 1668 2026 */ 1669 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)2027 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) 1670 2028 { 1671 2029 size_t slen; … … 1695 2053 #endif 1696 2054 1697 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)2055 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) 1698 2056 { 1699 2057 int len; … … 1726 2084 memory holding the result, inside a memory pool. 1727 2085 */ 1728 char *talloc_asprintf(const void *t, const char *fmt, ...)2086 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...) 1729 2087 { 1730 2088 va_list ap; … … 1779 2137 * of the string. 1780 2138 **/ 1781 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)2139 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) 1782 2140 { 1783 2141 if (unlikely(!s)) { … … 1793 2151 * end of the talloc'ed buffer, not the end of the string. 1794 2152 **/ 1795 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)2153 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) 1796 2154 { 1797 2155 size_t slen; … … 1814 2172 into a string buffer. 1815 2173 */ 1816 char *talloc_asprintf_append(char *s, const char *fmt, ...)2174 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...) 1817 2175 { 1818 2176 va_list ap; … … 1829 2187 into a buffer. 1830 2188 */ 1831 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)2189 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) 1832 2190 { 1833 2191 va_list ap; … … 1842 2200 alloc an array, checking for integer overflow in the array size 1843 2201 */ 1844 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)2202 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) 1845 2203 { 1846 2204 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1853 2211 alloc an zero array, checking for integer overflow in the array size 1854 2212 */ 1855 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)2213 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) 1856 2214 { 1857 2215 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1864 2222 realloc an array, checking for integer overflow in the array size 1865 2223 */ 1866 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)2224 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) 1867 2225 { 1868 2226 if (count >= MAX_TALLOC_SIZE/el_size) { … … 1877 2235 all the basic capabilities of an allocation library, which is why this is useful) 1878 2236 */ 1879 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)2237 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) 1880 2238 { 1881 2239 return _talloc_realloc(context, ptr, size, NULL); … … 1898 2256 this is useful for reducing the noise in leak reports 1899 2257 */ 1900 void *talloc_autofree_context(void)2258 _PUBLIC_ void *talloc_autofree_context(void) 1901 2259 { 1902 2260 if (autofree_context == NULL) { … … 1908 2266 } 1909 2267 1910 size_t talloc_get_size(const void *context)2268 _PUBLIC_ size_t talloc_get_size(const void *context) 1911 2269 { 1912 2270 struct talloc_chunk *tc; … … 1927 2285 find a parent of this context that has the given name, if any 1928 2286 */ 1929 void *talloc_find_parent_byname(const void *context, const char *name)2287 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name) 1930 2288 { 1931 2289 struct talloc_chunk *tc; … … 1951 2309 show the parentage of a context 1952 2310 */ 1953 void talloc_show_parents(const void *context, FILE *file)2311 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file) 1954 2312 { 1955 2313 struct talloc_chunk *tc; … … 1975 2333 return 1 if ptr is a parent of context 1976 2334 */ 1977 int talloc_is_parent(const void *context, const void *ptr)2335 static int _talloc_is_parent(const void *context, const void *ptr, int depth) 1978 2336 { 1979 2337 struct talloc_chunk *tc; … … 1984 2342 1985 2343 tc = talloc_chunk_from_ptr(context); 1986 while (tc ) {2344 while (tc && depth > 0) { 1987 2345 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; 1988 2346 while (tc && tc->prev) tc = tc->prev; 1989 2347 if (tc) { 1990 2348 tc = tc->parent; 2349 depth--; 1991 2350 } 1992 2351 } 1993 2352 return 0; 1994 2353 } 2354 2355 /* 2356 return 1 if ptr is a parent of context 2357 */ 2358 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr) 2359 { 2360 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH); 2361 }
Note:
See TracChangeset
for help on using the changeset viewer.