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