Changes in / [9aa1317:f1397d14]


Ignore:
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/builtins.c

    r9aa1317 rf1397d14  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov 21 16:31:39 2019
    13 // Update Count     : 101
     12// Last Modified On : Tue Jun 25 18:06:52 2019
     13// Update Count     : 97
    1414//
    1515
     
    6969
    7070// universal typed pointer constant
    71 static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
     71// Compiler issue: there is a problem with anonymous types that do not have a size.
     72static inline forall( dtype DT | sized(DT) ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    7273
    7374// exponentiation operator implementation
  • libcfa/src/heap.cfa

    r9aa1317 rf1397d14  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Nov 22 14:16:30 2019
    13 // Update Count     : 626
     12// Last Modified On : Fri Oct 18 07:42:09 2019
     13// Update Count     : 556
    1414//
    1515
     
    3030#include "malloc.h"
    3131
    32 #define MIN(x, y) (y > x ? x : y)
    3332
    3433static bool traceHeap = false;
     
    5150
    5251
    53 static bool prtFree = false;
    54 
    55 inline bool prtFree() {
    56         return prtFree;
    57 } // prtFree
    58 
    59 bool prtFreeOn() {
    60         bool temp = prtFree;
    61         prtFree = true;
     52static bool checkFree = false;
     53
     54inline bool checkFree() {
     55        return checkFree;
     56} // checkFree
     57
     58bool checkFreeOn() {
     59        bool temp = checkFree;
     60        checkFree = true;
    6261        return temp;
    63 } // prtFreeOn
    64 
    65 bool prtFreeOff() {
    66         bool temp = prtFree;
    67         prtFree = false;
     62} // checkFreeOn
     63
     64bool checkFreeOff() {
     65        bool temp = checkFree;
     66        checkFree = false;
    6867        return temp;
    69 } // prtFreeOff
     68} // checkFreeOff
    7069
    7170
     
    106105static unsigned int allocFree;                                                  // running total of allocations minus frees
    107106
    108 static void prtUnfreed() {
     107static void checkUnfreed() {
    109108        if ( allocFree != 0 ) {
    110109                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     
    113112                //                                      "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    114113                //                                      (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
    115                 // __cfaabi_dbg_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    116         } // if
    117 } // prtUnfreed
     114                // __cfaabi_dbg_bits_write( helpText, len );
     115        } // if
     116} // checkUnfreed
    118117
    119118extern "C" {
     
    124123        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    125124                fclose( stdin ); fclose( stdout );
    126                 prtUnfreed();
     125                checkUnfreed();
    127126        } // heapAppStop
    128127} // extern "C"
     
    135134static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    136135
     136
     137// #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
     138#define ALIGN 16
    137139
    138140#define SPINLOCK 0
     
    145147// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    146148// Break recusion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    147 enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
     149enum { NoBucketSizes = 93 };                                                    // number of buckets sizes
    148150
    149151struct HeapManager {
     
    192194                        } kind; // Kind
    193195                } header; // Header
    194                 char pad[libAlign() - sizeof( Header )];
     196                char pad[ALIGN - sizeof( Header )];
    195197                char data[0];                                                                   // storage
    196198        }; // Storage
    197199
    198         static_assert( libAlign() >= sizeof( Storage ), "libAlign() < sizeof( Storage )" );
     200        static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
    199201
    200202        struct FreeHeader {
     
    228230// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
    229231static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    230         16, 32, 48, 64 + sizeof(HeapManager.Storage), // 4
    231         96, 112, 128 + sizeof(HeapManager.Storage), // 3
    232         160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
    233         320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
    234         640, 768, 896, 1_024 + sizeof(HeapManager.Storage), // 4
    235         1_536, 2_048 + sizeof(HeapManager.Storage), // 2
    236         2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), // 4
    237         6_144, 8_192 + sizeof(HeapManager.Storage), // 2
    238         9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(HeapManager.Storage), // 8
    239         18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(HeapManager.Storage), // 8
    240         36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(HeapManager.Storage), // 8
    241         73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(HeapManager.Storage), // 8
    242         147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(HeapManager.Storage), // 8
    243         294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(HeapManager.Storage), // 8
    244         655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), // 4
    245         1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), // 8
    246         2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(HeapManager.Storage), // 4
     232        16, 32, 48, 64,
     233        64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
     234        256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
     235        1_024 + sizeof(HeapManager.Storage), 1_536, 2_048 + sizeof(HeapManager.Storage), 2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), 6_144,
     236        8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
     237        16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
     238        32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
     239        65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
     240        131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
     241        262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
     242        524_288 + sizeof(HeapManager.Storage), 655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), 1_179_648, 1_310_720, 1_441_792,
     243        1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), 2_621_440, 3_145_728, 3_670_016,
     244        4_194_304 + sizeof(HeapManager.Storage)
    247245};
    248246
     
    253251static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    254252#endif // FASTLOOKUP
    255 
    256253static int mmapFd = -1;                                                                 // fake or actual fd for anonymous file
     254
     255
    257256#ifdef __CFA_DEBUG__
    258257static bool heapBoot = 0;                                                               // detect recursion during boot
     
    260259static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    261260
     261// #comment TD : The return type of this function should be commented
     262static inline bool setMmapStart( size_t value ) {
     263  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     264        mmapStart = value;                                                                      // set global
     265
     266        // find the closest bucket size less than or equal to the mmapStart size
     267        maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     268        assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
     269        assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     270        return false;
     271} // setMmapStart
     272
     273
     274static void ?{}( HeapManager & manager ) with ( manager ) {
     275        pageSize = sysconf( _SC_PAGESIZE );
     276
     277        for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     278                freeLists[i].blockSize = bucketSizes[i];
     279        } // for
     280
     281        #ifdef FASTLOOKUP
     282        unsigned int idx = 0;
     283        for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     284                if ( i > bucketSizes[idx] ) idx += 1;
     285                lookup[i] = idx;
     286        } // for
     287        #endif // FASTLOOKUP
     288
     289        if ( setMmapStart( default_mmap_start() ) ) {
     290                abort( "HeapManager : internal error, mmap start initialization failure." );
     291        } // if
     292        heapExpand = default_heap_expansion();
     293
     294        char * End = (char *)sbrk( 0 );
     295        sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
     296        heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     297} // HeapManager
     298
     299
     300static void ^?{}( HeapManager & ) {
     301        #ifdef __STATISTICS__
     302        // if ( traceHeapTerm() ) {
     303        //      printStats();
     304        //      if ( checkfree() ) checkFree( heapManager, true );
     305        // } // if
     306        #endif // __STATISTICS__
     307} // ~HeapManager
     308
     309
     310static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
     311void memory_startup( void ) {
     312        #ifdef __CFA_DEBUG__
     313        if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
     314                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     315                abort( "boot() : internal error, recursively invoked during system boot." );
     316        } // if
     317        heapBoot = true;
     318        #endif // __CFA_DEBUG__
     319
     320        //assert( heapManager.heapBegin != 0 );
     321        //heapManager{};
     322        if ( heapManager.heapBegin == 0 ) heapManager{};
     323} // memory_startup
     324
     325static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
     326void memory_shutdown( void ) {
     327        ^heapManager{};
     328} // memory_shutdown
     329
    262330
    263331#ifdef __STATISTICS__
    264 // Heap statistics counters.
    265 static unsigned long long int mmap_storage;
     332static unsigned long long int mmap_storage;                             // heap statistics counters
    266333static unsigned int mmap_calls;
    267334static unsigned long long int munmap_storage;
     
    281348static unsigned long long int realloc_storage;
    282349static unsigned int realloc_calls;
    283 // Statistics file descriptor (changed by malloc_stats_fd).
    284 static int statfd = STDERR_FILENO;                                              // default stderr
     350
     351static int statfd;                                                                              // statistics file descriptor (changed by malloc_stats_fd)
     352
    285353
    286354// Use "write" because streams may be shutdown when calls are made.
    287355static void printStats() {
    288356        char helpText[512];
    289         __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
     357        __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
    290358                                                                        "\nHeap statistics:\n"
    291359                                                                        "  malloc: calls %u / storage %llu\n"
     
    337405                                                sbrk_calls, sbrk_storage
    338406                );
    339         __cfaabi_bits_write( fileno( stream ), helpText, len ); // ensures all bytes written or exit
    340         return len;
     407        return write( fileno( stream ), helpText, len );        // -1 => error
    341408} // printStatsXML
    342409#endif // __STATISTICS__
    343 
    344410
    345411// #comment TD : Is this the samething as Out-of-Memory?
     
    352418
    353419static inline void checkAlign( size_t alignment ) {
    354         if ( alignment < libAlign() || ! libPow2( alignment ) ) {
    355                 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
     420        if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
     421                abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
    356422        } // if
    357423} // checkAlign
     
    365431
    366432
    367 static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
    368   if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
    369         mmapStart = value;                                                                      // set global
    370 
    371         // find the closest bucket size less than or equal to the mmapStart size
    372         maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    373         assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    374         assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    375         return false;
    376 } // setMmapStart
    377 
    378 
    379433static inline void checkHeader( bool check, const char * name, void * addr ) {
    380434        if ( unlikely( check ) ) {                                                      // bad address ?
     
    385439} // checkHeader
    386440
    387 
    388 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) {
     441// #comment TD : function should be commented and/or have a more evocative name
     442//               this isn't either a check or a constructor which is what I would expect this function to be
     443static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
    389444        if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    390445                size_t offset = header->kind.fake.offset;
     
    397452} // fakeHeader
    398453
    399 
    400 // <-------+----------------------------------------------------> bsize (bucket size)
    401 // |header |addr
    402 //==================================================================================
    403 //                                | alignment
    404 // <-----------------<------------+-----------------------------> bsize (bucket size)
    405 //                   |fake-header | addr
     454// #comment TD : Why is this a define
    406455#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    407456
    408 // <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
    409 // |header |addr
    410 //==================================================================================
    411 //                                | alignment
    412 // <------------------------------<<---------- dsize --------->>> bsize (bucket size)
    413 //                   |fake-header |addr
    414 #define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
    415 
    416 
    417 static inline bool headers( const char * name __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
     457static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    418458        header = headerAddr( addr );
    419459
    420460        if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
    421                 fakeHeader( header, alignment );
     461                fakeHeader( header, size, alignment );
    422462                size = header->kind.real.blockSize & -3;                // mmap size
    423463                return true;
     
    428468        #endif // __CFA_DEBUG__
    429469
     470        // #comment TD : This code looks weird...
     471        //               It's called as the first statement of both branches of the last if, with the same parameters in all cases
     472
    430473        // header may be safe to dereference
    431         fakeHeader( header, alignment );
     474        fakeHeader( header, size, alignment );
    432475        #ifdef __CFA_DEBUG__
    433476        checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     
    457500                        unlock( extlock );
    458501                        errno = ENOMEM;
    459                         return 0p;
     502                        return 0;
    460503                } // if
    461504                #ifdef __STATISTICS__
     
    498541        // along with the block and is a multiple of the alignment size.
    499542
    500   if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p;
     543  if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0;
    501544        size_t tsize = size + sizeof(HeapManager.Storage);
    502545        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     
    531574                block = freeElem->freeList.pop();
    532575                #endif // SPINLOCK
    533                 if ( unlikely( block == 0p ) ) {                                // no free block ?
     576                if ( unlikely( block == 0 ) ) {                                 // no free block ?
    534577                        #if defined( SPINLOCK )
    535578                        unlock( freeElem->lock );
     
    540583
    541584                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    542   if ( unlikely( block == 0p ) ) return 0p;
     585  if ( unlikely( block == 0 ) ) return 0;
    543586                        #if defined( SPINLOCK )
    544587                } else {
     
    550593                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    551594        } else {                                                                                        // large size => mmap
    552   if ( unlikely( size > ~0ul - pageSize ) ) return 0p;
     595  if ( unlikely( size > ~0ul - pageSize ) ) return 0;
    553596                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    554597                #ifdef __STATISTICS__
     
    568611        } // if
    569612
    570         void * addr = &(block->data);                                           // adjust off header to user bytes
     613        void * area = &(block->data);                                           // adjust off header to user bytes
    571614
    572615        #ifdef __CFA_DEBUG__
    573         assert( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ?
     616        assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
    574617        __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
    575618        if ( traceHeap() ) {
    576619                enum { BufferSize = 64 };
    577620                char helpText[BufferSize];
    578                 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
    579                 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", addr, size );
    580                 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     621                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
     622                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
     623                __cfaabi_dbg_bits_write( helpText, len );
    581624        } // if
    582625        #endif // __CFA_DEBUG__
    583626
    584         return addr;
     627        return area;
    585628} // doMalloc
    586629
     
    588631static inline void doFree( void * addr ) with ( heapManager ) {
    589632        #ifdef __CFA_DEBUG__
    590         if ( unlikely( heapManager.heapBegin == 0p ) ) {
     633        if ( unlikely( heapManager.heapBegin == 0 ) ) {
    591634                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
    592635        } // if
     
    634677                char helpText[BufferSize];
    635678                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    636                 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     679                __cfaabi_dbg_bits_write( helpText, len );
    637680        } // if
    638681        #endif // __CFA_DEBUG__
     
    640683
    641684
    642 size_t prtFree( HeapManager & manager ) with ( manager ) {
     685size_t checkFree( HeapManager & manager ) with ( manager ) {
    643686        size_t total = 0;
    644687        #ifdef __STATISTICS__
    645         __cfaabi_bits_acquire();
    646         __cfaabi_bits_print_nolock( STDERR_FILENO, "\nBin lists (bin size : free blocks on list)\n" );
     688        __cfaabi_dbg_bits_acquire();
     689        __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
    647690        #endif // __STATISTICS__
    648691        for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     
    653696
    654697                #if defined( SPINLOCK )
    655                 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
     698                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
    656699                #else
    657                 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
     700                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
    658701                #endif // SPINLOCK
    659702                        total += size;
     
    664707
    665708                #ifdef __STATISTICS__
    666                 __cfaabi_bits_print_nolock( STDERR_FILENO, "%7zu, %-7u  ", size, N );
    667                 if ( (i + 1) % 8 == 0 ) __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
     709                __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
     710                if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
    668711                #endif // __STATISTICS__
    669712        } // for
    670713        #ifdef __STATISTICS__
    671         __cfaabi_bits_print_nolock( STDERR_FILENO, "\ntotal free blocks:%zu\n", total );
    672         __cfaabi_bits_release();
     714        __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
     715        __cfaabi_dbg_bits_release();
    673716        #endif // __STATISTICS__
    674717        return (char *)heapEnd - (char *)heapBegin - total;
    675 } // prtFree
    676 
    677 
    678 static void ?{}( HeapManager & manager ) with ( manager ) {
    679         pageSize = sysconf( _SC_PAGESIZE );
    680 
    681         for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    682                 freeLists[i].blockSize = bucketSizes[i];
    683         } // for
    684 
    685         #ifdef FASTLOOKUP
    686         unsigned int idx = 0;
    687         for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    688                 if ( i > bucketSizes[idx] ) idx += 1;
    689                 lookup[i] = idx;
    690         } // for
    691         #endif // FASTLOOKUP
    692 
    693         if ( setMmapStart( default_mmap_start() ) ) {
    694                 abort( "HeapManager : internal error, mmap start initialization failure." );
    695         } // if
    696         heapExpand = default_heap_expansion();
    697 
    698         char * End = (char *)sbrk( 0 );
    699         sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    700         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
    701 } // HeapManager
    702 
    703 
    704 static void ^?{}( HeapManager & ) {
    705         #ifdef __STATISTICS__
    706         // if ( traceHeapTerm() ) {
    707         //      printStats();
    708         //      if ( prtfree() ) prtFree( heapManager, true );
    709         // } // if
    710         #endif // __STATISTICS__
    711 } // ~HeapManager
    712 
    713 
    714 static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
    715 void memory_startup( void ) {
    716         #ifdef __CFA_DEBUG__
    717         if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
    718                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    719                 abort( "boot() : internal error, recursively invoked during system boot." );
    720         } // if
    721         heapBoot = true;
    722         #endif // __CFA_DEBUG__
    723 
    724         //assert( heapManager.heapBegin != 0 );
    725         //heapManager{};
    726         if ( heapManager.heapBegin == 0p ) heapManager{};
    727 } // memory_startup
    728 
    729 static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
    730 void memory_shutdown( void ) {
    731         ^heapManager{};
    732 } // memory_shutdown
     718} // checkFree
    733719
    734720
    735721static inline void * mallocNoStats( size_t size ) {             // necessary for malloc statistics
    736722        //assert( heapManager.heapBegin != 0 );
    737         if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ?
    738         void * addr = doMalloc( size );
    739         if ( unlikely( addr == 0p ) ) errno = ENOMEM;           // POSIX
    740         return addr;
     723        if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ?
     724        void * area = doMalloc( size );
     725        if ( unlikely( area == 0 ) ) errno = ENOMEM;            // POSIX
     726        return area;
    741727} // mallocNoStats
    742 
    743 
    744 static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) {
    745         size_t size = noOfElems * elemSize;
    746         char * addr = (char *)mallocNoStats( size );
    747   if ( unlikely( addr == 0p ) ) return 0p;
    748 
    749         HeapManager.Storage.Header * header;
    750         HeapManager.FreeHeader * freeElem;
    751         size_t bsize, alignment;
    752         bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );
    753         #ifndef __CFA_DEBUG__
    754         // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    755         if ( ! mapped )
    756         #endif // __CFA_DEBUG__
    757             // Zero entire data space even when > than size => realloc without a new allocation and zero fill works.
    758             // <-------00000000000000000000000000000000000000000000000000000> bsize (bucket size)
    759             // `-header`-addr                      `-size
    760                 memset( addr, '\0', bsize - sizeof(HeapManager.Storage) ); // set to zeros
    761 
    762         header->kind.real.blockSize |= 2;                                       // mark as zero filled
    763         return addr;
    764 } // callocNoStats
    765728
    766729
     
    782745        // subtract libAlign() because it is already the minimum alignment
    783746        // add sizeof(Storage) for fake header
    784         char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    785   if ( unlikely( addr == 0p ) ) return addr;
     747        // #comment TD : this is the only place that calls doMalloc without calling mallocNoStats, why ?
     748        char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     749  if ( unlikely( area == 0 ) ) return area;
    786750
    787751        // address in the block of the "next" alignment address
    788         char * user = (char *)libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );
     752        char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
    789753
    790754        // address of header from malloc
    791         HeapManager.Storage.Header * realHeader = headerAddr( addr );
     755        HeapManager.Storage.Header * realHeader = headerAddr( area );
    792756        // address of fake header * before* the alignment location
    793757        HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     
    799763        return user;
    800764} // memalignNoStats
    801 
    802 
    803 static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) {
    804         size_t size = noOfElems * elemSize;
    805         char * addr = (char *)memalignNoStats( alignment, size );
    806   if ( unlikely( addr == 0p ) ) return 0p;
    807         HeapManager.Storage.Header * header;
    808         HeapManager.FreeHeader * freeElem;
    809         size_t bsize;
    810         bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );
    811         #ifndef __CFA_DEBUG__
    812         // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    813         if ( ! mapped )
    814         #endif // __CFA_DEBUG__
    815                 memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros
    816         header->kind.real.blockSize |= 2;                               // mark as zero filled
    817 
    818         return addr;
    819 } // cmemalignNoStats
    820765
    821766
     
    831776extern "C" {
    832777        // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not
    833         // initialized. If size is 0, then malloc() returns either 0p, or a unique pointer value that can later be
     778        // initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be
    834779        // successfully passed to free().
    835780        void * malloc( size_t size ) {
     
    843788
    844789        // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to
    845         // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either 0p, or a
     790        // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a
    846791        // unique pointer value that can later be successfully passed to free().
    847792        void * calloc( size_t noOfElems, size_t elemSize ) {
     793                size_t size = noOfElems * elemSize;
    848794                #ifdef __STATISTICS__
    849795                __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    850                 __atomic_add_fetch( &calloc_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
    851                 #endif // __STATISTICS__
    852 
    853                 return callocNoStats( noOfElems, elemSize );
     796                __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
     797                #endif // __STATISTICS__
     798
     799                char * area = (char *)mallocNoStats( size );
     800          if ( unlikely( area == 0 ) ) return 0;
     801
     802                HeapManager.Storage.Header * header;
     803                HeapManager.FreeHeader * freeElem;
     804                size_t asize, alignment;
     805                bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
     806                #ifndef __CFA_DEBUG__
     807                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     808                if ( ! mapped )
     809                #endif // __CFA_DEBUG__
     810                        memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
     811
     812                header->kind.real.blockSize |= 2;                               // mark as zero filled
     813                return area;
    854814        } // calloc
     815
     816        // #comment TD : Document this function
     817        void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
     818                size_t size = noOfElems * elemSize;
     819                #ifdef __STATISTICS__
     820                __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     821                __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
     822                #endif // __STATISTICS__
     823
     824                char * area = (char *)memalignNoStats( alignment, size );
     825          if ( unlikely( area == 0 ) ) return 0;
     826                HeapManager.Storage.Header * header;
     827                HeapManager.FreeHeader * freeElem;
     828                size_t asize;
     829                bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
     830                #ifndef __CFA_DEBUG__
     831                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     832                if ( ! mapped )
     833                        #endif // __CFA_DEBUG__
     834                        memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros
     835                header->kind.real.blockSize |= 2;                               // mark as zero filled
     836
     837                return area;
     838        } // cmemalign
    855839
    856840        // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
    857841        // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
    858         // is larger than the old size, the added memory will not be initialized.  If ptr is 0p, then the call is
    859         // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not 0p, then the call
    860         // is equivalent to free(ptr). Unless ptr is 0p, it must have been returned by an earlier call to malloc(),
     842        // is larger than the old size, the added memory will not be initialized.  If ptr is NULL, then the call is
     843        // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call
     844        // is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(),
    861845        // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
    862         void * realloc( void * oaddr, size_t size ) {
     846        void * realloc( void * addr, size_t size ) {
    863847                #ifdef __STATISTICS__
    864848                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    865849                #endif // __STATISTICS__
    866850
    867           if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
    868           if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
     851          if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases
     852          if ( unlikely( size == 0 ) ) { free( addr ); return 0; }
    869853
    870854                HeapManager.Storage.Header * header;
    871855                HeapManager.FreeHeader * freeElem;
    872                 size_t bsize, oalign = 0;
    873                 headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    874 
    875                 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    876           if ( size <= odsize && odsize <= size * 2 ) { // allow up to 50% wasted storage in smaller size
    877                         // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know
    878                         // where to start filling, i.e., do not overwrite existing values in space.
    879                         //
     856                size_t asize, alignment = 0;
     857                headers( "realloc", addr, header, freeElem, asize, alignment );
     858
     859                size_t usize = asize - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
     860                if ( usize >= size ) {                                                  // already sufficient storage
    880861                        // This case does not result in a new profiler entry because the previous one still exists and it must match with
    881862                        // the free for this memory.  Hence, this realloc does not appear in the profiler output.
    882                         return oaddr;
     863                        return addr;
    883864                } // if
    884865
     
    887868                #endif // __STATISTICS__
    888869
    889                 // change size and copy old content to new storage
    890 
    891                 void * naddr;
    892                 if ( unlikely( oalign != 0 ) ) {                                // previous request memalign?
    893                         if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
    894                                 naddr = cmemalignNoStats( oalign, 1, size ); // create new aligned area
    895                         } else {
    896                                 naddr = memalignNoStats( oalign, size ); // create new aligned area
    897                         } // if
     870                void * area;
     871                if ( unlikely( alignment != 0 ) ) {                             // previous request memalign?
     872                        area = memalign( alignment, size );                     // create new aligned area
    898873                } else {
    899                         if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
    900                                 naddr = callocNoStats( 1, size );               // create new area
    901                         } else {
    902                                 naddr = mallocNoStats( size );                  // create new area
    903                         } // if
     874                        area = mallocNoStats( size );                           // create new area
    904875                } // if
    905           if ( unlikely( naddr == 0p ) ) return 0p;
    906                 headers( "realloc", naddr, header, freeElem, bsize, oalign );
    907                 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
    908                 // To preserve prior fill, the entire bucket must be copied versus the size.
    909                 memcpy( naddr, oaddr, MIN( odsize, ndsize ) );  // copy bytes
    910                 free( oaddr );
    911                 return naddr;
     876          if ( unlikely( area == 0 ) ) return 0;
     877                if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ?
     878                        assert( (header->kind.real.blockSize & 1) == 0 );
     879                        bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
     880                        #ifndef __CFA_DEBUG__
     881                        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     882                        if ( ! mapped )
     883                        #endif // __CFA_DEBUG__
     884                                memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part
     885                        header->kind.real.blockSize |= 2;                       // mark new request as zero fill
     886                } // if
     887                memcpy( area, addr, usize );                                    // copy bytes
     888                free( addr );
     889                return area;
    912890        } // realloc
    913891
     
    920898                #endif // __STATISTICS__
    921899
    922                 return memalignNoStats( alignment, size );
     900                void * area = memalignNoStats( alignment, size );
     901
     902                return area;
    923903        } // memalign
    924 
    925 
    926         // The cmemalign() function is the same as calloc() with memory alignment.
    927         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
    928                 #ifdef __STATISTICS__
    929                 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    930                 __atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
    931                 #endif // __STATISTICS__
    932 
    933                 return cmemalignNoStats( alignment, noOfElems, elemSize );
    934         } // cmemalign
    935904
    936905        // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a
     
    943912        // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The
    944913        // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of
    945         // sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later
     914        // sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later
    946915        // be successfully passed to free(3).
    947916        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    948917          if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
    949918                * memptr = memalign( alignment, size );
    950           if ( unlikely( * memptr == 0p ) ) return ENOMEM;
     919          if ( unlikely( * memptr == 0 ) ) return ENOMEM;
    951920                return 0;
    952921        } // posix_memalign
     
    961930        // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to
    962931        // malloc(), calloc() or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behavior
    963         // occurs. If ptr is 0p, no operation is performed.
     932        // occurs. If ptr is NULL, no operation is performed.
    964933        void free( void * addr ) {
    965934                #ifdef __STATISTICS__
     
    967936                #endif // __STATISTICS__
    968937
    969           if ( unlikely( addr == 0p ) ) {                                       // special case
    970                         // #ifdef __CFA_DEBUG__
    971                         // if ( traceHeap() ) {
    972                         //      #define nullmsg "Free( 0x0 ) size:0\n"
    973                         //      // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    974                         //      __cfaabi_dbg_write( nullmsg, sizeof(nullmsg) - 1 );
    975                         // } // if
    976                         // #endif // __CFA_DEBUG__
     938                // #comment TD : To decrease nesting I would but the special case in the
     939                //               else instead, plus it reads more naturally to have the
     940                //               short / normal case instead
     941                if ( unlikely( addr == 0 ) ) {                                  // special case
     942                        #ifdef __CFA_DEBUG__
     943                        if ( traceHeap() ) {
     944                                #define nullmsg "Free( 0x0 ) size:0\n"
     945                                // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
     946                                __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
     947                        } // if
     948                        #endif // __CFA_DEBUG__
    977949                        return;
    978950                } // exit
     
    981953        } // free
    982954
     955        // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
     956        // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
     957        // parameter.
     958        int mallopt( int option, int value ) {
     959                choose( option ) {
     960                  case M_TOP_PAD:
     961                        if ( setHeapExpand( value ) ) fallthru default;
     962                  case M_MMAP_THRESHOLD:
     963                        if ( setMmapStart( value ) ) fallthru default;
     964                  default:
     965                        // #comment TD : 1 for unsopported feels wrong
     966                        return 1;                                                                       // success, or unsupported
     967                } // switch
     968                return 0;                                                                               // error
     969        } // mallopt
     970
     971        // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
     972        // suitable argument).
     973        int malloc_trim( size_t ) {
     974                return 0;                                                                               // => impossible to release memory
     975        } // malloc_trim
     976
     977        // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
     978        // a block of memory allocated by malloc(3) or a related function.
     979        size_t malloc_usable_size( void * addr ) {
     980          if ( unlikely( addr == 0 ) ) return 0;                        // null allocation has 0 size
     981
     982                HeapManager.Storage.Header * header;
     983                HeapManager.FreeHeader * freeElem;
     984                size_t size, alignment;
     985
     986                headers( "malloc_usable_size", addr, header, freeElem, size, alignment );
     987                size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
     988                return usize;
     989        } // malloc_usable_size
     990
    983991
    984992    // The malloc_alignment() function returns the alignment of the allocation.
    985993        size_t malloc_alignment( void * addr ) {
    986           if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
     994          if ( unlikely( addr == 0 ) ) return libAlign();       // minimum alignment
    987995                HeapManager.Storage.Header * header = headerAddr( addr );
    988996                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    9961004    // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
    9971005        bool malloc_zero_fill( void * addr ) {
    998           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     1006          if ( unlikely( addr == 0 ) ) return false;            // null allocation is not zero fill
    9991007                HeapManager.Storage.Header * header = headerAddr( addr );
    10001008                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    10051013
    10061014
    1007         // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
    1008         // a block of memory allocated by malloc(3) or a related function.
    1009         size_t malloc_usable_size( void * addr ) {
    1010           if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    1011                 HeapManager.Storage.Header * header;
    1012                 HeapManager.FreeHeader * freeElem;
    1013                 size_t bsize, alignment;
    1014 
    1015                 headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
    1016                 return dataStorage( bsize, addr, header );      // data storage in bucket
    1017         } // malloc_usable_size
    1018 
    1019 
    10201015    // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
    10211016    // related functions.
     
    10231018                #ifdef __STATISTICS__
    10241019                printStats();
    1025                 if ( prtFree() ) prtFree( heapManager );
     1020                if ( checkFree() ) checkFree( heapManager );
    10261021                #endif // __STATISTICS__
    10271022        } // malloc_stats
    10281023
    10291024        // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.
    1030         int malloc_stats_fd( int fd __attribute__(( unused )) ) {
     1025        int malloc_stats_fd( int fd ) {
    10311026                #ifdef __STATISTICS__
    10321027                int temp = statfd;
     
    10381033        } // malloc_stats_fd
    10391034
    1040 
    1041         // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
    1042         // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
    1043         // parameter.
    1044         int mallopt( int option, int value ) {
    1045                 choose( option ) {
    1046                   case M_TOP_PAD:
    1047                         if ( setHeapExpand( value ) ) return 1;
    1048                   case M_MMAP_THRESHOLD:
    1049                         if ( setMmapStart( value ) ) return 1;
    1050                 } // switch
    1051                 return 0;                                                                               // error, unsupported
    1052         } // mallopt
    1053 
    1054         // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
    1055         // suitable argument).
    1056         int malloc_trim( size_t ) {
    1057                 return 0;                                                                               // => impossible to release memory
    1058         } // malloc_trim
    1059 
    1060 
    10611035        // The malloc_info() function exports an XML string that describes the current state of the memory-allocation
    10621036        // implementation in the caller.  The string is printed on the file stream stream.  The exported string includes
    10631037        // information about all arenas (see malloc(3)).
    10641038        int malloc_info( int options, FILE * stream ) {
    1065                 if ( options != 0 ) { errno = EINVAL; return -1; }
    10661039                return printStatsXML( stream );
    10671040        } // malloc_info
     
    10731046        // structure is returned as the function result.  (It is the caller's responsibility to free(3) this memory.)
    10741047        void * malloc_get_state( void ) {
    1075                 return 0p;                                                                              // unsupported
     1048                return 0;                                                                               // unsupported
    10761049        } // malloc_get_state
    10771050
     
    10851058
    10861059
    1087 // Must have CFA linkage to overload with C linkage realloc.
    1088 void * realloc( void * oaddr, size_t nalign, size_t size ) {
    1089     #ifdef __STATISTICS__
    1090         __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    1091     #endif // __STATISTICS__
    1092 
    1093   if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
    1094   if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
    1095 
    1096     if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum
    1097         #ifdef __CFA_DEBUG__
    1098     else
    1099                 checkAlign( nalign );                                                   // check alignment
    1100         #endif // __CFA_DEBUG__
    1101 
    1102         HeapManager.Storage.Header * header;
    1103         HeapManager.FreeHeader * freeElem;
    1104         size_t bsize, oalign = 0;
    1105         headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    1106 
    1107     size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    1108 
    1109   if ( oalign != 0 && (uintptr_t)oaddr % nalign == 0 ) { // has alignment and just happens to work out
    1110                 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1111                 return realloc( oaddr, size );
    1112     } // if
    1113 
    1114     #ifdef __STATISTICS__
    1115         __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
    1116     #endif // __STATISTICS__
    1117 
    1118     // change size and copy old content to new storage
    1119 
    1120     void * naddr;
    1121     if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
    1122         naddr = cmemalignNoStats( nalign, 1, size );    // create new aligned area
    1123     } else {
    1124         naddr = memalignNoStats( nalign, size );                // create new aligned area
    1125     } // if
    1126     size_t ndsize = dataStorage( bsize, naddr, header );        // data storage avilable in bucket
    1127         // To preserve prior fill, the entire bucket must be copied versus the size.
    1128     memcpy( naddr, oaddr, MIN( odsize, ndsize ) );              // copy bytes
    1129     free( oaddr );
    1130     return naddr;
    1131 } // realloc
    1132 
    1133 
    11341060// Local Variables: //
    11351061// tab-width: 4 //
  • libcfa/src/stdlib.cfa

    r9aa1317 rf1397d14  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov 20 17:22:47 2019
    13 // Update Count     : 485
     12// Last Modified On : Tue Oct 22 08:57:52 2019
     13// Update Count     : 478
    1414//
    1515
     
    3030        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
    3131                size_t olen = malloc_usable_size( ptr );                // current allocation
    32                 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     32                char * nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    3333                size_t nlen = malloc_usable_size( nptr );               // new allocation
    3434                if ( nlen > olen ) {                                                    // larger ?
    35                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     35                        memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    3636                } // if
    3737                return (T *)nptr;
    3838        } // alloc_set
    3939
     40        T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
     41                char * nptr;
     42                size_t alignment = malloc_alignment( ptr );
     43                if ( align != alignment && (uintptr_t)ptr % align != 0 ) {
     44                        size_t olen = malloc_usable_size( ptr );        // current allocation
     45                        nptr = (char *)memalign( align, olen );
     46                        size_t nlen = malloc_usable_size( nptr );       // new allocation
     47                        size_t lnth = olen < nlen ? olen : nlen;        // min
     48                        memcpy( nptr, ptr, lnth );                                      // initialize storage
     49                        free( ptr );
     50                } else {
     51                        nptr = (char *)ptr;
     52                } // if
     53                return (T *)nptr;
     54        } // alloc_align
     55
     56        T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
     57                char * nptr;
     58                size_t alignment = malloc_alignment( ptr );
     59                if ( align != alignment ) {
     60                        size_t olen = malloc_usable_size( ptr );        // current allocation
     61                        nptr = (char *)memalign( align, dim * sizeof(T) );
     62                        size_t nlen = malloc_usable_size( nptr );       // new allocation
     63                        size_t lnth = olen < nlen ? olen : nlen;        // min
     64                        memcpy( nptr, ptr, lnth );                                      // initialize storage
     65                        free( ptr );
     66                } else {
     67                        nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     68                } // if
     69                return (T *)nptr;
     70        } // alloc_align
     71
    4072        T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
    4173                size_t olen = malloc_usable_size( ptr );                // current allocation
    42                 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    43                 // char * nptr = alloc_align( ptr, align );
     74                char * nptr = alloc_align( ptr, align );
    4475                size_t nlen = malloc_usable_size( nptr );               // new allocation
    4576                if ( nlen > olen ) {                                                    // larger ?
    46                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     77                        memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    4778                } // if
    4879                return (T *)nptr;
  • libcfa/src/stdlib.hfa

    r9aa1317 rf1397d14  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Nov 22 15:13:14 2019
    13 // Update Count     : 399
     12// Last Modified On : Sun Oct 20 22:57:33 2019
     13// Update Count     : 390
    1414//
    1515
     
    2828} // extern "C"
    2929
    30 void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap
    31 
    3230//---------------------------------------
    3331
     
    5250        } // calloc
    5351
    54         T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
     52        T * realloc( T * ptr, size_t size ) {
     53                if ( unlikely( ptr == 0 ) ) return malloc();
    5554                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
    5655        } // realloc
     
    6059        } // memalign
    6160
    62         T * cmemalign( size_t align, size_t dim  ) {
    63                 return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
    64         } // cmemalign
    65 
    6661        T * aligned_alloc( size_t align ) {
    6762                return (T *)aligned_alloc( align, sizeof(T) );  // C aligned_alloc
     
    8479
    8580        T * alloc( T ptr[], size_t dim ) {                                      // realloc
    86                 return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     81                return realloc( ptr, dim * sizeof(T) );
    8782        } // alloc
    8883
     
    123118        } // alloc_align
    124119
    125         T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
    126                 return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    127         } // alloc_align
    128 
    129         T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
    130                 return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc
    131         } // alloc_align
    132 
    133120        T * alloc_align_set( size_t align, char fill ) {
    134121                return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
     
    155142
    156143forall( dtype T | sized(T) ) {
     144        T * alloc_align( T ptr[], size_t align );                       // realign
     145        T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
    157146        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill
    158147} // distribution
  • tests/.expect/alloc-ERROR.txt

    r9aa1317 rf1397d14  
    1 alloc.cfa:317:1 error: No reasonable alternatives for expression Applying untyped:
     1alloc.cfa:311:1 error: No reasonable alternatives for expression Applying untyped:
    22  Name: ?=?
    33...to:
     
    1919
    2020
    21 alloc.cfa:318:1 error: No reasonable alternatives for expression Applying untyped:
     21alloc.cfa:312:1 error: No reasonable alternatives for expression Applying untyped:
    2222  Name: ?=?
    2323...to:
     
    3939
    4040
    41 alloc.cfa:319:1 error: No reasonable alternatives for expression Applying untyped:
     41alloc.cfa:313:1 error: No reasonable alternatives for expression Applying untyped:
    4242  Name: ?=?
    4343...to:
     
    5050
    5151
    52 alloc.cfa:320:1 error: No reasonable alternatives for expression Applying untyped:
     52alloc.cfa:314:1 error: No reasonable alternatives for expression Applying untyped:
    5353  Name: ?=?
    5454...to:
  • tests/.expect/alloc.txt

    r9aa1317 rf1397d14  
    3030CFA resize array alloc
    31310xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    32 CFA resize array alloc
     32CFA resize array alloc, fill
    33330xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
    34 CFA resize array alloc
     34CFA resize array alloc, fill
    35350xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    3636CFA resize array alloc, fill
    37 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
     370xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
    3838
    3939C   memalign 42 42.5
  • tests/alloc.cfa

    r9aa1317 rf1397d14  
    1010// Created On       : Wed Feb  3 07:56:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Nov 22 15:34:19 2019
    13 // Update Count     : 404
     12// Last Modified On : Sun Oct 20 21:45:21 2019
     13// Update Count     : 391
    1414//
    1515
     
    126126
    127127        p = alloc( p, 2 * dim );                            // CFA resize array alloc
    128         for ( i; dim ~ 2 * dim ) { p[i] = 0x1010101; }          // fill upper part
     128        for ( i; dim ~ 2 * dim ) { p[i] = 0x1010101; }
    129129        printf( "CFA resize array alloc\n" );
    130130        for ( i; 2 * dim ) { printf( "%#x ", p[i] ); }
     
    139139
    140140        p = alloc_set( p, 3 * dim, fill );                                      // CFA resize array alloc, fill
    141         printf( "CFA resize array alloc\n" );
     141        printf( "CFA resize array alloc, fill\n" );
    142142        for ( i; 3 * dim ) { printf( "%#x ", p[i] ); }
    143143        printf( "\n" );
     
    145145
    146146        p = alloc_set( p, dim, fill );                                          // CFA resize array alloc, fill
    147         printf( "CFA resize array alloc\n" );
     147        printf( "CFA resize array alloc, fill\n" );
    148148        for ( i; dim ) { printf( "%#x ", p[i] ); }
    149149        printf( "\n" );
  • tests/heap.cfa

    r9aa1317 rf1397d14  
    1010// Created On       : Tue Nov  6 17:54:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov 20 16:10:24 2019
    13 // Update Count     : 25
     12// Last Modified On : Fri Jul 19 08:22:34 2019
     13// Update Count     : 19
    1414//
    1515
     
    7474                size_t s = (i + 1) * 20;
    7575                char * area = (char *)malloc( s );
    76                 if ( area == 0p ) abort( "malloc/free out of memory" );
     76                if ( area == 0 ) abort( "malloc/free out of memory" );
    7777                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
    7878                area[malloc_usable_size( area ) - 1] = '\345';  // fill ultimate byte
     
    8383                size_t s = i + 1;                                                               // +1 to make initialization simpler
    8484                locns[i] = (char *)malloc( s );
    85                 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );
     85                if ( locns[i] == 0 ) abort( "malloc/free out of memory" );
    8686                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
    8787                locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
     
    9999                size_t s = i + default_mmap_start();                    // cross over point
    100100                char * area = (char *)malloc( s );
    101                 if ( area == 0p ) abort( "malloc/free out of memory" );
     101                if ( area == 0 ) abort( "malloc/free out of memory" );
    102102                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
    103103                area[malloc_usable_size( area ) - 1] = '\345';  // fill ultimate byte
     
    108108                size_t s = i + default_mmap_start();                    // cross over point
    109109                locns[i] = (char *)malloc( s );
    110                 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );
     110                if ( locns[i] == 0 ) abort( "malloc/free out of memory" );
    111111                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
    112112                locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
     
    124124                size_t s = (i + 1) * 20;
    125125                char * area = (char *)calloc( 5, s );
    126                 if ( area == 0p ) abort( "calloc/free out of memory" );
     126                if ( area == 0 ) abort( "calloc/free out of memory" );
    127127                if ( area[0] != '\0' || area[s - 1] != '\0' ||
    128128                         area[malloc_usable_size( area ) - 1] != '\0' ||
     
    136136                size_t s = i + 1;
    137137                locns[i] = (char *)calloc( 5, s );
    138                 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );
     138                if ( locns[i] == 0 ) abort( "calloc/free out of memory" );
    139139                if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' ||
    140140                         locns[i][malloc_usable_size( locns[i] ) - 1] != '\0' ||
     
    155155                size_t s = i + default_mmap_start();                    // cross over point
    156156                char * area = (char *)calloc( 1, s );
    157                 if ( area == 0p ) abort( "calloc/free out of memory" );
     157                if ( area == 0 ) abort( "calloc/free out of memory" );
    158158                if ( area[0] != '\0' || area[s - 1] != '\0' ) abort( "calloc/free corrupt storage4.1" );
    159159                if ( area[malloc_usable_size( area ) - 1] != '\0' ) abort( "calloc/free corrupt storage4.2" );
     
    167167                size_t s = i + default_mmap_start();                    // cross over point
    168168                locns[i] = (char *)calloc( 1, s );
    169                 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );
     169                if ( locns[i] == 0 ) abort( "calloc/free out of memory" );
    170170                if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' ||
    171171                         locns[i][malloc_usable_size( locns[i] ) - 1] != '\0' ||
     
    189189                for ( s; 1 ~ NoOfAllocs ) {                                             // allocation of size 0 can return null
    190190                        char * area = (char *)memalign( a, s );
    191                         if ( area == 0p ) abort( "memalign/free out of memory" );
    192                         //sout | i | area;
     191                        if ( area == 0 ) abort( "memalign/free out of memory" );
     192                        //sout | i | " " | area;
    193193                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    194194                                abort( "memalign/free bad alignment : memalign(%d,%d) = %p", (int)a, s, area );
    195195                        } // if
    196                         area[0] = '\345'; area[s - 1] = '\345';         // fill first/last byte
     196                        area[0] = '\345'; area[s - 1] = '\345'; // fill first/last byte
    197197                        area[malloc_usable_size( area ) - 1] = '\345'; // fill ultimate byte
    198198                        free( area );
     
    207207                        size_t s = i + default_mmap_start();            // cross over point
    208208                        char * area = (char *)memalign( a, s );
    209                         if ( area == 0p ) abort( "memalign/free out of memory" );
    210                         //sout | i | area;
     209                        if ( area == 0 ) abort( "memalign/free out of memory" );
     210                        //sout | i | " " | area;
    211211                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    212212                                abort( "memalign/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)s, area );
     
    223223                // initial N byte allocation
    224224                char * area = (char *)calloc( 5, i );
    225                 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
     225                if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
    226226                if ( area[0] != '\0' || area[i - 1] != '\0' ||
    227227                         area[malloc_usable_size( area ) - 1] != '\0' ||
     
    231231                for ( s; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
    232232                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    233                         if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
     233                        if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
    234234                        if ( area[0] != '\0' || area[s - 1] != '\0' ||
    235235                                 area[malloc_usable_size( area ) - 1] != '\0' ||
     
    245245                size_t s = i + default_mmap_start();                    // cross over point
    246246                char * area = (char *)calloc( 1, s );
    247                 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
     247                if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
    248248                if ( area[0] != '\0' || area[s - 1] != '\0' ||
    249249                         area[malloc_usable_size( area ) - 1] != '\0' ||
     
    253253                for ( r; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
    254254                        area = (char *)realloc( area, r );                      // attempt to reuse storage
    255                         if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
     255                        if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
    256256                        if ( area[0] != '\0' || area[r - 1] != '\0' ||
    257257                                 area[malloc_usable_size( area ) - 1] != '\0' ||
     
    267267                // initial N byte allocation
    268268                char * area = (char *)memalign( a, amount );    // aligned N-byte allocation
    269                 if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ?
    270                 //sout | alignments[a] | area;
     269                if ( area == 0 ) abort( "memalign/realloc/free out of memory" ); // no storage ?
     270                //sout | alignments[a] | " " | area;
    271271                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    272272                        abort( "memalign/realloc/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)amount, area );
     
    278278                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" );
    279279                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    280                         if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ?
    281                         //sout | i | area;
     280                        if ( area == 0 ) abort( "memalign/realloc/free out of memory" ); // no storage ?
     281                        //sout | i | " " | area;
    282282                        if ( (size_t)area % a != 0 ) {                          // check for initial alignment
    283283                                abort( "memalign/realloc/free bad alignment %p", area );
     
    294294                for ( s; 1 ~ limit ) {                                                  // allocation of size 0 can return null
    295295                        char * area = (char *)cmemalign( a, 1, s );
    296                         if ( area == 0p ) abort( "cmemalign/free out of memory" );
    297                         //sout | i | area;
     296                        if ( area == 0 ) abort( "cmemalign/free out of memory" );
     297                        //sout | i | " " | area;
    298298                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    299299                                abort( "cmemalign/free bad alignment : cmemalign(%d,%d) = %p", (int)a, s, area );
     
    313313                // initial N byte allocation
    314314                char * area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation
    315                 if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
    316                 //sout | alignments[a] | area;
     315                if ( area == 0 ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
     316                //sout | alignments[a] | " " | area;
    317317                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    318318                        abort( "cmemalign/realloc/free bad alignment : cmemalign(%d,%d) = %p", (int)a, (int)amount, area );
     
    327327                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc/free corrupt storage2" );
    328328                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    329                         if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
    330                         //sout | i | area;
     329                        if ( area == 0 ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
     330                        //sout | i | " " | area;
    331331                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    332332                                abort( "cmemalign/realloc/free bad alignment %p", area );
    333                         } // if
    334                         if ( area[s - 1] != '\0' || area[s - 1] != '\0' ||
    335                                  area[malloc_usable_size( area ) - 1] != '\0' ||
    336                                  ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" );
    337                         area[s - 1] = '\345';                                           // fill last byte
    338                 } // for
    339                 free( area );
    340         } // for
    341 
    342         // check memalign/realloc with align/free
    343 
    344         amount = 2;
    345         for ( a; libAlign() ~= limit ~ a ) {                            // generate powers of 2
    346                 // initial N byte allocation
    347                 char * area = (char *)memalign( a, amount );    // aligned N-byte allocation
    348                 if ( area == 0p ) abort( "memalign/realloc with align/free out of memory" ); // no storage ?
    349                 //sout | alignments[a] | area | endl;
    350                 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    351                         abort( "memalign/realloc with align/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)amount, area );
    352                 } // if
    353                 area[0] = '\345'; area[amount - 2] = '\345';    // fill first/penultimate byte
    354 
    355                 // Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
    356                 for ( s; amount ~ 256 * 1024 ) {                                // start at initial memory request
    357                         if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" );
    358                         area = (char *)realloc( area, a * 2, s );       // attempt to reuse storage
    359                         if ( area == 0p ) abort( "memalign/realloc with align/free out of memory" ); // no storage ?
    360                         //sout | i | area | endl;
    361                         if ( (size_t)area % a * 2 != 0 ) {                      // check for initial alignment
    362                                 abort( "memalign/realloc with align/free bad alignment %p", area );
    363                         } // if
    364                         area[s - 1] = '\345';                                           // fill last byte
    365                 } // for
    366                 free( area );
    367         } // for
    368 
    369         // check cmemalign/realloc with align/free
    370 
    371         amount = 2;
    372         for ( size_t a = libAlign() + libAlign(); a <= limit; a += a ) { // generate powers of 2
    373                 // initial N byte allocation
    374                 char *area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation
    375                 if ( area == 0p ) abort( "cmemalign/realloc with align/free out of memory" ); // no storage ?
    376                 //sout | alignments[a] | area | endl;
    377                 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    378                         abort( "cmemalign/realloc with align/free bad alignment : cmemalign(%d,%d) = %p", (int)a, (int)amount, area );
    379                 } // if
    380                 if ( area[0] != '\0' || area[amount - 1] != '\0' ||
    381                          area[malloc_usable_size( area ) - 1] != '\0' ||
    382                          ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc with align/free corrupt storage1" );
    383                 area[0] = '\345'; area[amount - 2] = '\345';    // fill first/penultimate byte
    384 
    385                 // Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
    386                 for ( int s = amount; s < 256 * 1024; s += 1 ) { // start at initial memory request
    387                         if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc with align/free corrupt storage2" );
    388                         area = (char *)realloc( area, a * 2, s );       // attempt to reuse storage
    389                         if ( area == 0p ) abort( "cmemalign/realloc with align/free out of memory" ); // no storage ?
    390                         //sout | i | area | endl;
    391                         if ( (size_t)area % a * 2 != 0 || malloc_alignment( area ) != a * 2 ) { // check for initial alignment
    392                                 abort( "cmemalign/realloc with align/free bad alignment %p %jd %jd", area, malloc_alignment( area ), a * 2 );
    393333                        } // if
    394334                        if ( area[s - 1] != '\0' || area[s - 1] != '\0' ||
Note: See TracChangeset for help on using the changeset viewer.