Changes in libcfa/src/heap.cfa [7117ac3:b6830d74]
- File:
-
- 1 edited
-
libcfa/src/heap.cfa (modified) (47 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
r7117ac3 rb6830d74 1 // #comment TD : this file uses both spaces and tabs for indentation 2 1 3 // 2 4 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo … … 10 12 // Created On : Tue Dec 19 21:58:35 2017 11 13 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Sep 6 09:01:30201813 // Update Count : 51314 // Last Modified On : Sat Aug 11 08:22:16 2018 15 // Update Count : 495 14 16 // 15 17 … … 23 25 24 26 // #comment TD : Many of these should be merged into math I believe 25 #include "bits/align.hfa" // libPow226 #include "bits/defs.hfa" // likely, unlikely27 #include "bits/locks.hfa" // __spinlock_t27 #include "bits/align.hfa" // libPow2 28 #include "bits/defs.hfa" // likely, unlikely 29 #include "bits/locks.hfa" // __spinlock_t 28 30 #include "startup.hfa" // STARTUP_PRIORITY_MEMORY 29 #include "stdlib.hfa" // bsearchl31 #include "stdlib.hfa" // bsearchl 30 32 #include "malloc.h" 31 33 … … 149 151 150 152 extern "C" { 151 void heapAppStart() {// called by __cfaabi_appready_startup152 allocFree = 0;153 } // heapAppStart154 155 void heapAppStop() {// called by __cfaabi_appready_startdown156 fclose( stdin ); fclose( stdout );157 checkUnfreed();158 } // heapAppStop153 void heapAppStart() { // called by __cfaabi_appready_startup 154 allocFree = 0; 155 } // heapAppStart 156 157 void heapAppStop() { // called by __cfaabi_appready_startdown 158 fclose( stdin ); fclose( stdout ); 159 checkUnfreed(); 160 } // heapAppStop 159 161 } // extern "C" 160 162 #endif // __CFA_DEBUG__ … … 165 167 166 168 struct Storage { 167 struct Header { // header169 struct Header { // header 168 170 union Kind { 169 171 struct RealHeader { 170 172 union { 171 struct { // 4-byte word => 8-byte header, 8-byte word => 16-byte header 173 // #comment TD : this code use byte size but the comment uses bit size 174 175 struct { // 32-bit word => 64-bit header, 64-bit word => 128-bit header 172 176 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4 173 177 uint32_t padding; // unused, force home/blocksize to overlay alignment in fake header 174 #endif // __ BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4178 #endif // __ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32 175 179 176 180 union { … … 185 189 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 186 190 uint32_t padding; // unused, force home/blocksize to overlay alignment in fake header 187 #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 191 #endif // __ORDER_LITTLE_ENDIAN__ && __U_WORDSIZE__ == 32 192 188 193 }; 189 // future code 194 195 // #comment TD : C++ code 190 196 #if BUCKLOCK == LOCKFREE 191 197 Stack<Storage>::Link next; // freed block points next freed block of same size (double-wide) … … 205 211 } fake; // FakeHeader 206 212 } kind; // Kind 207 } header; // Header208 char pad[ALIGN - sizeof( Header )];209 char data[0]; // storage213 } header; // Header 214 char pad[ALIGN - sizeof( Header )]; 215 char data[0]; // storage 210 216 }; // Storage 211 217 … … 214 220 struct FreeHeader { 215 221 #if BUCKLOCK == SPINLOCK 216 __spinlock_t lock; // must be first field for alignment217 Storage * freeList;222 __spinlock_t lock; // must be first field for alignment 223 Storage * freeList; 218 224 #elif BUCKLOCK == LOCKFREE 219 // futurecode220 StackLF<Storage> freeList;225 // #comment TD : C++ code 226 StackLF<Storage> freeList; 221 227 #else 222 #error undefined lock type for bucket lock228 #error undefined lock type for bucket lock 223 229 #endif // SPINLOCK 224 size_t blockSize; // size of allocations on this list230 size_t blockSize; // size of allocations on this list 225 231 }; // FreeHeader 226 232 … … 243 249 static unsigned int maxBucketsUsed; // maximum number of buckets in use 244 250 251 // #comment TD : This array is not const but it feels like it should be 245 252 // Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size. 246 static const unsigned int bucketSizes[NoBucketSizes] @= {// different bucket sizes253 static unsigned int bucketSizes[NoBucketSizes] @= { // different bucket sizes 247 254 16, 32, 48, 64, 248 255 64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224, … … 272 279 // #comment TD : The return type of this function should be commented 273 280 static inline bool setMmapStart( size_t value ) { 274 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;281 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true; 275 282 mmapStart = value; // set global 276 283 … … 306 313 sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment 307 314 heapBegin = heapEnd = sbrk( 0 ); // get new start point 308 } // HeapManager315 } // HeapManager 309 316 310 317 … … 316 323 // } // if 317 324 #endif // __STATISTICS__ 318 } // ~HeapManager325 } // ~HeapManager 319 326 320 327 … … 322 329 void memory_startup( void ) { 323 330 #ifdef __CFA_DEBUG__ 324 if ( unlikely( heapBoot ) ) { // check for recursion during system boot331 if ( unlikely( heapBoot ) ) { // check for recursion during system boot 325 332 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 326 333 abort( "boot() : internal error, recursively invoked during system boot." ); … … 329 336 #endif // __CFA_DEBUG__ 330 337 331 // assert( heapManager.heapBegin != 0 );332 //heapManager{};333 if ( heapManager.heapBegin == 0 )heapManager{};338 // #comment TD : This assertion seems redundent with the above code 339 assert( heapManager.heapBegin == 0 ); 340 heapManager{}; 334 341 } // memory_startup 335 342 … … 367 374 char helpText[512]; 368 375 __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText), 369 "\nHeap statistics:\n"370 " malloc: calls %u / storage %llu\n"371 " calloc: calls %u / storage %llu\n"372 " memalign: calls %u / storage %llu\n"373 " cmemalign: calls %u / storage %llu\n"374 " realloc: calls %u / storage %llu\n"375 " free: calls %u / storage %llu\n"376 " mmap: calls %u / storage %llu\n"377 " munmap: calls %u / storage %llu\n"378 " sbrk: calls %u / storage %llu\n",379 malloc_calls, malloc_storage,380 calloc_calls, calloc_storage,381 memalign_calls, memalign_storage,382 cmemalign_calls, cmemalign_storage,383 realloc_calls, realloc_storage,384 free_calls, free_storage,385 mmap_calls, mmap_storage,386 munmap_calls, munmap_storage,387 sbrk_calls, sbrk_storage376 "\nHeap statistics:\n" 377 " malloc: calls %u / storage %llu\n" 378 " calloc: calls %u / storage %llu\n" 379 " memalign: calls %u / storage %llu\n" 380 " cmemalign: calls %u / storage %llu\n" 381 " realloc: calls %u / storage %llu\n" 382 " free: calls %u / storage %llu\n" 383 " mmap: calls %u / storage %llu\n" 384 " munmap: calls %u / storage %llu\n" 385 " sbrk: calls %u / storage %llu\n", 386 malloc_calls, malloc_storage, 387 calloc_calls, calloc_storage, 388 memalign_calls, memalign_storage, 389 cmemalign_calls, cmemalign_storage, 390 realloc_calls, realloc_storage, 391 free_calls, free_storage, 392 mmap_calls, mmap_storage, 393 munmap_calls, munmap_storage, 394 sbrk_calls, sbrk_storage 388 395 ); 389 396 } // printStats 390 397 391 static int printStatsXML( FILE * stream ) { // see malloc_info 398 // #comment TD : Why do we have this? 399 static int printStatsXML( FILE * stream ) { 392 400 char helpText[512]; 393 401 int len = snprintf( helpText, sizeof(helpText), … … 423 431 static inline void noMemory() { 424 432 abort( "Heap memory exhausted at %zu bytes.\n" 425 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",426 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );433 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.", 434 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) ); 427 435 } // noMemory 428 436 … … 436 444 437 445 static inline bool setHeapExpand( size_t value ) { 438 if ( heapExpand < pageSize ) return true;446 if ( heapExpand < pageSize ) return true; 439 447 heapExpand = value; 440 448 return false; … … 445 453 if ( unlikely( check ) ) { // bad address ? 446 454 abort( "Attempt to %s storage %p with address outside the heap.\n" 447 "Possible cause is duplicate free on same block or overwriting of memory.",448 name, addr );455 "Possible cause is duplicate free on same block or overwriting of memory.", 456 name, addr ); 449 457 } // if 450 458 } // checkHeader … … 476 484 477 485 #ifdef __CFA_DEBUG__ 478 checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?486 checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ? 479 487 #endif // __CFA_DEBUG__ 480 488 … … 482 490 // It's called as the first statement of both branches of the last if, with the same parameters in all cases 483 491 484 // header may be safe to dereference485 fakeHeader( header, size, alignment );492 // header may be safe to dereference 493 fakeHeader( header, size, alignment ); 486 494 #ifdef __CFA_DEBUG__ 487 checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)495 checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -) 488 496 #endif // __CFA_DEBUG__ 489 497 490 freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);498 freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3); 491 499 #ifdef __CFA_DEBUG__ 492 if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {493 abort( "Attempt to %s storage %p with corrupted header.\n"494 "Possible cause is duplicate free on same block or overwriting of header information.",495 name, addr );496 } // if500 if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) { 501 abort( "Attempt to %s storage %p with corrupted header.\n" 502 "Possible cause is duplicate free on same block or overwriting of header information.", 503 name, addr ); 504 } // if 497 505 #endif // __CFA_DEBUG__ 498 size = freeElem->blockSize;499 return false;506 size = freeElem->blockSize; 507 return false; 500 508 } // headers 501 509 … … 513 521 return 0; 514 522 } // if 515 #ifdef __STATISTICS__523 #ifdef __STATISTICS__ 516 524 sbrk_calls += 1; 517 525 sbrk_storage += increase; 518 #endif // __STATISTICS__519 #ifdef __CFA_DEBUG__526 #endif // __STATISTICS__ 527 #ifdef __CFA_DEBUG__ 520 528 // Set new memory to garbage so subsequent uninitialized usages might fail. 521 529 memset( (char *)heapEnd + heapRemaining, '\377', increase ); 522 #endif // __CFA_DEBUG__530 #endif // __CFA_DEBUG__ 523 531 rem = heapRemaining + increase - size; 524 532 } // if … … 552 560 553 561 #if defined( SPINLOCK ) 554 lock( freeElem->lock __cfaabi_dbg_ctx2 );555 block = freeElem->freeList; // remove node from stack562 lock( freeElem->lock __cfaabi_dbg_ctx2 ); 563 block = freeElem->freeList; // remove node from stack 556 564 #else 557 block = freeElem->freeList.pop();565 block = freeElem->freeList.pop(); 558 566 #endif // SPINLOCK 559 567 if ( unlikely( block == 0 ) ) { // no free block ? … … 561 569 unlock( freeElem->lock ); 562 570 #endif // SPINLOCK 563 564 571 // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more 565 572 // and then carve it off. 566 573 567 574 block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call 568 if ( unlikely( block == 0 ) ) return 0;575 if ( unlikely( block == 0 ) ) return 0; 569 576 #if defined( SPINLOCK ) 570 577 } else { … … 575 582 576 583 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 577 } else { // large size => mmap584 } else { // large size => mmap 578 585 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size 579 586 #ifdef __STATISTICS__ 580 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );581 __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );587 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); 588 __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST ); 582 589 #endif // __STATISTICS__ 583 590 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); … … 586 593 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno ); 587 594 } // if 588 #ifdef __CFA_DEBUG__595 #ifdef __CFA_DEBUG__ 589 596 // Set new memory to garbage so subsequent uninitialized usages might fail. 590 597 memset( block, '\377', tsize ); 591 #endif // __CFA_DEBUG__598 #endif // __CFA_DEBUG__ 592 599 block->header.kind.real.blockSize = tsize; // storage size for munmap 593 } // if594 595 void * area = &(block->data); // adjust off header to user bytes600 } // if 601 602 void * area = &(block->data); // adjust off header to user bytes 596 603 597 604 #ifdef __CFA_DEBUG__ 598 assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?599 __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );600 if ( traceHeap() ) {601 enum { BufferSize = 64 };602 char helpText[BufferSize];603 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );604 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );605 __cfaabi_dbg_bits_write( helpText, len );606 } // if605 assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ? 606 __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST ); 607 if ( traceHeap() ) { 608 enum { BufferSize = 64 }; 609 char helpText[BufferSize]; 610 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize ); 611 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size ); 612 __cfaabi_dbg_bits_write( helpText, len ); 613 } // if 607 614 #endif // __CFA_DEBUG__ 608 615 … … 613 620 static inline void doFree( void * addr ) with ( heapManager ) { 614 621 #ifdef __CFA_DEBUG__ 615 if ( unlikely( heapManager.heapBegin == 0 ) ) {616 abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );617 } // if622 if ( unlikely( heapManager.heapBegin == 0 ) ) { 623 abort( "doFree( %p ) : internal error, called before heap is initialized.", addr ); 624 } // if 618 625 #endif // __CFA_DEBUG__ 619 626 … … 624 631 if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ? 625 632 #ifdef __STATISTICS__ 626 __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );627 __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST );633 __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST ); 634 __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST ); 628 635 #endif // __STATISTICS__ 629 636 if ( munmap( header, size ) == -1 ) { 630 637 #ifdef __CFA_DEBUG__ 631 638 abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n" 632 "Possible cause is invalid pointer.",633 addr );639 "Possible cause is invalid pointer.", 640 addr ); 634 641 #endif // __CFA_DEBUG__ 635 642 } // if 636 } else {643 } else { 637 644 #ifdef __CFA_DEBUG__ 638 // Set free memory to garbage so subsequent usages might fail.639 memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );645 // Set free memory to garbage so subsequent usages might fail. 646 memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) ); 640 647 #endif // __CFA_DEBUG__ 641 648 642 649 #ifdef __STATISTICS__ 643 free_storage += size;650 free_storage += size; 644 651 #endif // __STATISTICS__ 645 652 #if defined( SPINLOCK ) 646 lock( freeElem->lock __cfaabi_dbg_ctx2 ); // acquire spin lock647 header->kind.real.next = freeElem->freeList; // push on stack648 freeElem->freeList = (HeapManager.Storage *)header;649 unlock( freeElem->lock ); // release spin lock653 lock( freeElem->lock __cfaabi_dbg_ctx2 ); // acquire spin lock 654 header->kind.real.next = freeElem->freeList; // push on stack 655 freeElem->freeList = (HeapManager.Storage *)header; 656 unlock( freeElem->lock ); // release spin lock 650 657 #else 651 freeElem->freeList.push( *(HeapManager.Storage *)header );658 freeElem->freeList.push( *(HeapManager.Storage *)header ); 652 659 #endif // SPINLOCK 653 } // if660 } // if 654 661 655 662 #ifdef __CFA_DEBUG__ 656 __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );657 if ( traceHeap() ) {658 char helpText[64];659 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );660 __cfaabi_dbg_bits_write( helpText, len );661 } // if663 __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST ); 664 if ( traceHeap() ) { 665 char helpText[64]; 666 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size ); 667 __cfaabi_dbg_bits_write( helpText, len ); 668 } // if 662 669 #endif // __CFA_DEBUG__ 663 670 } // doFree … … 667 674 size_t total = 0; 668 675 #ifdef __STATISTICS__ 669 __cfaabi_dbg_bits_acquire();670 __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );676 __cfaabi_dbg_bits_acquire(); 677 __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" ); 671 678 #endif // __STATISTICS__ 672 679 for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) { … … 688 695 689 696 #ifdef __STATISTICS__ 690 __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u ", size, N );691 if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );697 __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u ", size, N ); 698 if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" ); 692 699 #endif // __STATISTICS__ 693 700 } // for 694 701 #ifdef __STATISTICS__ 695 __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );696 __cfaabi_dbg_bits_release();702 __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total ); 703 __cfaabi_dbg_bits_release(); 697 704 #endif // __STATISTICS__ 698 705 return (char *)heapEnd - (char *)heapBegin - total; 699 706 } // checkFree 700 707 701 702 static inline void * mallocNoStats( size_t size ) { // necessary for malloc statistics 703 //assert( heapManager.heapBegin != 0 ); 704 if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ? 708 // #comment TD : This is not a good name, plus this feels like it could easily be folded into doMalloc 709 static inline void * malloc2( size_t size ) { // necessary for malloc statistics 710 assert( heapManager.heapBegin != 0 ); 705 711 void * area = doMalloc( size ); 706 712 if ( unlikely( area == 0 ) ) errno = ENOMEM; // POSIX 707 713 return area; 708 } // malloc NoStats709 710 711 static inline void * memalign NoStats( size_t alignment, size_t size ) { // necessary for malloc statistics712 #ifdef __CFA_DEBUG__714 } // malloc2 715 716 717 static inline void * memalign2( size_t alignment, size_t size ) { // necessary for malloc statistics 718 #ifdef __CFA_DEBUG__ 713 719 checkAlign( alignment ); // check alignment 714 #endif // __CFA_DEBUG__720 #endif // __CFA_DEBUG__ 715 721 716 722 // if alignment <= default alignment, do normal malloc as two headers are unnecessary 717 if ( unlikely( alignment <= libAlign() ) ) return mallocNoStats( size );723 if ( unlikely( alignment <= libAlign() ) ) return malloc2( size ); 718 724 719 725 // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for … … 726 732 // subtract libAlign() because it is already the minimum alignment 727 733 // add sizeof(Storage) for fake header 728 // #comment TD : this is the only place that calls doMalloc without calling malloc NoStats, why ?734 // #comment TD : this is the only place that calls doMalloc without calling malloc2, why ? 729 735 char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) ); 730 if ( unlikely( area == 0 ) ) return area;736 if ( unlikely( area == 0 ) ) return area; 731 737 732 738 // address in the block of the "next" alignment address … … 743 749 744 750 return user; 745 } // memalign NoStats751 } // memalign2 746 752 747 753 748 754 extern "C" { 749 // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not 750 // initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be 751 // successfully passed to free(). 755 // The malloc() function allocates size bytes and returns a pointer to the 756 // allocated memory. The memory is not initialized. If size is 0, then malloc() 757 // returns either NULL, or a unique pointer value that can later be successfully 758 // passed to free(). 752 759 void * malloc( size_t size ) { 753 760 #ifdef __STATISTICS__ 754 __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST ); 755 __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST ); 756 #endif // __STATISTICS__ 757 758 return mallocNoStats( size ); 759 } // malloc 760 761 // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to 762 // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a 763 // unique pointer value that can later be successfully passed to free(). 764 void * calloc( size_t noOfElems, size_t elemSize ) { 761 __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST ); 762 __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST ); 763 #endif // __STATISTICS__ 764 765 return malloc2( size ); 766 } // malloc 767 768 // The calloc() function allocates memory for an array of nmemb elements of 769 // size bytes each and returns a pointer to the allocated memory. The memory 770 // is set to zero. If nmemb or size is 0, then calloc() returns either NULL, 771 // or a unique pointer value that can later be successfully passed to free(). 772 void * calloc( size_t noOfElems, size_t elemSize ) { 765 773 size_t size = noOfElems * elemSize; 766 774 #ifdef __STATISTICS__ 767 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );768 __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );769 #endif // __STATISTICS__ 770 771 char * area = (char *)malloc NoStats( size );772 if ( unlikely( area == 0 ) ) return 0;775 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST ); 776 __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST ); 777 #endif // __STATISTICS__ 778 779 char * area = (char *)malloc2( size ); 780 if ( unlikely( area == 0 ) ) return 0; 773 781 774 782 HeapManager.Storage.Header * header; … … 782 790 memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros 783 791 784 header->kind.real.blockSize |= 2; // mark as zero filled792 header->kind.real.blockSize |= 2; // mark as zero filled 785 793 return area; 786 } // calloc794 } // calloc 787 795 788 796 // #comment TD : Document this function … … 790 798 size_t size = noOfElems * elemSize; 791 799 #ifdef __STATISTICS__ 792 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );793 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );794 #endif // __STATISTICS__ 795 796 char * area = (char *)memalign NoStats( alignment, size );797 if ( unlikely( area == 0 ) ) return 0;800 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 801 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST ); 802 #endif // __STATISTICS__ 803 804 char * area = (char *)memalign2( alignment, size ); 805 if ( unlikely( area == 0 ) ) return 0; 798 806 HeapManager.Storage.Header * header; 799 807 HeapManager.FreeHeader * freeElem; … … 803 811 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 804 812 if ( ! mapped ) 805 #endif // __CFA_DEBUG__813 #endif // __CFA_DEBUG__ 806 814 memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros 807 815 header->kind.real.blockSize |= 2; // mark as zero filled 808 816 809 817 return area; 810 } // cmemalign 811 812 // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be 813 // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size 814 // is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is 815 // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call 816 // is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), 817 // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done. 818 void * realloc( void * addr, size_t size ) { 819 #ifdef __STATISTICS__ 820 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 821 #endif // __STATISTICS__ 822 823 if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases 824 if ( unlikely( size == 0 ) ) { free( addr ); return 0; } 818 } // cmemalign 819 820 // The realloc() function changes the size of the memory block pointed to by 821 // ptr to size bytes. The contents will be unchanged in the range from the 822 // start of the region up to the minimum of the old and new sizes. If the new 823 // size is larger than the old size, the added memory will not be initialized. 824 // If ptr is NULL, then the call is equivalent to malloc(size), for all values 825 // of size; if size is equal to zero, and ptr is not NULL, then the call is 826 // equivalent to free(ptr). Unless ptr is NULL, it must have been returned by 827 // an earlier call to malloc(), calloc() or realloc(). If the area pointed to 828 // was moved, a free(ptr) is done. 829 void * realloc( void * addr, size_t size ) { 830 #ifdef __STATISTICS__ 831 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 832 #endif // __STATISTICS__ 833 834 if ( unlikely( addr == 0 ) ) return malloc2( size ); // special cases 835 if ( unlikely( size == 0 ) ) { free( addr ); return 0; } 825 836 826 837 HeapManager.Storage.Header * header; … … 837 848 838 849 #ifdef __STATISTICS__ 839 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );850 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 840 851 #endif // __STATISTICS__ 841 852 … … 844 855 area = memalign( alignment, size ); // create new area 845 856 } else { 846 area = malloc NoStats( size );// create new area847 } // if 848 if ( unlikely( area == 0 ) ) return 0;857 area = malloc2( size ); // create new area 858 } // if 859 if ( unlikely( area == 0 ) ) return 0; 849 860 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ? 850 861 assert( (header->kind.real.blockSize & 1) == 0 ); … … 853 864 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 854 865 if ( ! mapped ) 855 #endif // __CFA_DEBUG__866 #endif // __CFA_DEBUG__ 856 867 memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part 857 868 header->kind.real.blockSize |= 2; // mark new request as zero fill … … 863 874 864 875 865 // The obsolete function memalign() allocates size bytes and returns a pointer to the allocated memory. The memory 866 // address will be a multiple of alignment, which must be a power of two. 867 void * memalign( size_t alignment, size_t size ) { 876 // The obsolete function memalign() allocates size bytes and returns 877 // a pointer to the allocated memory. The memory address will be a 878 // multiple of alignment, which must be a power of two. 879 void * memalign( size_t alignment, size_t size ) __attribute__ ((deprecated)); 880 void * memalign( size_t alignment, size_t size ) { 868 881 #ifdef __STATISTICS__ 869 882 __atomic_add_fetch( &memalign_calls, 1, __ATOMIC_SEQ_CST ); … … 871 884 #endif // __STATISTICS__ 872 885 873 void * area = memalign NoStats( alignment, size );886 void * area = memalign2( alignment, size ); 874 887 875 888 return area; 876 } // memalign877 878 // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a879 // multiple of alignment.889 } // memalign 890 891 // The function aligned_alloc() is the same as memalign(), except for 892 // the added restriction that size should be a multiple of alignment. 880 893 void * aligned_alloc( size_t alignment, size_t size ) { 881 894 return memalign( alignment, size ); … … 883 896 884 897 885 // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The 886 // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of 887 // sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later 888 // be successfully passed to free(3). 898 // The function posix_memalign() allocates size bytes and places the address 899 // of the allocated memory in *memptr. The address of the allocated memory 900 // will be a multiple of alignment, which must be a power of two and a multiple 901 // of sizeof(void *). If size is 0, then posix_memalign() returns either NULL, 902 // or a unique pointer value that can later be successfully passed to free(3). 889 903 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 890 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment904 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment 891 905 * memptr = memalign( alignment, size ); 892 if ( unlikely( * memptr == 0 ) ) return ENOMEM;906 if ( unlikely( * memptr == 0 ) ) return ENOMEM; 893 907 return 0; 894 908 } // posix_memalign 895 909 896 // The obsolete function valloc() allocates size bytes and returns a pointer to the allocated memory. The memory 897 // address will be a multiple of the page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 910 // The obsolete function valloc() allocates size bytes and returns a pointer 911 // to the allocated memory. The memory address will be a multiple of the page size. 912 // It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 913 void * valloc( size_t size ) __attribute__ ((deprecated)); 898 914 void * valloc( size_t size ) { 899 915 return memalign( pageSize, size ); … … 901 917 902 918 903 // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to 904 // malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior 905 // occurs. If ptr is NULL, no operation is performed. 919 // The free() function frees the memory space pointed to by ptr, which must 920 // have been returned by a previous call to malloc(), calloc() or realloc(). 921 // Otherwise, or if free(ptr) has already been called before, undefined 922 // behavior occurs. If ptr is NULL, no operation is performed. 906 923 void free( void * addr ) { 907 924 #ifdef __STATISTICS__ 908 __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );925 __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST ); 909 926 #endif // __STATISTICS__ 910 927 … … 914 931 if ( unlikely( addr == 0 ) ) { // special case 915 932 #ifdef __CFA_DEBUG__ 916 if ( traceHeap() ) {917 #define nullmsg "Free( 0x0 ) size:0\n"918 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.919 __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );920 } // if933 if ( traceHeap() ) { 934 #define nullmsg "Free( 0x0 ) size:0\n" 935 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf. 936 __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 ); 937 } // if 921 938 #endif // __CFA_DEBUG__ 922 939 return; … … 926 943 } // free 927 944 928 // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see 929 // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that 945 // The mallopt() function adjusts parameters that control the behavior of the 946 // memory-allocation functions (see malloc(3)). The param argument specifies 947 // the parameter to be modified, and value specifies the new value for that 930 948 // parameter. 931 int mallopt( int option, int value ) {949 int mallopt( int option, int value ) { 932 950 choose( option ) { 933 case M_TOP_PAD:934 if ( setHeapExpand( value ) ) fallthru default;935 case M_MMAP_THRESHOLD:936 if ( setMmapStart( value ) ) fallthru default;937 default:938 // #comment TD : 1 for unsopported feels wrong939 return 1; // success, or unsupported951 case M_TOP_PAD: 952 if ( setHeapExpand( value ) ) fallthru default; 953 case M_MMAP_THRESHOLD: 954 if ( setMmapStart( value ) ) fallthru default; 955 default: 956 // #comment TD : 1 for unsopported feels wrong 957 return 1; // success, or unsupported 940 958 } // switch 941 959 return 0; // error 942 960 } // mallopt 943 961 944 // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a945 // suitable argument).962 // The malloc_trim() function attempts to release free memory at the top 963 // of the heap (by calling sbrk(2) with a suitable argument). 946 964 int malloc_trim( size_t ) { 947 965 return 0; // => impossible to release memory 948 966 } // malloc_trim 949 967 950 // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to 951 // a block of memory allocated by malloc(3) or a related function. 952 size_t malloc_usable_size( void * addr ) { 953 if ( unlikely( addr == 0 ) ) return 0; // null allocation has 0 size 968 // The malloc_usable_size() function returns the number of usable bytes in the 969 // block pointed to by ptr, a pointer to a block of memory allocated by 970 // malloc(3) or a related function. 971 size_t malloc_usable_size( void * addr ) { 972 if ( unlikely( addr == 0 ) ) return 0; // null allocation has 0 size 954 973 955 974 HeapManager.Storage.Header * header; … … 963 982 964 983 965 // The malloc_alignment() function returns the alignment of the allocation. 984 // #comment TD : Document this function 966 985 size_t malloc_alignment( void * addr ) { 967 if ( unlikely( addr == 0 ) ) return libAlign(); // minimum alignment986 if ( unlikely( addr == 0 ) ) return libAlign(); // minimum alignment 968 987 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ); 969 988 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? … … 972 991 return libAlign (); // minimum alignment 973 992 } // if 974 } // malloc_alignment975 976 977 // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc(). 993 } // malloc_alignment 994 995 996 // #comment TD : Document this function 978 997 bool malloc_zero_fill( void * addr ) { 979 if ( unlikely( addr == 0 ) ) return false; // null allocation is not zero fill998 if ( unlikely( addr == 0 ) ) return false; // null allocation is not zero fill 980 999 981 1000 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ); … … 984 1003 } // if 985 1004 return (header->kind.real.blockSize & 2) != 0; // zero filled (calloc/cmemalign) ? 986 } // malloc_zero_fill 987 988 989 // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and 990 // related functions. 1005 } // malloc_zero_fill 1006 1007 1008 // #comment TD : Document this function 991 1009 void malloc_stats( void ) { 992 1010 #ifdef __STATISTICS__ 993 printStats();994 if ( checkFree() ) checkFree( heapManager );995 #endif // __STATISTICS__ 996 } // malloc_stats997 998 // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.999 int malloc_stats_fd( int fd ) {1000 #ifdef __STATISTICS__ 1001 int temp = statfd;1002 statfd = fd;1003 return temp;1011 printStats(); 1012 if ( checkFree() ) checkFree( heapManager ); 1013 #endif // __STATISTICS__ 1014 } // malloc_stats 1015 1016 // #comment TD : Document this function 1017 int malloc_stats_fd( int fd ) { 1018 #ifdef __STATISTICS__ 1019 int temp = statfd; 1020 statfd = fd; 1021 return temp; 1004 1022 #else 1005 return -1; 1006 #endif // __STATISTICS__ 1007 } // malloc_stats_fd 1008 1009 // The malloc_info() function exports an XML string that describes the current state of the memory-allocation 1010 // implementation in the caller. The string is printed on the file stream stream. The exported string includes 1011 // information about all arenas (see malloc(3)). 1023 return -1; 1024 #endif // __STATISTICS__ 1025 } // malloc_stats_fd 1026 1027 1028 // #comment TD : Document this function 1012 1029 int malloc_info( int options, FILE * stream ) { 1013 1030 return printStatsXML( stream ); … … 1015 1032 1016 1033 1017 // The malloc_get_state() function records the current state of all malloc(3) internal bookkeeping variables (but 1018 // not the actual contents of the heap or the state of malloc_hook(3) functions pointers). The state is recorded in 1019 // a system-dependent opaque data structure dynamically allocated via malloc(3), and a pointer to that data 1020 // structure is returned as the function result. (It is the caller's responsibility to free(3) this memory.) 1034 // #comment TD : What are these two functions for? 1021 1035 void * malloc_get_state( void ) { 1022 return 0; // unsupported1036 return 0; 1023 1037 } // malloc_get_state 1024 1038 1025 1026 // The malloc_set_state() function restores the state of all malloc(3) internal bookkeeping variables to the values1027 // recorded in the opaque data structure pointed to by state.1028 1039 int malloc_set_state( void * ptr ) { 1029 return 0; // unsupported1040 return 0; 1030 1041 } // malloc_set_state 1031 1042 } // extern "C"
Note:
See TracChangeset
for help on using the changeset viewer.