Changes in libcfa/src/heap.cfa [1076d05:e3fea42]
- File:
-
- 1 edited
-
libcfa/src/heap.cfa (modified) (47 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/heap.cfa
r1076d05 re3fea42 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 6 17:29:26202013 // Update Count : 72712 // Last Modified On : Tue Feb 4 10:04:51 2020 13 // Update Count : 648 14 14 // 15 15 … … 19 19 #include <errno.h> // errno 20 20 #include <string.h> // memset, memcpy 21 #include <limits.h> // ULONG_MAX22 21 extern "C" { 23 22 #include <sys/mman.h> // mmap, munmap 24 23 } // extern "C" 25 24 25 // #comment TD : Many of these should be merged into math I believe 26 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" // ceiling33 32 34 33 #define MIN(x, y) (y > x ? x : y) … … 82 81 }; 83 82 83 size_t default_mmap_start() __attribute__(( weak )) { 84 return __CFA_DEFAULT_MMAP_START__; 85 } // default_mmap_start 86 84 87 size_t default_heap_expansion() __attribute__(( weak )) { 85 88 return __CFA_DEFAULT_HEAP_EXPANSION__; 86 89 } // default_heap_expansion 87 88 size_t default_mmap_start() __attribute__(( weak )) {89 return __CFA_DEFAULT_MMAP_START__;90 } // default_mmap_start91 90 92 91 … … 151 150 union { 152 151 // FreeHeader * home; // allocated block points back to home locations (must overlay alignment) 153 // 2nd low-order bit => zero filled154 152 void * home; // allocated block points back to home locations (must overlay alignment) 155 153 size_t blockSize; // size for munmap (must overlay alignment) … … 171 169 struct FakeHeader { 172 170 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 173 // 1st low-order bit => fake header & alignment 174 uint32_t alignment; 171 uint32_t alignment; // low-order bits of home/blockSize used for tricks 175 172 #endif // __ORDER_LITTLE_ENDIAN__ 176 173 … … 182 179 } fake; // FakeHeader 183 180 } kind; // Kind 184 size_t size; // allocation size in bytes185 181 } header; // Header 186 182 char pad[libAlign() - sizeof( Header )]; … … 266 262 static unsigned long long int free_storage; 267 263 static unsigned int free_calls; 268 static unsigned long long int aalloc_storage;269 static unsigned int aalloc_calls;270 264 static unsigned long long int calloc_storage; 271 265 static unsigned int calloc_calls; 272 266 static unsigned long long int memalign_storage; 273 267 static unsigned int memalign_calls; 274 static unsigned long long int amemalign_storage;275 static unsigned int amemalign_calls;276 268 static unsigned long long int cmemalign_storage; 277 269 static unsigned int cmemalign_calls; 278 static unsigned long long int resize_storage;279 static unsigned int resize_calls;280 270 static unsigned long long int realloc_storage; 281 271 static unsigned int realloc_calls; … … 285 275 // Use "write" because streams may be shutdown when calls are made. 286 276 static void printStats() { 287 char helpText[ 1024];277 char helpText[512]; 288 278 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), 289 279 "\nHeap statistics:\n" 290 280 " malloc: calls %u / storage %llu\n" 291 " aalloc: calls %u / storage %llu\n"292 281 " calloc: calls %u / storage %llu\n" 293 282 " memalign: calls %u / storage %llu\n" 294 " amemalign: calls %u / storage %llu\n"295 283 " cmemalign: calls %u / storage %llu\n" 296 " resize: calls %u / storage %llu\n"297 284 " realloc: calls %u / storage %llu\n" 298 285 " free: calls %u / storage %llu\n" … … 301 288 " sbrk: calls %u / storage %llu\n", 302 289 malloc_calls, malloc_storage, 303 aalloc_calls, calloc_storage,304 290 calloc_calls, calloc_storage, 305 291 memalign_calls, memalign_storage, 306 amemalign_calls, amemalign_storage,307 292 cmemalign_calls, cmemalign_storage, 308 resize_calls, resize_storage,309 293 realloc_calls, realloc_storage, 310 294 free_calls, free_storage, … … 316 300 317 301 static int printStatsXML( FILE * stream ) { // see malloc_info 318 char helpText[ 1024];302 char helpText[512]; 319 303 int len = snprintf( helpText, sizeof(helpText), 320 304 "<malloc version=\"1\">\n" … … 323 307 "</sizes>\n" 324 308 "<total type=\"malloc\" count=\"%u\" size=\"%llu\"/>\n" 325 "<total type=\"aalloc\" count=\"%u\" size=\"%llu\"/>\n"326 309 "<total type=\"calloc\" count=\"%u\" size=\"%llu\"/>\n" 327 310 "<total type=\"memalign\" count=\"%u\" size=\"%llu\"/>\n" 328 "<total type=\"amemalign\" count=\"%u\" size=\"%llu\"/>\n"329 311 "<total type=\"cmemalign\" count=\"%u\" size=\"%llu\"/>\n" 330 "<total type=\"resize\" count=\"%u\" size=\"%llu\"/>\n"331 312 "<total type=\"realloc\" count=\"%u\" size=\"%llu\"/>\n" 332 313 "<total type=\"free\" count=\"%u\" size=\"%llu\"/>\n" … … 336 317 "</malloc>", 337 318 malloc_calls, malloc_storage, 338 aalloc_calls, aalloc_storage,339 319 calloc_calls, calloc_storage, 340 320 memalign_calls, memalign_storage, 341 amemalign_calls, amemalign_storage,342 321 cmemalign_calls, cmemalign_storage, 343 resize_calls, resize_storage,344 322 realloc_calls, realloc_storage, 345 323 free_calls, free_storage, … … 359 337 // ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) ); 360 338 // } // noMemory 339 340 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 } // if 345 } // checkAlign 346 347 348 static inline bool setHeapExpand( size_t value ) { 349 if ( heapExpand < pageSize ) return true; 350 heapExpand = value; 351 return false; 352 } // setHeapExpand 361 353 362 354 … … 377 369 378 370 static inline bool setMmapStart( size_t value ) { // true => mmapped, false => sbrk 379 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false;371 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true; 380 372 mmapStart = value; // set global 381 373 … … 384 376 assert( maxBucketsUsed < NoBucketSizes ); // subscript failure ? 385 377 assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ? 386 return true;378 return false; 387 379 } // setMmapStart 388 389 390 // <-------+----------------------------------------------------> bsize (bucket size)391 // |header |addr392 //==================================================================================393 // align/offset |394 // <-----------------<------------+-----------------------------> bsize (bucket size)395 // |fake-header | addr396 #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 |addr401 //==================================================================================402 // align/offset |403 // <------------------------------<<---------- dsize --------->>> bsize (bucket size)404 // |fake-header |addr405 #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 } // if412 } // checkAlign413 380 414 381 … … 424 391 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) { 425 392 if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ? 393 size_t offset = header->kind.fake.offset; 426 394 alignment = header->kind.fake.alignment & -2; // remove flag from value 427 395 #ifdef __CFA_DEBUG__ 428 396 checkAlign( alignment ); // check alignment 429 397 #endif // __CFA_DEBUG__ 430 header = realHeader( header ); // backup from fake to real header398 header = (HeapManager.Storage.Header *)((char *)header - offset); 431 399 } // if 432 400 } // fakeHeader 401 402 403 // <-------+----------------------------------------------------> bsize (bucket size) 404 // |header |addr 405 //================================================================================== 406 // | alignment 407 // <-----------------<------------+-----------------------------> bsize (bucket size) 408 // |fake-header | addr 409 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) )) 410 411 // <-------<<--------------------- dsize ---------------------->> bsize (bucket size) 412 // |header |addr 413 //================================================================================== 414 // | alignment 415 // <------------------------------<<---------- dsize --------->>> bsize (bucket size) 416 // |fake-header |addr 417 #define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header )) 433 418 434 419 … … 443 428 444 429 #ifdef __CFA_DEBUG__ 445 checkHeader( addr < heapBegin , name, addr );// bad low address ?430 checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ? 446 431 #endif // __CFA_DEBUG__ 447 432 … … 502 487 // along with the block and is a multiple of the alignment size. 503 488 504 if ( unlikely( size > ULONG_MAX- sizeof(HeapManager.Storage) ) ) return 0p;489 if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p; 505 490 size_t tsize = size + sizeof(HeapManager.Storage); 506 491 if ( likely( tsize < mmapStart ) ) { // small size => sbrk … … 554 539 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 555 540 } else { // large size => mmap 556 if ( unlikely( size > ULONG_MAX- pageSize ) ) return 0p;541 if ( unlikely( size > ~0ul - pageSize ) ) return 0p; 557 542 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size 558 543 #ifdef __STATISTICS__ … … 572 557 } // if 573 558 574 block->header.size = size; // store allocation size575 559 void * addr = &(block->data); // adjust off header to user bytes 576 560 … … 696 680 #endif // FASTLOOKUP 697 681 698 if ( !setMmapStart( default_mmap_start() ) ) {682 if ( setMmapStart( default_mmap_start() ) ) { 699 683 abort( "HeapManager : internal error, mmap start initialization failure." ); 700 684 } // if … … 702 686 703 687 char * end = (char *)sbrk( 0 ); 704 heapBegin = heapEnd = sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment 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 705 690 } // HeapManager 706 691 … … 728 713 //assert( heapManager.heapBegin != 0 ); 729 714 //heapManager{}; 730 if ( heapManager.heapBegin == 0p ) heapManager{}; // sanity check715 if ( heapManager.heapBegin == 0p ) heapManager{}; 731 716 } // memory_startup 732 717 … … 740 725 //assert( heapManager.heapBegin != 0 ); 741 726 if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ? 742 #if __SIZEOF_POINTER__ == 8743 verify( size < ((typeof(size_t))1 << 48) );744 #endif // __SIZEOF_POINTER__ == 8745 727 void * addr = doMalloc( size ); 746 728 if ( unlikely( addr == 0p ) ) errno = ENOMEM; // POSIX … … 749 731 750 732 751 static inline void * callocNoStats( size_t dim, size_t elemSize ) {752 size_t size = dim* elemSize;733 static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) { 734 size_t size = noOfElems * elemSize; 753 735 char * addr = (char *)mallocNoStats( size ); 754 736 if ( unlikely( addr == 0p ) ) return 0p; … … 808 790 809 791 810 static inline void * cmemalignNoStats( size_t alignment, size_t dim, size_t elemSize ) {811 size_t size = dim* elemSize;792 static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) { 793 size_t size = noOfElems * elemSize; 812 794 char * addr = (char *)memalignNoStats( alignment, size ); 813 795 if ( unlikely( addr == 0p ) ) return 0p; … … 821 803 #endif // __CFA_DEBUG__ 822 804 memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros 823 824 header->kind.real.blockSize |= 2; // mark as zero filled 805 header->kind.real.blockSize |= 2; // mark as zero filled 806 825 807 return addr; 826 808 } // cmemalignNoStats … … 837 819 838 820 extern "C" { 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(). 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(). 841 824 void * malloc( size_t size ) { 842 825 #ifdef __STATISTICS__ … … 848 831 } // malloc 849 832 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 ) { 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 ) { 864 837 #ifdef __STATISTICS__ 865 838 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST ); 866 __atomic_add_fetch( &calloc_storage, dim* elemSize, __ATOMIC_SEQ_CST );867 #endif // __STATISTICS__ 868 869 return callocNoStats( dim, elemSize );839 __atomic_add_fetch( &calloc_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST ); 840 #endif // __STATISTICS__ 841 842 return callocNoStats( noOfElems, elemSize ); 870 843 } // calloc 871 844 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. 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. 907 851 void * realloc( void * oaddr, size_t size ) { 908 852 #ifdef __STATISTICS__ 909 853 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 910 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );911 854 #endif // __STATISTICS__ 912 855 … … 924 867 // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know 925 868 // 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 with 871 // the free for this memory. Hence, this realloc does not appear in the profiler output. 926 872 return oaddr; 927 873 } // if 874 875 #ifdef __STATISTICS__ 876 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 877 #endif // __STATISTICS__ 928 878 929 879 // change size and copy old content to new storage … … 953 903 } // realloc 954 904 955 // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete) 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. 956 907 void * memalign( size_t alignment, size_t size ) { 957 908 #ifdef __STATISTICS__ … … 964 915 965 916 966 // Same as aalloc() with memory alignment.967 void * amemalign( size_t alignment, size_t dim, size_t elemSize ) {917 // The cmemalign() function is the same as calloc() with memory alignment. 918 void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) { 968 919 #ifdef __STATISTICS__ 969 920 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 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 ); 921 __atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST ); 922 #endif // __STATISTICS__ 923 924 return cmemalignNoStats( alignment, noOfElems, elemSize ); 985 925 } // cmemalign 986 926 987 // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple988 // of alignment. This requirement is universally ignored.927 // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a 928 // multiple of alignment. 989 929 void * aligned_alloc( size_t alignment, size_t size ) { 990 930 return memalign( alignment, size ); … … 992 932 993 933 994 // Allocates size bytes and places the address of the allocated memory in *memptr. The address of the allocated995 // memory shall be a multiple of alignment, which must be a power of two and a multiple of sizeof(void *). If size996 // is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later be successfully passed to997 // free(3).934 // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The 935 // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of 936 // sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later 937 // be successfully passed to free(3). 998 938 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 999 939 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment … … 1003 943 } // posix_memalign 1004 944 1005 // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the1006 // page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).945 // The obsolete function valloc() allocates size bytes and returns a pointer to the allocated memory. The memory 946 // address will be a multiple of the page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 1007 947 void * valloc( size_t size ) { 1008 948 return memalign( pageSize, size ); … … 1010 950 1011 951 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. 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. 1021 955 void free( void * addr ) { 1022 956 #ifdef __STATISTICS__ … … 1039 973 1040 974 1041 // Returns the alignment of anallocation.975 // The malloc_alignment() function returns the alignment of the allocation. 1042 976 size_t malloc_alignment( void * addr ) { 1043 977 if ( unlikely( addr == 0p ) ) return libAlign(); // minimum alignment … … 1046 980 return header->kind.fake.alignment & -2; // remove flag from value 1047 981 } else { 1048 return libAlign (); // minimum alignment982 return libAlign (); // minimum alignment 1049 983 } // if 1050 984 } // malloc_alignment 1051 985 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(). 986 987 // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc(). 1068 988 bool malloc_zero_fill( void * addr ) { 1069 989 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill 1070 990 HeapManager.Storage.Header * header = headerAddr( addr ); 1071 991 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1072 header = realHeader( header ); // backup from fake to real header992 header = (HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset); 1073 993 } // if 1074 return (header->kind.real.blockSize & 2) != 0; // zero filled ?994 return (header->kind.real.blockSize & 2) != 0; // zero filled (calloc/cmemalign) ? 1075 995 } // malloc_zero_fill 1076 996 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. 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. 1115 1000 size_t malloc_usable_size( void * addr ) { 1116 1001 if ( unlikely( addr == 0p ) ) return 0; // null allocation has 0 size … … 1124 1009 1125 1010 1126 // Prints (on default standard error) statistics about memory allocated by malloc and related functions. 1011 // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and 1012 // related functions. 1127 1013 void malloc_stats( void ) { 1128 1014 #ifdef __STATISTICS__ … … 1132 1018 } // malloc_stats 1133 1019 1134 // Changes the file descripter where malloc_stats() writesstatistics.1020 // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics. 1135 1021 int malloc_stats_fd( int fd __attribute__(( unused )) ) { 1136 1022 #ifdef __STATISTICS__ … … 1144 1030 1145 1031 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. 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. 1148 1035 int mallopt( int option, int value ) { 1149 1036 choose( option ) { 1150 1037 case M_TOP_PAD: 1151 heapExpand = ceiling( value, pageSize );return 1;1038 if ( setHeapExpand( value ) ) return 1; 1152 1039 case M_MMAP_THRESHOLD: 1153 1040 if ( setMmapStart( value ) ) return 1; 1154 break;1155 1041 } // switch 1156 1042 return 0; // error, unsupported 1157 1043 } // mallopt 1158 1044 1159 // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument). 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). 1160 1047 int malloc_trim( size_t ) { 1161 1048 return 0; // => impossible to release memory … … 1163 1050 1164 1051 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 (see1167 // malloc).1052 // The malloc_info() function exports an XML string that describes the current state of the memory-allocation 1053 // implementation in the caller. The string is printed on the file stream stream. The exported string includes 1054 // information about all arenas (see malloc(3)). 1168 1055 int malloc_info( int options, FILE * stream ) { 1169 1056 if ( options != 0 ) { errno = EINVAL; return -1; } … … 1172 1059 1173 1060 1174 // Records the current state of all malloc internal bookkeeping variables (but not the actual contents of the heap1175 // or the state of malloc_hook functions pointers). The state is recorded in a system-dependent opaque data1176 // structure dynamically allocated via malloc, and a pointer to that data structure is returned as the function1177 // result. (The caller must freethis memory.)1061 // The malloc_get_state() function records the current state of all malloc(3) internal bookkeeping variables (but 1062 // not the actual contents of the heap or the state of malloc_hook(3) functions pointers). The state is recorded in 1063 // a system-dependent opaque data structure dynamically allocated via malloc(3), and a pointer to that data 1064 // structure is returned as the function result. (It is the caller's responsibility to free(3) this memory.) 1178 1065 void * malloc_get_state( void ) { 1179 1066 return 0p; // unsupported … … 1181 1068 1182 1069 1183 // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data1184 // structure pointed to by state.1070 // The malloc_set_state() function restores the state of all malloc(3) internal bookkeeping variables to the values 1071 // recorded in the opaque data structure pointed to by state. 1185 1072 int malloc_set_state( void * ptr ) { 1186 1073 return 0; // unsupported … … 1190 1077 1191 1078 // Must have CFA linkage to overload with C linkage realloc. 1192 void * re size( void * oaddr, size_t nalign, size_t size ) {1079 void * realloc( void * oaddr, size_t nalign, size_t size ) { 1193 1080 #ifdef __STATISTICS__ 1194 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 1195 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1081 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 1196 1082 #endif // __STATISTICS__ 1197 1083 1198 1084 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1199 if ( unlikely( size == 0 ) ) { free( oaddr ); return memalignNoStats( nalign, size ); } // special cases 1200 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1201 1085 if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases 1086 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 1202 1087 1203 1088 if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum … … 1210 1095 HeapManager.FreeHeader * freeElem; 1211 1096 size_t bsize, oalign = 0; 1212 headers( "re size", oaddr, header, freeElem, bsize, oalign );1097 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1213 1098 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1214 1099 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 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 1226 1110 1227 1111 void * naddr; … … 1232 1116 } // if 1233 1117 1234 free( oaddr );1235 return naddr;1236 } // resize1237 1238 1239 void * realloc( void * oaddr, size_t nalign, size_t size ) {1240 if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum1241 #ifdef __CFA_DEBUG__1242 else1243 checkAlign( nalign ); // check alignment1244 #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 bucket1251 1252 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match1253 if ( oalign >= libAlign() ) { // fake header ?1254 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)1255 } // if1256 return realloc( oaddr, size );1257 } // if1258 1259 // change size and copy old content to new storage1260 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 cases1268 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size );1269 1270 void * naddr;1271 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill1272 naddr = cmemalignNoStats( nalign, 1, size ); // create new aligned area1273 } else {1274 naddr = memalignNoStats( nalign, size ); // create new aligned area1275 } // if1276 1277 1118 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 1278 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage av ailable in bucket1119 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket 1279 1120 // To preserve prior fill, the entire bucket must be copied versus the size. 1280 1121 memcpy( naddr, oaddr, MIN( odsize, ndsize ) ); // copy bytes
Note:
See TracChangeset
for help on using the changeset viewer.