Changes in libcfa/src/heap.cfa [e3fea42:1076d05]
- File:
-
- 1 edited
-
libcfa/src/heap.cfa (modified) (47 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
re3fea42 r1076d05 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 10:04:51202013 // Update Count : 64812 // Last Modified On : Wed May 6 17:29:26 2020 13 // Update Count : 727 14 14 // 15 15 … … 19 19 #include <errno.h> // errno 20 20 #include <string.h> // memset, memcpy 21 #include <limits.h> // ULONG_MAX 21 22 extern "C" { 22 23 #include <sys/mman.h> // mmap, munmap 23 24 } // extern "C" 24 25 25 // #comment TD : Many of these should be merged into math I believe26 26 #include "bits/align.hfa" // libPow2 27 27 #include "bits/defs.hfa" // likely, unlikely … … 30 30 //#include "stdlib.hfa" // bsearchl 31 31 #include "malloc.h" 32 #include "bitmanip.hfa" // ceiling 32 33 33 34 #define MIN(x, y) (y > x ? x : y) … … 81 82 }; 82 83 84 size_t default_heap_expansion() __attribute__(( weak )) { 85 return __CFA_DEFAULT_HEAP_EXPANSION__; 86 } // default_heap_expansion 87 83 88 size_t default_mmap_start() __attribute__(( weak )) { 84 89 return __CFA_DEFAULT_MMAP_START__; 85 90 } // default_mmap_start 86 87 size_t default_heap_expansion() __attribute__(( weak )) {88 return __CFA_DEFAULT_HEAP_EXPANSION__;89 } // default_heap_expansion90 91 91 92 … … 150 151 union { 151 152 // FreeHeader * home; // allocated block points back to home locations (must overlay alignment) 153 // 2nd low-order bit => zero filled 152 154 void * home; // allocated block points back to home locations (must overlay alignment) 153 155 size_t blockSize; // size for munmap (must overlay alignment) … … 169 171 struct FakeHeader { 170 172 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 171 uint32_t alignment; // low-order bits of home/blockSize used for tricks 173 // 1st low-order bit => fake header & alignment 174 uint32_t alignment; 172 175 #endif // __ORDER_LITTLE_ENDIAN__ 173 176 … … 179 182 } fake; // FakeHeader 180 183 } kind; // Kind 184 size_t size; // allocation size in bytes 181 185 } header; // Header 182 186 char pad[libAlign() - sizeof( Header )]; … … 262 266 static unsigned long long int free_storage; 263 267 static unsigned int free_calls; 268 static unsigned long long int aalloc_storage; 269 static unsigned int aalloc_calls; 264 270 static unsigned long long int calloc_storage; 265 271 static unsigned int calloc_calls; 266 272 static unsigned long long int memalign_storage; 267 273 static unsigned int memalign_calls; 274 static unsigned long long int amemalign_storage; 275 static unsigned int amemalign_calls; 268 276 static unsigned long long int cmemalign_storage; 269 277 static unsigned int cmemalign_calls; 278 static unsigned long long int resize_storage; 279 static unsigned int resize_calls; 270 280 static unsigned long long int realloc_storage; 271 281 static unsigned int realloc_calls; … … 275 285 // Use "write" because streams may be shutdown when calls are made. 276 286 static void printStats() { 277 char helpText[ 512];287 char helpText[1024]; 278 288 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), 279 289 "\nHeap statistics:\n" 280 290 " malloc: calls %u / storage %llu\n" 291 " aalloc: calls %u / storage %llu\n" 281 292 " calloc: calls %u / storage %llu\n" 282 293 " memalign: calls %u / storage %llu\n" 294 " amemalign: calls %u / storage %llu\n" 283 295 " cmemalign: calls %u / storage %llu\n" 296 " resize: calls %u / storage %llu\n" 284 297 " realloc: calls %u / storage %llu\n" 285 298 " free: calls %u / storage %llu\n" … … 288 301 " sbrk: calls %u / storage %llu\n", 289 302 malloc_calls, malloc_storage, 303 aalloc_calls, calloc_storage, 290 304 calloc_calls, calloc_storage, 291 305 memalign_calls, memalign_storage, 306 amemalign_calls, amemalign_storage, 292 307 cmemalign_calls, cmemalign_storage, 308 resize_calls, resize_storage, 293 309 realloc_calls, realloc_storage, 294 310 free_calls, free_storage, … … 300 316 301 317 static int printStatsXML( FILE * stream ) { // see malloc_info 302 char helpText[ 512];318 char helpText[1024]; 303 319 int len = snprintf( helpText, sizeof(helpText), 304 320 "<malloc version=\"1\">\n" … … 307 323 "</sizes>\n" 308 324 "<total type=\"malloc\" count=\"%u\" size=\"%llu\"/>\n" 325 "<total type=\"aalloc\" count=\"%u\" size=\"%llu\"/>\n" 309 326 "<total type=\"calloc\" count=\"%u\" size=\"%llu\"/>\n" 310 327 "<total type=\"memalign\" count=\"%u\" size=\"%llu\"/>\n" 328 "<total type=\"amemalign\" count=\"%u\" size=\"%llu\"/>\n" 311 329 "<total type=\"cmemalign\" count=\"%u\" size=\"%llu\"/>\n" 330 "<total type=\"resize\" count=\"%u\" size=\"%llu\"/>\n" 312 331 "<total type=\"realloc\" count=\"%u\" size=\"%llu\"/>\n" 313 332 "<total type=\"free\" count=\"%u\" size=\"%llu\"/>\n" … … 317 336 "</malloc>", 318 337 malloc_calls, malloc_storage, 338 aalloc_calls, aalloc_storage, 319 339 calloc_calls, calloc_storage, 320 340 memalign_calls, memalign_storage, 341 amemalign_calls, amemalign_storage, 321 342 cmemalign_calls, cmemalign_storage, 343 resize_calls, resize_storage, 322 344 realloc_calls, realloc_storage, 323 345 free_calls, free_storage, … … 339 361 340 362 341 static inline void checkAlign( size_t alignment ) {342 if ( alignment < libAlign() || ! libPow2( alignment ) ) {343 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );344 } // if345 } // checkAlign346 347 348 static inline bool setHeapExpand( size_t value ) {349 if ( heapExpand < pageSize ) return true;350 heapExpand = value;351 return false;352 } // setHeapExpand353 354 355 363 // thunk problem 356 364 size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) { … … 369 377 370 378 static inline bool setMmapStart( size_t value ) { // true => mmapped, false => sbrk 371 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;379 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false; 372 380 mmapStart = value; // set global 373 381 … … 376 384 assert( maxBucketsUsed < NoBucketSizes ); // subscript failure ? 377 385 assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ? 378 return false;386 return true; 379 387 } // setMmapStart 388 389 390 // <-------+----------------------------------------------------> bsize (bucket size) 391 // |header |addr 392 //================================================================================== 393 // align/offset | 394 // <-----------------<------------+-----------------------------> bsize (bucket size) 395 // |fake-header | addr 396 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) )) 397 #define realHeader( header ) ((HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset)) 398 399 // <-------<<--------------------- dsize ---------------------->> bsize (bucket size) 400 // |header |addr 401 //================================================================================== 402 // align/offset | 403 // <------------------------------<<---------- dsize --------->>> bsize (bucket size) 404 // |fake-header |addr 405 #define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header )) 406 407 408 static inline void checkAlign( size_t alignment ) { 409 if ( alignment < libAlign() || ! libPow2( alignment ) ) { 410 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() ); 411 } // if 412 } // checkAlign 380 413 381 414 … … 391 424 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) { 392 425 if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ? 393 size_t offset = header->kind.fake.offset;394 426 alignment = header->kind.fake.alignment & -2; // remove flag from value 395 427 #ifdef __CFA_DEBUG__ 396 428 checkAlign( alignment ); // check alignment 397 429 #endif // __CFA_DEBUG__ 398 header = (HeapManager.Storage.Header *)((char *)header - offset);430 header = realHeader( header ); // backup from fake to real header 399 431 } // if 400 432 } // fakeHeader 401 402 403 // <-------+----------------------------------------------------> bsize (bucket size)404 // |header |addr405 //==================================================================================406 // | alignment407 // <-----------------<------------+-----------------------------> bsize (bucket size)408 // |fake-header | addr409 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))410 411 // <-------<<--------------------- dsize ---------------------->> bsize (bucket size)412 // |header |addr413 //==================================================================================414 // | alignment415 // <------------------------------<<---------- dsize --------->>> bsize (bucket size)416 // |fake-header |addr417 #define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))418 433 419 434 … … 428 443 429 444 #ifdef __CFA_DEBUG__ 430 checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr );// bad low address ?445 checkHeader( addr < heapBegin, name, addr ); // bad low address ? 431 446 #endif // __CFA_DEBUG__ 432 447 … … 487 502 // along with the block and is a multiple of the alignment size. 488 503 489 if ( unlikely( size > ~0ul- sizeof(HeapManager.Storage) ) ) return 0p;504 if ( unlikely( size > ULONG_MAX - sizeof(HeapManager.Storage) ) ) return 0p; 490 505 size_t tsize = size + sizeof(HeapManager.Storage); 491 506 if ( likely( tsize < mmapStart ) ) { // small size => sbrk … … 539 554 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 540 555 } else { // large size => mmap 541 if ( unlikely( size > ~0ul- pageSize ) ) return 0p;556 if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p; 542 557 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size 543 558 #ifdef __STATISTICS__ … … 557 572 } // if 558 573 574 block->header.size = size; // store allocation size 559 575 void * addr = &(block->data); // adjust off header to user bytes 560 576 … … 680 696 #endif // FASTLOOKUP 681 697 682 if ( setMmapStart( default_mmap_start() ) ) {698 if ( ! setMmapStart( default_mmap_start() ) ) { 683 699 abort( "HeapManager : internal error, mmap start initialization failure." ); 684 700 } // if … … 686 702 687 703 char * end = (char *)sbrk( 0 ); 688 sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment 689 heapBegin = heapEnd = sbrk( 0 ); // get new start point 704 heapBegin = heapEnd = sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment 690 705 } // HeapManager 691 706 … … 713 728 //assert( heapManager.heapBegin != 0 ); 714 729 //heapManager{}; 715 if ( heapManager.heapBegin == 0p ) heapManager{}; 730 if ( heapManager.heapBegin == 0p ) heapManager{}; // sanity check 716 731 } // memory_startup 717 732 … … 725 740 //assert( heapManager.heapBegin != 0 ); 726 741 if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ? 742 #if __SIZEOF_POINTER__ == 8 743 verify( size < ((typeof(size_t))1 << 48) ); 744 #endif // __SIZEOF_POINTER__ == 8 727 745 void * addr = doMalloc( size ); 728 746 if ( unlikely( addr == 0p ) ) errno = ENOMEM; // POSIX … … 731 749 732 750 733 static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) {734 size_t size = noOfElems* elemSize;751 static inline void * callocNoStats( size_t dim, size_t elemSize ) { 752 size_t size = dim * elemSize; 735 753 char * addr = (char *)mallocNoStats( size ); 736 754 if ( unlikely( addr == 0p ) ) return 0p; … … 790 808 791 809 792 static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) {793 size_t size = noOfElems* elemSize;810 static inline void * cmemalignNoStats( size_t alignment, size_t dim, size_t elemSize ) { 811 size_t size = dim * elemSize; 794 812 char * addr = (char *)memalignNoStats( alignment, size ); 795 813 if ( unlikely( addr == 0p ) ) return 0p; … … 803 821 #endif // __CFA_DEBUG__ 804 822 memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros 805 header->kind.real.blockSize |= 2; // mark as zero filled 806 823 824 header->kind.real.blockSize |= 2; // mark as zero filled 807 825 return addr; 808 826 } // cmemalignNoStats … … 819 837 820 838 extern "C" { 821 // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not 822 // initialized. If size is 0, then malloc() returns either 0p, or a unique pointer value that can later be 823 // successfully passed to free(). 839 // Allocates size bytes and returns a pointer to the allocated memory. The contents are undefined. If size is 0, 840 // then malloc() returns a unique pointer value that can later be successfully passed to free(). 824 841 void * malloc( size_t size ) { 825 842 #ifdef __STATISTICS__ … … 831 848 } // malloc 832 849 833 // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to 834 // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either 0p, or a 835 // unique pointer value that can later be successfully passed to free(). 836 void * calloc( size_t noOfElems, size_t elemSize ) { 850 851 // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes. 852 void * aalloc( size_t dim, size_t elemSize ) { 853 #ifdef __STATISTICS__ 854 __atomic_add_fetch( &aalloc_calls, 1, __ATOMIC_SEQ_CST ); 855 __atomic_add_fetch( &aalloc_storage, dim * elemSize, __ATOMIC_SEQ_CST ); 856 #endif // __STATISTICS__ 857 858 return mallocNoStats( dim * elemSize ); 859 } // aalloc 860 861 862 // Same as aalloc() with memory set to zero. 863 void * calloc( size_t dim, size_t elemSize ) { 837 864 #ifdef __STATISTICS__ 838 865 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST ); 839 __atomic_add_fetch( &calloc_storage, noOfElems* elemSize, __ATOMIC_SEQ_CST );840 #endif // __STATISTICS__ 841 842 return callocNoStats( noOfElems, elemSize );866 __atomic_add_fetch( &calloc_storage, dim * elemSize, __ATOMIC_SEQ_CST ); 867 #endif // __STATISTICS__ 868 869 return callocNoStats( dim, elemSize ); 843 870 } // calloc 844 871 845 // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be 846 // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size 847 // is larger than the old size, the added memory will not be initialized. If ptr is 0p, then the call is 848 // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not 0p, then the call 849 // is equivalent to free(ptr). Unless ptr is 0p, it must have been returned by an earlier call to malloc(), 850 // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done. 872 // Change the size of the memory block pointed to by oaddr to size bytes. The contents are undefined. If oaddr is 873 // 0p, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and oaddr is 874 // not 0p, then the call is equivalent to free(oaddr). Unless oaddr is 0p, it must have been returned by an earlier 875 // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done. 876 void * resize( void * oaddr, size_t size ) { 877 #ifdef __STATISTICS__ 878 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 879 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 880 #endif // __STATISTICS__ 881 882 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 883 if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases 884 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 885 886 HeapManager.Storage.Header * header; 887 HeapManager.FreeHeader * freeElem; 888 size_t bsize, oalign = 0; 889 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 890 891 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 892 // same size, DO NOT preserve STICKY PROPERTIES. 893 if ( oalign == 0 && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 894 header->kind.real.blockSize &= -2; // no alignment and turn off 0 fill 895 return oaddr; 896 } // if 897 898 // change size, DO NOT preserve STICKY PROPERTIES. 899 free( oaddr ); 900 void * naddr = mallocNoStats( size ); // create new area 901 return naddr; 902 } // resize 903 904 905 // Same as resize() but the contents are unchanged in the range from the start of the region up to the minimum of 906 // the old and new sizes. 851 907 void * realloc( void * oaddr, size_t size ) { 852 908 #ifdef __STATISTICS__ 853 909 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 910 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 854 911 #endif // __STATISTICS__ 855 912 … … 867 924 // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know 868 925 // where to start filling, i.e., do not overwrite existing values in space. 869 //870 // This case does not result in a new profiler entry because the previous one still exists and it must match with871 // the free for this memory. Hence, this realloc does not appear in the profiler output.872 926 return oaddr; 873 927 } // if 874 875 #ifdef __STATISTICS__876 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );877 #endif // __STATISTICS__878 928 879 929 // change size and copy old content to new storage … … 903 953 } // realloc 904 954 905 // The obsolete function memalign() allocates size bytes and returns a pointer to the allocated memory. The memory 906 // address will be a multiple of alignment, which must be a power of two. 955 // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete) 907 956 void * memalign( size_t alignment, size_t size ) { 908 957 #ifdef __STATISTICS__ … … 915 964 916 965 917 // The cmemalign() function is the same as calloc() with memory alignment.918 void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {966 // Same as aalloc() with memory alignment. 967 void * amemalign( size_t alignment, size_t dim, size_t elemSize ) { 919 968 #ifdef __STATISTICS__ 920 969 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 921 __atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST ); 922 #endif // __STATISTICS__ 923 924 return cmemalignNoStats( alignment, noOfElems, elemSize ); 970 __atomic_add_fetch( &cmemalign_storage, dim * elemSize, __ATOMIC_SEQ_CST ); 971 #endif // __STATISTICS__ 972 973 return memalignNoStats( alignment, dim * elemSize ); 974 } // amemalign 975 976 977 // Same as calloc() with memory alignment. 978 void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) { 979 #ifdef __STATISTICS__ 980 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 981 __atomic_add_fetch( &cmemalign_storage, dim * elemSize, __ATOMIC_SEQ_CST ); 982 #endif // __STATISTICS__ 983 984 return cmemalignNoStats( alignment, dim, elemSize ); 925 985 } // cmemalign 926 986 927 // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a928 // multiple of alignment.987 // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple 988 // of alignment. This requirement is universally ignored. 929 989 void * aligned_alloc( size_t alignment, size_t size ) { 930 990 return memalign( alignment, size ); … … 932 992 933 993 934 // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The935 // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of936 // sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later937 // be successfully passed tofree(3).994 // Allocates size bytes and places the address of the allocated memory in *memptr. The address of the allocated 995 // memory shall be a multiple of alignment, which must be a power of two and a multiple of sizeof(void *). If size 996 // is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later be successfully passed to 997 // free(3). 938 998 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 939 999 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment … … 943 1003 } // posix_memalign 944 1004 945 // The obsolete function valloc() allocates size bytes and returns a pointer to the allocated memory. The memory946 // address will be a multiple of thepage size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).1005 // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the 1006 // page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 947 1007 void * valloc( size_t size ) { 948 1008 return memalign( pageSize, size ); … … 950 1010 951 1011 952 // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to 953 // malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior 954 // occurs. If ptr is 0p, no operation is performed. 1012 // Same as valloc but rounds size to multiple of page size. 1013 void * pvalloc( size_t size ) { 1014 return memalign( pageSize, libCeiling( size, pageSize ) ); 1015 } // pvalloc 1016 1017 1018 // Frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() 1019 // or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is 1020 // 0p, no operation is performed. 955 1021 void free( void * addr ) { 956 1022 #ifdef __STATISTICS__ … … 973 1039 974 1040 975 // The malloc_alignment() function returns the alignment of theallocation.1041 // Returns the alignment of an allocation. 976 1042 size_t malloc_alignment( void * addr ) { 977 1043 if ( unlikely( addr == 0p ) ) return libAlign(); // minimum alignment … … 980 1046 return header->kind.fake.alignment & -2; // remove flag from value 981 1047 } else { 982 return libAlign (); // minimum alignment1048 return libAlign(); // minimum alignment 983 1049 } // if 984 1050 } // malloc_alignment 985 1051 986 987 // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc(). 1052 // Set the alignment for an the allocation and return previous alignment or 0 if no alignment. 1053 size_t $malloc_alignment_set( void * addr, size_t alignment ) { 1054 if ( unlikely( addr == 0p ) ) return libAlign(); // minimum alignment 1055 size_t ret; 1056 HeapManager.Storage.Header * header = headerAddr( addr ); 1057 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1058 ret = header->kind.fake.alignment & -2; // remove flag from old value 1059 header->kind.fake.alignment = alignment | 1; // add flag to new value 1060 } else { 1061 ret = 0; // => no alignment to change 1062 } // if 1063 return ret; 1064 } // $malloc_alignment_set 1065 1066 1067 // Returns true if the allocation is zero filled, e.g., allocated by calloc(). 988 1068 bool malloc_zero_fill( void * addr ) { 989 1069 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill 990 1070 HeapManager.Storage.Header * header = headerAddr( addr ); 991 1071 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 992 header = (HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset);993 } // if 994 return (header->kind.real.blockSize & 2) != 0; // zero filled (calloc/cmemalign)?1072 header = realHeader( header ); // backup from fake to real header 1073 } // if 1074 return (header->kind.real.blockSize & 2) != 0; // zero filled ? 995 1075 } // malloc_zero_fill 996 1076 997 998 // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to 999 // a block of memory allocated by malloc(3) or a related function. 1077 // Set allocation is zero filled and return previous zero filled. 1078 bool $malloc_zero_fill_set( void * addr ) { 1079 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill 1080 HeapManager.Storage.Header * header = headerAddr( addr ); 1081 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1082 header = realHeader( header ); // backup from fake to real header 1083 } // if 1084 bool ret = (header->kind.real.blockSize & 2) != 0; // zero filled ? 1085 header->kind.real.blockSize |= 2; // mark as zero filled 1086 return ret; 1087 } // $malloc_zero_fill_set 1088 1089 1090 // Returns original total allocation size (not bucket size) => array size is dimension * sizeif(T). 1091 size_t malloc_size( void * addr ) { 1092 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill 1093 HeapManager.Storage.Header * header = headerAddr( addr ); 1094 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1095 header = realHeader( header ); // backup from fake to real header 1096 } // if 1097 return header->size; 1098 } // malloc_size 1099 1100 // Set allocation size and return previous size. 1101 size_t $malloc_size_set( void * addr, size_t size ) { 1102 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill 1103 HeapManager.Storage.Header * header = headerAddr( addr ); 1104 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1105 header = realHeader( header ); // backup from fake to real header 1106 } // if 1107 size_t ret = header->size; 1108 header->size = size; 1109 return ret; 1110 } // $malloc_size_set 1111 1112 1113 // Returns the number of usable bytes in the block pointed to by ptr, a pointer to a block of memory allocated by 1114 // malloc or a related function. 1000 1115 size_t malloc_usable_size( void * addr ) { 1001 1116 if ( unlikely( addr == 0p ) ) return 0; // null allocation has 0 size … … 1009 1124 1010 1125 1011 // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and 1012 // related functions. 1126 // Prints (on default standard error) statistics about memory allocated by malloc and related functions. 1013 1127 void malloc_stats( void ) { 1014 1128 #ifdef __STATISTICS__ … … 1018 1132 } // malloc_stats 1019 1133 1020 // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes thestatistics.1134 // Changes the file descripter where malloc_stats() writes statistics. 1021 1135 int malloc_stats_fd( int fd __attribute__(( unused )) ) { 1022 1136 #ifdef __STATISTICS__ … … 1030 1144 1031 1145 1032 // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see 1033 // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that 1034 // parameter. 1146 // Adjusts parameters that control the behaviour of the memory-allocation functions (see malloc). The param argument 1147 // specifies the parameter to be modified, and value specifies the new value for that parameter. 1035 1148 int mallopt( int option, int value ) { 1036 1149 choose( option ) { 1037 1150 case M_TOP_PAD: 1038 if ( setHeapExpand( value ) )return 1;1151 heapExpand = ceiling( value, pageSize ); return 1; 1039 1152 case M_MMAP_THRESHOLD: 1040 1153 if ( setMmapStart( value ) ) return 1; 1154 break; 1041 1155 } // switch 1042 1156 return 0; // error, unsupported 1043 1157 } // mallopt 1044 1158 1045 // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a 1046 // suitable argument). 1159 // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument). 1047 1160 int malloc_trim( size_t ) { 1048 1161 return 0; // => impossible to release memory … … 1050 1163 1051 1164 1052 // The malloc_info() function exports an XML string that describes the current state of the memory-allocation1053 // implementation in the caller. The string is printed on the file stream stream. The exported string includes1054 // information about all arenas (see malloc(3)).1165 // Exports an XML string that describes the current state of the memory-allocation implementation in the caller. 1166 // The string is printed on the file stream stream. The exported string includes information about all arenas (see 1167 // malloc). 1055 1168 int malloc_info( int options, FILE * stream ) { 1056 1169 if ( options != 0 ) { errno = EINVAL; return -1; } … … 1059 1172 1060 1173 1061 // The malloc_get_state() function records the current state of all malloc(3) internal bookkeeping variables (but1062 // not the actual contents of the heap or the state of malloc_hook(3) functions pointers). The state is recorded in1063 // a system-dependent opaque data structure dynamically allocated via malloc(3), and a pointer to that data1064 // structure is returned as the function result. (It is the caller's responsibility to free(3)this memory.)1174 // Records the current state of all malloc internal bookkeeping variables (but not the actual contents of the heap 1175 // or the state of malloc_hook functions pointers). The state is recorded in a system-dependent opaque data 1176 // structure dynamically allocated via malloc, and a pointer to that data structure is returned as the function 1177 // result. (The caller must free this memory.) 1065 1178 void * malloc_get_state( void ) { 1066 1179 return 0p; // unsupported … … 1068 1181 1069 1182 1070 // The malloc_set_state() function restores the state of all malloc(3) internal bookkeeping variables to the values1071 // recorded in the opaque datastructure pointed to by state.1183 // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data 1184 // structure pointed to by state. 1072 1185 int malloc_set_state( void * ptr ) { 1073 1186 return 0; // unsupported … … 1077 1190 1078 1191 // Must have CFA linkage to overload with C linkage realloc. 1079 void * re alloc( void * oaddr, size_t nalign, size_t size ) {1192 void * resize( void * oaddr, size_t nalign, size_t size ) { 1080 1193 #ifdef __STATISTICS__ 1081 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 1194 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 1195 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1082 1196 #endif // __STATISTICS__ 1083 1197 1084 1198 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1085 if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases 1086 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 1199 if ( unlikely( size == 0 ) ) { free( oaddr ); return memalignNoStats( nalign, size ); } // special cases 1200 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1201 1087 1202 1088 1203 if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum … … 1095 1210 HeapManager.FreeHeader * freeElem; 1096 1211 size_t bsize, oalign = 0; 1097 headers( "re alloc", oaddr, header, freeElem, bsize, oalign );1212 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1098 1213 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1099 1214 1100 if ( oalign != 0 && (uintptr_t)oaddr % nalign == 0 ) { // has alignment and just happens to work out 1101 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1102 return realloc( oaddr, size ); 1103 } // if 1104 1105 #ifdef __STATISTICS__ 1106 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 1107 #endif // __STATISTICS__ 1108 1109 // change size and copy old content to new storage 1215 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1216 if ( oalign >= libAlign() ) { // fake header ? 1217 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1218 } // if 1219 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 1220 header->kind.real.blockSize &= -2; // turn off 0 fill 1221 return oaddr; 1222 } // if 1223 } // if 1224 1225 // change size 1110 1226 1111 1227 void * naddr; … … 1116 1232 } // if 1117 1233 1234 free( oaddr ); 1235 return naddr; 1236 } // resize 1237 1238 1239 void * realloc( void * oaddr, size_t nalign, size_t size ) { 1240 if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum 1241 #ifdef __CFA_DEBUG__ 1242 else 1243 checkAlign( nalign ); // check alignment 1244 #endif // __CFA_DEBUG__ 1245 1246 HeapManager.Storage.Header * header; 1247 HeapManager.FreeHeader * freeElem; 1248 size_t bsize, oalign = 0; 1249 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1250 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1251 1252 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1253 if ( oalign >= libAlign() ) { // fake header ? 1254 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1255 } // if 1256 return realloc( oaddr, size ); 1257 } // if 1258 1259 // change size and copy old content to new storage 1260 1261 #ifdef __STATISTICS__ 1262 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 1263 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 1264 #endif // __STATISTICS__ 1265 1266 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1267 if ( unlikely( size == 0 ) ) { free( oaddr ); return memalignNoStats( nalign, size ); } // special cases 1268 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1269 1270 void * naddr; 1271 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill 1272 naddr = cmemalignNoStats( nalign, 1, size ); // create new aligned area 1273 } else { 1274 naddr = memalignNoStats( nalign, size ); // create new aligned area 1275 } // if 1276 1118 1277 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 1119 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage av ilable in bucket1278 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage available in bucket 1120 1279 // To preserve prior fill, the entire bucket must be copied versus the size. 1121 1280 memcpy( naddr, oaddr, MIN( odsize, ndsize ) ); // copy bytes
Note:
See TracChangeset
for help on using the changeset viewer.