Changeset feb999f for libcfa/src
- Timestamp:
- Apr 12, 2024, 7:49:05 AM (7 months ago)
- Branches:
- master
- Children:
- b78c54f
- Parents:
- 6dd4091
- Location:
- libcfa/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
r6dd4091 rfeb999f 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 3 21:30:54202413 // Update Count : 16 1912 // Last Modified On : Sun Apr 7 21:54:29 2024 13 // Update Count : 1644 14 14 // 15 15 … … 114 114 115 115 116 // generic Bsearchl does not inline, so substitute with hand-coded binary-search.116 // CFA 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_ calls;192 unsigned int free_calls, free_null_0_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 { 234 struct RealHeader { // 4-byte word => 8-byte header, 8-byte word => 16-byte header 235 235 union { 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 }; 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 246 241 }; 242 size_t size; // allocation size in bytes 247 243 } real; // RealHeader 248 244 … … 261 257 262 258 struct CALIGN FreeHeader { 263 size_t blockSize CALIGN; // size of allocations on this list264 259 #ifdef OWNERSHIP 265 260 #ifdef RETURNSPIN … … 271 266 Storage * freeList; // thread free list 272 267 Heap * homeManager; // heap owner (free storage to bucket, from bucket to heap) 268 size_t blockSize; // size of allocations on this list 273 269 }; // FreeHeader 274 270 … … 369 365 static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing 370 366 static __thread Heap * heapManager CALIGN TLSMODEL; 371 static 367 static __thread bool heapManagerBootFlag CALIGN TLSMODEL = false; 372 368 static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing 373 369 … … 595 591 596 592 #ifdef __STATISTICS__ 597 static HeapStatistics stats; // zero filled598 599 593 #define prtFmt \ 600 594 "\nHeap statistics: (storage request / allocation)\n" \ … … 607 601 " resize >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \ 608 602 " realloc >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \ 609 " free !null calls %'u; null calls %'u; storage %'llu / %'llu bytes\n" \603 " free !null calls %'u; null/0 calls %'u; storage %'llu / %'llu bytes\n" \ 610 604 " return pulls %'u; pushes %'u; storage %'llu / %'llu bytes\n" \ 611 605 " sbrk calls %'u; storage %'llu bytes\n" \ … … 627 621 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc, 628 622 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc, 629 free_calls, free_null_ calls, free_storage_request, free_storage_alloc,623 free_calls, free_null_0_calls, free_storage_request, free_storage_alloc, 630 624 return_pulls, return_pushes, return_storage_request, return_storage_alloc, 631 625 sbrk_calls, sbrk_storage, … … 650 644 "<total type=\"resize\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 651 645 "<total type=\"realloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 652 "<total type=\"free\" !null=\"%'u;\" 0 null =\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \646 "<total type=\"free\" !null=\"%'u;\" 0 null/0=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 653 647 "<total type=\"return\" pulls=\"%'u;\" 0 pushes=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \ 654 648 "<total type=\"sbrk\" count=\"%'u;\" size=\"%'llu\"/> bytes\n" \ … … 670 664 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc, 671 665 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc, 672 free_calls, free_null_ calls, free_storage_request, free_storage_alloc,666 free_calls, free_null_0_calls, free_storage_request, free_storage_alloc, 673 667 return_pulls, return_pushes, return_storage_request, return_storage_alloc, 674 668 sbrk_calls, sbrk_storage, … … 799 793 } else { 800 794 fakeHeader( header, alignment ); 801 if ( unlikely( MmappedBit( header ) ) ) { // mmapped ?795 if ( unlikely( MmappedBit( header ) ) ) { // mmapped storage ? 802 796 verify( addr < heapBegin || heapEnd < addr ); 803 797 size = ClearStickyBits( header->kind.real.blockSize ); // mmap size 798 freeHead = 0p; // prevent uninitialized warning 804 799 return true; 805 800 } // if … … 904 899 905 900 906 #define BOOT_HEAP_MANAGER \907 if ( unlikely( ! heapMasterBootFlag ) ) { \908 heapManagerCtor(); /* trigger for first heap */ \909 } /* if */910 911 901 #ifdef __STATISTICS__ 912 902 #define STAT_NAME __counter 913 903 #define STAT_PARM , unsigned int STAT_NAME 914 904 #define STAT_ARG( name ) , name 915 #define STAT_0_CNT( counter ) stats.counters[counter].calls_0 += 1905 #define STAT_0_CNT( counter ) heapManager->stats.counters[counter].calls_0 += 1 916 906 #else 917 907 #define STAT_NAME … … 921 911 #endif // __STATISTICS__ 922 912 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 */ 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 STAT_0_CNT( counter ); \ 924 __VA_ARGS__; /* call routine, if specified */ \ 925 return 0p; \ 926 } /* if */ 927 927 #else 928 #define __NULL_0_ALLOC__ 928 #define __NULL_0_ALLOC__( counter, ... ) 929 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__ 930 940 931 941 #define PROLOG( counter, ... ) \ 932 942 BOOT_HEAP_MANAGER; \ 933 if ( \ 934 __NULL_0_ALLOC__ \ 935 unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \ 936 STAT_0_CNT( counter ); \ 937 __VA_ARGS__; \ 938 return 0p; \ 939 } /* if */ 940 943 __NULL_0_ALLOC__( counter, __VA_ARGS__ ) \ 944 __OVERFLOW_MALLOC__( __VA_ARGS__ ) 941 945 942 946 #define SCRUB_SIZE 1024lu … … 948 952 PROLOG( STAT_NAME ); 949 953 950 verify( heapManager );951 954 Heap.Storage * block; // pointer to new block of storage 952 955 … … 956 959 957 960 #ifdef __STATISTICS__ 958 stats.counters[STAT_NAME].calls += 1; 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; 959 967 stats.counters[STAT_NAME].request += size; 960 968 #endif // __STATISTICS__ … … 1078 1086 1079 1087 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 1080 1092 verify( addr ); 1081 1093 … … 1091 1103 #endif // __STATISTICS__ || __CFA_DEBUG__ 1092 1104 1105 // Do not move these down because heap can be null! 1093 1106 #ifdef __STATISTICS__ 1107 #ifdef __NONNULL_0_ALLOC__ 1108 if ( unlikely( rsize == 0 ) ) // malloc( 0 ) ? 1109 stats.free_null_0_calls += 1; 1110 else 1111 #endif // __NONNULL_0_ALLOC__ 1112 heapManager->stats.free_calls += 1; // count free amd implicit frees from resize/realloc 1094 1113 stats.free_storage_request += rsize; 1095 1114 stats.free_storage_alloc += size; … … 1117 1136 } // if 1118 1137 } else { 1138 assert( freeHead ); 1119 1139 #ifdef __CFA_DEBUG__ 1120 1140 // memset is NOT always inlined! … … 1321 1341 // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done. 1322 1342 void * resize( void * oaddr, size_t size ) libcfa_public { 1323 if ( unlikely( oaddr == 0p ) ) { // => malloc( size )1343 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1324 1344 return doMalloc( size STAT_ARG( RESIZE ) ); 1325 1345 } // if … … 1333 1353 1334 1354 size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket 1335 // same size, DO NOT preserveSTICKY PROPERTIES.1355 // same size, DO NOT PRESERVE STICKY PROPERTIES. 1336 1356 if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 1337 1357 ClearZeroFillBit( header ); // no alignment and turn off 0 fill … … 1346 1366 } // if 1347 1367 1348 // change size, DO NOT preserveSTICKY PROPERTIES.1368 // change size, DO NOT PRESERVE STICKY PROPERTIES. 1349 1369 doFree( oaddr ); // free previous storage 1350 1370 … … 1356 1376 // the old and new sizes. 1357 1377 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 ); 1358 1381 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1359 1382 return doMalloc( size STAT_ARG( REALLOC ) ); … … 1498 1521 } // if 1499 1522 1500 #ifdef __STATISTICS__1501 incCalls( FREE );1502 #endif // __STATISTICS__1503 1504 1523 doFree( addr ); // handles heapManager == nullptr 1505 1524 } // free … … 1579 1598 #endif // __STATISTICS__ 1580 1599 } // malloc_stats_clear 1581 1582 1600 1583 1601 // Changes the file descriptor where malloc_stats() writes statistics. … … 1700 1718 } // if 1701 1719 1702 // change size, DO NOT preserveSTICKY PROPERTIES.1720 // change size, DO NOT PRESERVE STICKY PROPERTIES. 1703 1721 doFree( oaddr ); // free previous storage 1704 1722 return memalignNoStats( nalign, size STAT_ARG( RESIZE ) ); // create new aligned area … … 1707 1725 1708 1726 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 ); 1709 1730 if ( unlikely( oaddr == 0p ) ) { // => malloc( size ) 1710 1731 return memalignNoStats( nalign, size STAT_ARG( REALLOC ) ); -
libcfa/src/heap.hfa
r6dd4091 rfeb999f 10 10 // Created On : Tue May 26 11:23:55 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 11 11:18:18 202313 // Update Count : 2 412 // Last Modified On : Mon Apr 1 09:36:20 2024 13 // Update Count : 25 14 14 // 15 15 … … 46 46 } // extern "C" 47 47 48 // New allocation operations. 48 49 void * resize( void * oaddr, size_t alignment, size_t size ); 49 50 void * realloc( void * oaddr, size_t alignment, size_t size ); … … 51 52 52 53 // Local Variables: // 53 // mode: c //54 54 // tab-width: 4 // 55 55 // End: //
Note: See TracChangeset
for help on using the changeset viewer.