Changes in libcfa/src/heap.cfa [feb999f:be10079]
- File:
-
- 1 edited
-
libcfa/src/heap.cfa (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
rfeb999f rbe10079 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Apr 7 21:54:29202413 // Update Count : 16 4412 // Last Modified On : Wed Jan 3 21:30:54 2024 13 // Update Count : 1619 14 14 // 15 15 … … 114 114 115 115 116 // CFAgeneric Bsearchl does not inline, so substitute with hand-coded binary-search.116 // generic Bsearchl does not inline, so substitute with hand-coded binary-search. 117 117 inline __attribute__((always_inline)) 118 118 static size_t Bsearchl( unsigned int key, const unsigned int vals[], size_t dim ) { … … 190 190 unsigned int realloc_calls, realloc_0_calls; 191 191 unsigned long long int realloc_storage_request, realloc_storage_alloc; 192 unsigned int free_calls, free_null_ 0_calls;192 unsigned int free_calls, free_null_calls; 193 193 unsigned long long int free_storage_request, free_storage_alloc; 194 194 unsigned int return_pulls, return_pushes; … … 232 232 struct Header { // header 233 233 union Kind { 234 struct RealHeader { // 4-byte word => 8-byte header, 8-byte word => 16-byte header234 struct RealHeader { 235 235 union { 236 // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped 237 // FreeHeader * home; // allocated block points back to home locations (must overlay alignment) 238 void * home; // allocated block points back to home locations (must overlay alignment) 239 size_t blockSize; // size for munmap (must overlay alignment) 240 Storage * next; // freed block points to next freed block of same size 236 struct { // 4-byte word => 8-byte header, 8-byte word => 16-byte header 237 union { 238 // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped 239 // FreeHeader * home; // allocated block points back to home locations (must overlay alignment) 240 void * home; // allocated block points back to home locations (must overlay alignment) 241 size_t blockSize; // size for munmap (must overlay alignment) 242 Storage * next; // freed block points to next freed block of same size 243 }; 244 size_t size; // allocation size in bytes 245 }; 241 246 }; 242 size_t size; // allocation size in bytes243 247 } real; // RealHeader 244 248 … … 257 261 258 262 struct CALIGN FreeHeader { 263 size_t blockSize CALIGN; // size of allocations on this list 259 264 #ifdef OWNERSHIP 260 265 #ifdef RETURNSPIN … … 266 271 Storage * freeList; // thread free list 267 272 Heap * homeManager; // heap owner (free storage to bucket, from bucket to heap) 268 size_t blockSize; // size of allocations on this list269 273 }; // FreeHeader 270 274 … … 365 369 static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing 366 370 static __thread Heap * heapManager CALIGN TLSMODEL; 367 static __thread bool heapManagerBootFlag CALIGN TLSMODEL = false;371 static __thread bool heapManagerBootFlag CALIGN TLSMODEL = false; 368 372 static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing 369 373 … … 591 595 592 596 #ifdef __STATISTICS__ 597 static HeapStatistics stats; // zero filled 598 593 599 #define prtFmt \ 594 600 "\nHeap statistics: (storage request / allocation)\n" \ … … 601 607 " resize >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \ 602 608 " realloc >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \ 603 " free !null calls %'u; null /0calls %'u; storage %'llu / %'llu bytes\n" \609 " free !null calls %'u; null calls %'u; storage %'llu / %'llu bytes\n" \ 604 610 " return pulls %'u; pushes %'u; storage %'llu / %'llu bytes\n" \ 605 611 " sbrk calls %'u; storage %'llu bytes\n" \ … … 621 627 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc, 622 628 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc, 623 free_calls, free_null_ 0_calls, free_storage_request, free_storage_alloc,629 free_calls, free_null_calls, free_storage_request, free_storage_alloc, 624 630 return_pulls, return_pushes, return_storage_request, return_storage_alloc, 625 631 sbrk_calls, sbrk_storage, … … 644 650 "<total type=\"resize\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 645 651 "<total type=\"realloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 646 "<total type=\"free\" !null=\"%'u;\" 0 null /0=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \652 "<total type=\"free\" !null=\"%'u;\" 0 null=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 647 653 "<total type=\"return\" pulls=\"%'u;\" 0 pushes=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 648 654 "<total type=\"sbrk\" count=\"%'u;\" size=\"%'llu\"/> bytes\n" \ … … 664 670 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc, 665 671 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc, 666 free_calls, free_null_ 0_calls, free_storage_request, free_storage_alloc,672 free_calls, free_null_calls, free_storage_request, free_storage_alloc, 667 673 return_pulls, return_pushes, return_storage_request, return_storage_alloc, 668 674 sbrk_calls, sbrk_storage, … … 793 799 } else { 794 800 fakeHeader( header, alignment ); 795 if ( unlikely( MmappedBit( header ) ) ) { // mmapped storage?801 if ( unlikely( MmappedBit( header ) ) ) { // mmapped ? 796 802 verify( addr < heapBegin || heapEnd < addr ); 797 803 size = ClearStickyBits( header->kind.real.blockSize ); // mmap size 798 freeHead = 0p; // prevent uninitialized warning799 804 return true; 800 805 } // if … … 899 904 900 905 906 #define BOOT_HEAP_MANAGER \ 907 if ( unlikely( ! heapMasterBootFlag ) ) { \ 908 heapManagerCtor(); /* trigger for first heap */ \ 909 } /* if */ 910 901 911 #ifdef __STATISTICS__ 902 912 #define STAT_NAME __counter 903 913 #define STAT_PARM , unsigned int STAT_NAME 904 914 #define STAT_ARG( name ) , name 905 #define STAT_0_CNT( counter ) heapManager->stats.counters[counter].calls_0 += 1915 #define STAT_0_CNT( counter ) stats.counters[counter].calls_0 += 1 906 916 #else 907 917 #define STAT_NAME … … 911 921 #endif // __STATISTICS__ 912 922 913 #define BOOT_HEAP_MANAGER \ 914 if ( unlikely( ! heapMasterBootFlag ) ) { \ 915 heapManagerCtor(); /* trigger for first heap */ \ 916 } /* if */ \ 917 verify( heapManager ); 918 919 #define __NONNULL_0_ALLOC__ /* Uncomment to return non-null address for malloc( 0 ). */ 920 #ifndef __NONNULL_0_ALLOC__ 921 #define __NULL_0_ALLOC__( counter, ... ) /* 0 byte allocation returns null pointer */ \ 922 if ( unlikely( size == 0 ) ) { \ 923 // Uncomment to get allocation addresses for a 0-sized allocation rather than a null pointer. 924 //#define __NONNULL_0_ALLOC__ 925 #if ! defined( __NONNULL_0_ALLOC__ ) 926 #define __NULL_0_ALLOC__ unlikely( size == 0 ) || /* 0 BYTE ALLOCATION RETURNS NULL POINTER */ 927 #else 928 #define __NULL_0_ALLOC__ 929 #endif // __NONNULL_0_ALLOC__ 930 931 #define PROLOG( counter, ... ) \ 932 BOOT_HEAP_MANAGER; \ 933 if ( \ 934 __NULL_0_ALLOC__ \ 935 unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \ 923 936 STAT_0_CNT( counter ); \ 924 __VA_ARGS__; /* call routine, if specified */\937 __VA_ARGS__; \ 925 938 return 0p; \ 926 939 } /* if */ 927 #else 928 #define __NULL_0_ALLOC__( counter, ... ) 929 #endif // __NONNULL_0_ALLOC__ 930 931 #ifdef __DEBUG__ 932 #define __OVERFLOW_MALLOC__( ... ) \ 933 if ( unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \ 934 __VA_ARGS__; /* call routine, if specified */ \ 935 return 0p; \ 936 } /* if */ 937 #else 938 #define __OVERFLOW_MALLOC__( ... ) 939 #endif // __DEBUG__ 940 941 #define PROLOG( counter, ... ) \ 942 BOOT_HEAP_MANAGER; \ 943 __NULL_0_ALLOC__( counter, __VA_ARGS__ ) \ 944 __OVERFLOW_MALLOC__( __VA_ARGS__ ) 940 945 941 946 942 #define SCRUB_SIZE 1024lu … … 952 948 PROLOG( STAT_NAME ); 953 949 950 verify( heapManager ); 954 951 Heap.Storage * block; // pointer to new block of storage 955 952 … … 959 956 960 957 #ifdef __STATISTICS__ 961 #ifdef __NONNULL_0_ALLOC__ 962 if ( unlikely( size == 0 ) ) // malloc( 0 ) ? 963 stats.counters[STAT_NAME].calls_0 += 1; 964 else 965 #endif // __NONNULL_0_ALLOC__ 966 stats.counters[STAT_NAME].calls += 1; 958 stats.counters[STAT_NAME].calls += 1; 967 959 stats.counters[STAT_NAME].request += size; 968 960 #endif // __STATISTICS__ … … 1086 1078 1087 1079 static void doFree( void * addr ) libcfa_nopreempt with( *heapManager ) { 1088 // char buf[64];1089 // int len = sprintf( buf, "doFree addr %p\n", addr );1090 // write( 2, buf, len );1091 1092 1080 verify( addr ); 1093 1081 … … 1103 1091 #endif // __STATISTICS__ || __CFA_DEBUG__ 1104 1092 1105 // Do not move these down because heap can be null!1106 1093 #ifdef __STATISTICS__ 1107 #ifdef __NONNULL_0_ALLOC__1108 if ( unlikely( rsize == 0 ) ) // malloc( 0 ) ?1109 stats.free_null_0_calls += 1;1110 else1111 #endif // __NONNULL_0_ALLOC__1112 heapManager->stats.free_calls += 1; // count free amd implicit frees from resize/realloc1113 1094 stats.free_storage_request += rsize; 1114 1095 stats.free_storage_alloc += size; … … 1136 1117 } // if 1137 1118 } else { 1138 assert( freeHead );1139 1119 #ifdef __CFA_DEBUG__ 1140 1120 // memset is NOT always inlined! … … 1341 1321 // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done. 1342 1322 void * resize( void * oaddr, size_t size ) libcfa_public { 1343 if ( unlikely( oaddr == 0p ) ) { // => malloc( size )1323 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1344 1324 return doMalloc( size STAT_ARG( RESIZE ) ); 1345 1325 } // if … … 1353 1333 1354 1334 size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket 1355 // same size, DO NOT PRESERVESTICKY PROPERTIES.1335 // same size, DO NOT preserve STICKY PROPERTIES. 1356 1336 if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 1357 1337 ClearZeroFillBit( header ); // no alignment and turn off 0 fill … … 1366 1346 } // if 1367 1347 1368 // change size, DO NOT PRESERVESTICKY PROPERTIES.1348 // change size, DO NOT preserve STICKY PROPERTIES. 1369 1349 doFree( oaddr ); // free previous storage 1370 1350 … … 1376 1356 // the old and new sizes. 1377 1357 void * realloc( void * oaddr, size_t size ) libcfa_public { 1378 // char buf[64];1379 // int len = sprintf( buf, "realloc1 oaddr %p size %d\n", oaddr, size );1380 // write( 2, buf, len );1381 1358 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1382 1359 return doMalloc( size STAT_ARG( REALLOC ) ); … … 1521 1498 } // if 1522 1499 1500 #ifdef __STATISTICS__ 1501 incCalls( FREE ); 1502 #endif // __STATISTICS__ 1503 1523 1504 doFree( addr ); // handles heapManager == nullptr 1524 1505 } // free … … 1598 1579 #endif // __STATISTICS__ 1599 1580 } // malloc_stats_clear 1581 1600 1582 1601 1583 // Changes the file descriptor where malloc_stats() writes statistics. … … 1718 1700 } // if 1719 1701 1720 // change size, DO NOT PRESERVESTICKY PROPERTIES.1702 // change size, DO NOT preserve STICKY PROPERTIES. 1721 1703 doFree( oaddr ); // free previous storage 1722 1704 return memalignNoStats( nalign, size STAT_ARG( RESIZE ) ); // create new aligned area … … 1725 1707 1726 1708 void * realloc( void * oaddr, size_t nalign, size_t size ) libcfa_public { 1727 // char buf[64];1728 // int len = sprintf( buf, "realloc2 oaddr %p size %d\n", oaddr, size );1729 // write( 2, buf, len );1730 1709 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1731 1710 return memalignNoStats( nalign, size STAT_ARG( REALLOC ) );
Note:
See TracChangeset
for help on using the changeset viewer.