Changeset 92aca37
- Timestamp:
- Aug 10, 2020, 2:54:06 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 5104893, e2702fd
- Parents:
- 53fd995
- Location:
- libcfa/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
r53fd995 r92aca37 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // heap.c --7 // heap.cfa -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 6 09:08:58202013 // Update Count : 8 6112 // Last Modified On : Sun Aug 9 12:23:20 2020 13 // Update Count : 894 14 14 // 15 15 … … 23 23 #include <sys/mman.h> // mmap, munmap 24 24 25 #include "bits/align.hfa" // lib Pow225 #include "bits/align.hfa" // libAlign 26 26 #include "bits/defs.hfa" // likely, unlikely 27 27 #include "bits/locks.hfa" // __spinlock_t … … 88 88 } // default_heap_expansion 89 89 90 bool default_heap_exhausted() __attribute__(( weak )) { // find and free some storage91 // Returning false prints "out of heap memory" message and aborts.92 return false;93 } // default_heap_exhausted94 95 90 96 91 #ifdef __CFA_DEBUG__ 97 static unsigned int allocUnfreed;// running total of allocations minus frees92 static size_t allocUnfreed; // running total of allocations minus frees 98 93 99 94 static void prtUnfreed() { … … 101 96 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 102 97 char helpText[512]; 103 int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with % u(0x%x) bytes of storage allocated but not freed.\n"98 int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n" 104 99 "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n", 105 100 (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid … … 292 287 static unsigned long long int sbrk_storage; 293 288 // Statistics file descriptor (changed by malloc_stats_fd). 294 static int stat fd = STDERR_FILENO; // default stderr289 static int stat_fd = STDERR_FILENO; // default stderr 295 290 296 291 // Use "write" because streams may be shutdown when calls are made. … … 312 307 " sbrk: calls %u / storage %llu\n", 313 308 malloc_calls, malloc_storage, 314 aalloc_calls, calloc_storage,309 aalloc_calls, aalloc_storage, 315 310 calloc_calls, calloc_storage, 316 311 memalign_calls, memalign_storage, … … 411 406 412 407 static inline void checkAlign( size_t alignment ) { 413 if ( alignment < libAlign() || ! libPow2( alignment ) ) {408 if ( alignment < libAlign() || ! is_pow2( alignment ) ) { 414 409 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() ); 415 410 } // if … … 443 438 header = headerAddr( addr ); 444 439 445 440 if ( unlikely( heapEnd < addr ) ) { // mmapped ? 446 441 fakeHeader( header, alignment ); 447 442 size = header->kind.real.blockSize & -3; // mmap size … … 471 466 } // headers 472 467 473 #define NO_MEMORY_MSG " noheap memory available for allocating %zd new bytes."468 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes." 474 469 475 470 static inline void * extend( size_t size ) with( heapManager ) { … … 479 474 // If the size requested is bigger than the current remaining storage, increase the size of the heap. 480 475 481 size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() ); 482 Succeed: 483 { 484 if ( sbrk( increase ) != (void *)-1 ) break Succeed; // succeed ? 485 if ( default_heap_exhausted() ) { // try fix 486 if ( sbrk( increase ) != (void *)-1 ) break Succeed; // succeed ? 487 } // if 476 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, libAlign() ); 477 if ( sbrk( increase ) == (void *)-1 ) { // failed, no memory ? 488 478 unlock( extlock ); 489 479 abort( NO_MEMORY_MSG, size ); // give up 490 } 480 } // if 491 481 #ifdef __STATISTICS__ 492 482 sbrk_calls += 1; … … 524 514 posn = Bsearchl( (unsigned int)tsize, bucketSizes, (size_t)maxBucketsUsed ); 525 515 HeapManager.FreeHeader * freeElem = &freeLists[posn]; 526 // #ifdef FASTLOOKUP527 // if ( tsize < LookupSizes )528 // freeElem = &freeLists[lookup[tsize]];529 // else530 // #endif // FASTLOOKUP531 // freeElem = bsearchl( tsize, freeLists, (size_t)maxBucketsUsed ); // binary search532 // HeapManager.FreeHeader * freeElem =533 // #ifdef FASTLOOKUP534 // tsize < LookupSizes ? &freeLists[lookup[tsize]] :535 // #endif // FASTLOOKUP536 // bsearchl( tsize, freeLists, (size_t)maxBucketsUsed ); // binary search537 516 verify( freeElem <= &freeLists[maxBucketsUsed] ); // subscripting error ? 538 517 verify( tsize <= freeElem->blockSize ); // search failure ? … … 566 545 } else { // large size => mmap 567 546 if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p; 568 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size547 tsize = ceiling2( tsize, pageSize ); // must be multiple of page size 569 548 #ifdef __STATISTICS__ 570 549 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); 571 550 __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST ); 572 551 #endif // __STATISTICS__ 573 Succeed: 574 { 575 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); 576 if ( block != (HeapManager.Storage *)MAP_FAILED ) break Succeed; // succeed ? 577 if ( errno == ENOMEM && default_heap_exhausted() ) { // out of memory and try again ? 578 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); 579 if ( block != (HeapManager.Storage *)MAP_FAILED ) break Succeed; // succeed ? 580 } // if 581 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); 552 553 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); 554 if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ? 555 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory 582 556 // Do not call strerror( errno ) as it may call malloc. 583 557 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno ); 584 } 558 } //if 585 559 #ifdef __CFA_DEBUG__ 586 560 // Set new memory to garbage so subsequent uninitialized usages might fail. … … 653 627 __atomic_add_fetch( &allocUnfreed, -size, __ATOMIC_SEQ_CST ); 654 628 if ( traceHeap() ) { 655 enum { BufferSize = 64 }; 656 char helpText[BufferSize]; 629 char helpText[64]; 657 630 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size ); 658 631 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug … … 677 650 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) { 678 651 #else 679 for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) { 680 typeof(p) temp = ( p )`next->top; // FIX ME: direct assignent fails, initialization works 681 p = temp; 652 for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) { 682 653 #endif // BUCKETLOCK 683 654 total += size; … … 721 692 722 693 char * end = (char *)sbrk( 0 ); 723 heapBegin = heapEnd = sbrk( (char *) libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment694 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment 724 695 } // HeapManager 725 696 … … 729 700 if ( traceHeapTerm() ) { 730 701 printStats(); 731 // if ( prtfree() ) prtFree( heapManager, true );702 // prtUnfreed() called in heapAppStop() 732 703 } // if 733 704 #endif // __STATISTICS__ … … 738 709 void memory_startup( void ) { 739 710 #ifdef __CFA_DEBUG__ 740 if ( unlikely( heapBoot ) ) {// check for recursion during system boot711 if ( heapBoot ) { // check for recursion during system boot 741 712 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 742 713 abort( "boot() : internal error, recursively invoked during system boot." ); … … 757 728 758 729 static inline void * mallocNoStats( size_t size ) { // necessary for malloc statistics 759 verify( heapManager.heapBegin != 0 ); // called before memory_startup ?730 verify( heapManager.heapBegin != 0p ); // called before memory_startup ? 760 731 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 761 732 … … 793 764 794 765 795 static inline void * memalignNoStats( size_t alignment, size_t size ) { // necessary for malloc statistics766 static inline void * memalignNoStats( size_t alignment, size_t size ) { 796 767 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 797 768 … … 815 786 816 787 // address in the block of the "next" alignment address 817 char * user = (char *) libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );788 char * user = (char *)ceiling2( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment ); 818 789 819 790 // address of header from malloc … … 843 814 #endif // __CFA_DEBUG__ 844 815 headers( "cmemalign", addr, header, freeElem, bsize, alignment ); 816 817 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 845 818 #ifndef __CFA_DEBUG__ 846 847 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.848 819 if ( ! mapped ) 849 820 #endif // __CFA_DEBUG__ … … 857 828 858 829 859 // supported mallopt options860 #ifndef M_MMAP_THRESHOLD861 #define M_MMAP_THRESHOLD (-1)862 #endif // M_TOP_PAD863 #ifndef M_TOP_PAD864 #define M_TOP_PAD (-2)865 #endif // M_TOP_PAD866 867 868 830 extern "C" { 869 831 // Allocates size bytes and returns a pointer to the allocated memory. The contents are undefined. If size is 0, … … 881 843 // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes. 882 844 void * aalloc( size_t dim, size_t elemSize ) { 845 size_t size = dim * elemSize; 883 846 #ifdef __STATISTICS__ 884 847 __atomic_add_fetch( &aalloc_calls, 1, __ATOMIC_SEQ_CST ); 885 __atomic_add_fetch( &aalloc_storage, dim * elemSize, __ATOMIC_SEQ_CST );886 #endif // __STATISTICS__ 887 888 return mallocNoStats( dim * elemSize );848 __atomic_add_fetch( &aalloc_storage, size, __ATOMIC_SEQ_CST ); 849 #endif // __STATISTICS__ 850 851 return mallocNoStats( size ); 889 852 } // aalloc 890 853 … … 899 862 return callocNoStats( dim, elemSize ); 900 863 } // calloc 864 901 865 902 866 // Change the size of the memory block pointed to by oaddr to size bytes. The contents are undefined. If oaddr is … … 907 871 #ifdef __STATISTICS__ 908 872 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 909 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );910 873 #endif // __STATISTICS__ 911 874 912 875 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 913 876 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 914 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 877 if ( unlikely( oaddr == 0p ) ) { 878 #ifdef __STATISTICS__ 879 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 880 #endif // __STATISTICS__ 881 return mallocNoStats( size ); 882 } // if 915 883 916 884 HeapManager.Storage.Header * header; 917 885 HeapManager.FreeHeader * freeElem; 918 size_t bsize, oalign = 0;886 size_t bsize, oalign; 919 887 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 920 888 921 889 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 922 890 // same size, DO NOT preserve STICKY PROPERTIES. 923 if ( oalign == 0&& size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size891 if ( oalign <= libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 924 892 header->kind.real.blockSize &= -2; // no alignment and turn off 0 fill 925 893 header->kind.real.size = size; // reset allocation size 926 894 return oaddr; 927 895 } // if 896 897 #ifdef __STATISTICS__ 898 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 899 #endif // __STATISTICS__ 928 900 929 901 // change size, DO NOT preserve STICKY PROPERTIES. … … 938 910 #ifdef __STATISTICS__ 939 911 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 940 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );941 912 #endif // __STATISTICS__ 942 913 943 914 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 944 915 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 945 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 916 if ( unlikely( oaddr == 0p ) ) { 917 #ifdef __STATISTICS__ 918 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 919 #endif // __STATISTICS__ 920 return mallocNoStats( size ); 921 } // if 946 922 947 923 HeapManager.Storage.Header * header; 948 924 HeapManager.FreeHeader * freeElem; 949 size_t bsize, oalign = 0;925 size_t bsize, oalign; 950 926 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 951 927 … … 961 937 } // if 962 938 939 #ifdef __STATISTICS__ 940 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 941 #endif // __STATISTICS__ 942 963 943 // change size and copy old content to new storage 964 944 965 945 void * naddr; 966 if ( likely( oalign == 0 ) ) { // previous request memalign?946 if ( likely( oalign <= libAlign() ) ) { // previous request not aligned ? 967 947 naddr = mallocNoStats( size ); // create new area 968 948 } else { … … 997 977 // Same as aalloc() with memory alignment. 998 978 void * amemalign( size_t alignment, size_t dim, size_t elemSize ) { 979 size_t size = dim * elemSize; 999 980 #ifdef __STATISTICS__ 1000 981 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 1001 __atomic_add_fetch( &cmemalign_storage, dim * elemSize, __ATOMIC_SEQ_CST );1002 #endif // __STATISTICS__ 1003 1004 return memalignNoStats( alignment, dim * elemSize );982 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST ); 983 #endif // __STATISTICS__ 984 985 return memalignNoStats( alignment, size ); 1005 986 } // amemalign 1006 987 … … 1028 1009 // free(3). 1029 1010 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 1030 if ( alignment < libAlign() || ! libPow2( alignment ) ) return EINVAL; // check alignment1011 if ( alignment < libAlign() || ! is_pow2( alignment ) ) return EINVAL; // check alignment 1031 1012 * memptr = memalign( alignment, size ); 1032 1013 return 0; … … 1042 1023 // Same as valloc but rounds size to multiple of page size. 1043 1024 void * pvalloc( size_t size ) { 1044 return memalign( pageSize, libCeiling( size, pageSize ) );1025 return memalign( pageSize, ceiling2( size, pageSize ) ); 1045 1026 } // pvalloc 1046 1027 … … 1080 1061 } // malloc_alignment 1081 1062 1063 1082 1064 // Set the alignment for an the allocation and return previous alignment or 0 if no alignment. 1083 1065 size_t $malloc_alignment_set( void * addr, size_t alignment ) { … … 1162 1144 } // malloc_stats 1163 1145 1146 1164 1147 // Changes the file descripter where malloc_stats() writes statistics. 1165 1148 int malloc_stats_fd( int fd __attribute__(( unused )) ) { 1166 1149 #ifdef __STATISTICS__ 1167 int temp = stat fd;1168 stat fd = fd;1150 int temp = stat_fd; 1151 stat_fd = fd; 1169 1152 return temp; 1170 1153 #else … … 1198 1181 // malloc). 1199 1182 int malloc_info( int options, FILE * stream ) { 1200 if ( options != 0 ) { errno = EINVAL; return -1; } 1183 if ( options != 0 ) { errno = EINVAL; return -1; } 1184 #ifdef __STATISTICS__ 1201 1185 return printStatsXML( stream ); 1186 #else 1187 return 0; // unsupported 1188 #endif // __STATISTICS__ 1202 1189 } // malloc_info 1203 1190 … … 1214 1201 // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data 1215 1202 // structure pointed to by state. 1216 int malloc_set_state( void * ptr) {1203 int malloc_set_state( void * ) { 1217 1204 return 0; // unsupported 1218 1205 } // malloc_set_state … … 1224 1211 #ifdef __STATISTICS__ 1225 1212 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 1226 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );1227 1213 #endif // __STATISTICS__ 1228 1214 1229 1215 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1230 1216 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 1231 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1217 if ( unlikely( oaddr == 0p ) ) { 1218 #ifdef __STATISTICS__ 1219 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1220 #endif // __STATISTICS__ 1221 return memalignNoStats( nalign, size ); 1222 } // if 1232 1223 1233 1224 if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum … … 1239 1230 HeapManager.Storage.Header * header; 1240 1231 HeapManager.FreeHeader * freeElem; 1241 size_t bsize, oalign = 0;1232 size_t bsize, oalign; 1242 1233 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1243 1234 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket … … 1253 1244 } // if 1254 1245 } // if 1246 1247 #ifdef __STATISTICS__ 1248 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1249 #endif // __STATISTICS__ 1255 1250 1256 1251 // change size, DO NOT preserve STICKY PROPERTIES. … … 1269 1264 HeapManager.Storage.Header * header; 1270 1265 HeapManager.FreeHeader * freeElem; 1271 size_t bsize, oalign = 0;1266 size_t bsize, oalign; 1272 1267 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1273 1268 -
libcfa/src/heap.hfa
r53fd995 r92aca37 10 10 // Created On : Tue May 26 11:23:55 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Aug 5 14:55:55202013 // Update Count : 1 412 // Last Modified On : Sat Aug 8 17:36:48 2020 13 // Update Count : 16 14 14 // 15 15 … … 18 18 size_t default_mmap_start(); // CFA extras 19 19 size_t default_heap_expansion(); 20 bool default_heap_exhausted(); // unsafe to call printf!21 20 22 21 bool traceHeap(); … … 31 30 bool checkFreeOn(); 32 31 bool checkFreeOff(); 32 33 // supported mallopt options 34 #ifndef M_MMAP_THRESHOLD 35 #define M_MMAP_THRESHOLD (-1) 36 #endif // M_TOP_PAD 37 #ifndef M_TOP_PAD 38 #define M_TOP_PAD (-2) 39 #endif // M_TOP_PAD 33 40 34 41 extern "C" {
Note: See TracChangeset
for help on using the changeset viewer.