Changeset ad2dced
- Timestamp:
- Dec 15, 2020, 9:48:28 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- dd92fe9
- Parents:
- 5dc5da7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
r5dc5da7 rad2dced 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 13 22:04:10202013 // Update Count : 98412 // Last Modified On : Tue Dec 15 21:37:54 2020 13 // Update Count : 1013 14 14 // 15 15 16 16 #include <unistd.h> // sbrk, sysconf 17 #include <stdlib.h> // EXIT_FAILURE 17 18 #include <stdbool.h> // true, false 18 19 #include <stdio.h> // snprintf, fileno … … 71 72 // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address, 72 73 // the brk address is extended by the extension amount. 73 __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),74 __CFA_DEFAULT_HEAP_EXPANSION__ = (10 * 1024 * 1024), 74 75 75 76 // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets; … … 115 116 116 117 // statically allocated variables => zero filled. 117 static size_t pageSize; // architecture pagesize 118 size_t __page_size; // architecture pagesize 119 int __map_prot; // common mmap/mprotect protection 118 120 static size_t heapExpand; // sbrk advance 119 121 static size_t mmapStart; // cross over point for mmap … … 249 251 #endif // FASTLOOKUP 250 252 251 static int mmapFd = -1;// fake or actual fd for anonymous file253 static const off_t mmapFd = -1; // fake or actual fd for anonymous file 252 254 #ifdef __CFA_DEBUG__ 253 255 static bool heapBoot = 0; // detect recursion during boot … … 374 376 375 377 static inline bool setMmapStart( size_t value ) { // true => mmapped, false => sbrk 376 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false;378 if ( value < __page_size || bucketSizes[NoBucketSizes - 1] < value ) return false; 377 379 mmapStart = value; // set global 378 380 … … 484 486 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes." 485 487 488 #include <unistd.h> 486 489 static inline void * extend( size_t size ) with( heapManager ) { 487 490 lock( extlock __cfaabi_dbg_ctx2 ); … … 490 493 // If the size requested is bigger than the current remaining storage, increase the size of the heap. 491 494 492 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, pageSize ); 495 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, __page_size ); 496 // Do not call abort or strerror( errno ) as they may call malloc. 493 497 if ( sbrk( increase ) == (void *)-1 ) { // failed, no memory ? 494 498 unlock( extlock ); 495 abort( NO_MEMORY_MSG, size ); // give up 496 } // if 497 if ( mprotect( (char *)heapEnd + heapRemaining, increase, PROT_READ | PROT_WRITE | PROT_EXEC ) ) { 498 enum { BufferSize = 128 }; 499 char helpText[BufferSize]; 500 // Do not call strerror( errno ) as it may call malloc. 501 int len = snprintf( helpText, BufferSize, "internal error, extend(), mprotect failure, heapEnd:%p size:%zd, errno:%d.", heapEnd, increase, errno ); 502 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); 499 __cfaabi_bits_print_nolock( STDERR_FILENO, NO_MEMORY_MSG, size ); 500 _exit( EXIT_FAILURE ); 501 } // if 502 if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) { 503 unlock( extlock ); 504 __cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno ); 505 _exit( EXIT_FAILURE ); 503 506 } // if 504 507 #ifdef __STATISTICS__ … … 508 511 #ifdef __CFA_DEBUG__ 509 512 // Set new memory to garbage so subsequent uninitialized usages might fail. 510 //memset( (char *)heapEnd + heapRemaining, '\377', increase );511 Memset( (char *)heapEnd + heapRemaining, increase );513 memset( (char *)heapEnd + heapRemaining, '\hde', increase ); 514 //Memset( (char *)heapEnd + heapRemaining, increase ); 512 515 #endif // __CFA_DEBUG__ 513 516 rem = heapRemaining + increase - size; … … 568 571 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 569 572 } else { // large size => mmap 570 if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;571 tsize = ceiling2( tsize, pageSize ); // must be multiple of page size573 if ( unlikely( size > ULONG_MAX - __page_size ) ) return 0p; 574 tsize = ceiling2( tsize, __page_size ); // must be multiple of page size 572 575 #ifdef __STATISTICS__ 573 576 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); … … 575 578 #endif // __STATISTICS__ 576 579 577 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );580 block = (HeapManager.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); 578 581 if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ? 579 582 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory … … 583 586 #ifdef __CFA_DEBUG__ 584 587 // Set new memory to garbage so subsequent uninitialized usages might fail. 585 //memset( block, '\377', tsize );586 Memset( block, tsize );588 memset( block, '\hde', tsize ); 589 //Memset( block, tsize ); 587 590 #endif // __CFA_DEBUG__ 588 591 block->header.kind.real.blockSize = tsize; // storage size for munmap … … 624 627 #endif // __STATISTICS__ 625 628 if ( munmap( header, size ) == -1 ) { 626 #ifdef __CFA_DEBUG__627 629 abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n" 628 630 "Possible cause is invalid pointer.", 629 631 addr ); 630 #endif // __CFA_DEBUG__631 632 } // if 632 633 } else { 633 634 #ifdef __CFA_DEBUG__ 634 635 // Set free memory to garbage so subsequent usages might fail. 635 //memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );636 Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );636 memset( ((HeapManager.Storage *)header)->data, '\hde', freeElem->blockSize - sizeof( HeapManager.Storage ) ); 637 //Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) ); 637 638 #endif // __CFA_DEBUG__ 638 639 … … 703 704 704 705 static void ?{}( HeapManager & manager ) with( manager ) { 705 pageSize = sysconf( _SC_PAGESIZE ); 706 __page_size = sysconf( _SC_PAGESIZE ); 707 __map_prot = PROT_READ | PROT_WRITE | PROT_EXEC; 706 708 707 709 for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists … … 723 725 724 726 char * end = (char *)sbrk( 0 ); 725 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, pageSize ) - end ); // move start of heap to multiple of alignment727 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment 726 728 } // HeapManager 727 729 … … 741 743 #ifdef __CFA_DEBUG__ 742 744 if ( heapBoot ) { // check for recursion during system boot 743 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.744 745 abort( "boot() : internal error, recursively invoked during system boot." ); 745 746 } // if … … 1048 1049 // page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 1049 1050 void * valloc( size_t size ) { 1050 return memalign( pageSize, size );1051 return memalign( __page_size, size ); 1051 1052 } // valloc 1052 1053 … … 1054 1055 // Same as valloc but rounds size to multiple of page size. 1055 1056 void * pvalloc( size_t size ) { 1056 return memalign( pageSize, ceiling2( size, pageSize ) );1057 return memalign( __page_size, ceiling2( size, __page_size ) ); 1057 1058 } // pvalloc 1058 1059 … … 1193 1194 choose( option ) { 1194 1195 case M_TOP_PAD: 1195 heapExpand = ceiling2( value, pageSize ); return 1;1196 heapExpand = ceiling2( value, __page_size ); return 1; 1196 1197 case M_MMAP_THRESHOLD: 1197 1198 if ( setMmapStart( value ) ) return 1;
Note: See TracChangeset
for help on using the changeset viewer.