Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    rb6830d74 r58b6d1b  
    1 // #comment TD : this file uses both spaces and tabs for indentation
    2 
    31//
    42// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
     
    1210// Created On       : Tue Dec 19 21:58:35 2017
    1311// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Sat Aug 11 08:22:16 2018
    15 // Update Count     : 495
     12// Last Modified On : Tue Jul 31 18:08:50 2018
     13// Update Count     : 470
    1614//
    1715
     
    2422} // extern "C"
    2523
    26 // #comment TD : Many of these should be merged into math I believe
    2724#include "bits/align.hfa"                                                                       // libPow2
    2825#include "bits/defs.hfa"                                                                        // likely, unlikely
     
    3936
    4037size_t default_mmap_start() __attribute__(( weak )) {
    41         return __CFA_DEFAULT_MMAP_START__;
     38    return __CFA_DEFAULT_MMAP_START__;
    4239} // default_mmap_start
    4340
    4441size_t default_heap_expansion() __attribute__(( weak )) {
    45         return __CFA_DEFAULT_HEAP_EXPANSION__;
     42    return __CFA_DEFAULT_HEAP_EXPANSION__;
    4643} // default_heap_expansion
    4744
     
    6562#endif // LOCKFREE
    6663
    67 // #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
    6864#define ALIGN 16
    6965
     
    7975
    8076
    81 static bool traceHeap = false;
    82 
    83 inline bool traceHeap() {
     77static _Bool traceHeap = false;
     78
     79inline _Bool traceHeap() {
    8480        return traceHeap;
    8581} // traceHeap
    8682
    87 bool traceHeapOn() {
    88         bool temp = traceHeap;
     83_Bool traceHeapOn() {
     84        _Bool temp = traceHeap;
    8985        traceHeap = true;
    9086        return temp;
    9187} // traceHeapOn
    9288
    93 bool traceHeapOff() {
    94         bool temp = traceHeap;
     89_Bool traceHeapOff() {
     90        _Bool temp = traceHeap;
    9591        traceHeap = false;
    9692        return temp;
     
    9894
    9995
    100 static bool checkFree = false;
    101 
    102 inline bool checkFree() {
     96static _Bool checkFree = false;
     97
     98inline _Bool checkFree() {
    10399        return checkFree;
    104100} // checkFree
    105101
    106 bool checkFreeOn() {
    107         bool temp = checkFree;
     102_Bool checkFreeOn() {
     103        _Bool temp = checkFree;
    108104        checkFree = true;
    109105        return temp;
    110106} // checkFreeOn
    111107
    112 bool checkFreeOff() {
    113         bool temp = checkFree;
     108_Bool checkFreeOff() {
     109        _Bool temp = checkFree;
    114110        checkFree = false;
    115111        return temp;
     
    117113
    118114
    119 // static bool traceHeapTerm = false;
    120 
    121 // inline bool traceHeapTerm() {
     115// static _Bool traceHeapTerm = false;
     116
     117// inline _Bool traceHeapTerm() {
    122118//      return traceHeapTerm;
    123119// } // traceHeapTerm
    124120
    125 // bool traceHeapTermOn() {
    126 //      bool temp = traceHeapTerm;
     121// _Bool traceHeapTermOn() {
     122//      _Bool temp = traceHeapTerm;
    127123//      traceHeapTerm = true;
    128124//      return temp;
    129125// } // traceHeapTermOn
    130126
    131 // bool traceHeapTermOff() {
    132 //      bool temp = traceHeapTerm;
     127// _Bool traceHeapTermOff() {
     128//      _Bool temp = traceHeapTerm;
    133129//      traceHeapTerm = false;
    134130//      return temp;
     
    137133
    138134#ifdef __CFA_DEBUG__
    139 static unsigned int allocFree;                                                  // running total of allocations minus frees
     135static unsigned int allocfree;                                                  // running total of allocations minus frees
     136static unsigned int appStart;                                                   // storage allocation when application starts
    140137
    141138static void checkUnfreed() {
    142         if ( allocFree != 0 ) {
     139        unsigned int total = allocfree - appStart;
     140    if ( total != 0 ) {
    143141                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    144142                // char helpText[512];
    145                 // int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
     143                // int len = snprintf( helpText, 512, "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
    146144                //                                      "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    147                 //                                      (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
     145                //                                      (long int)getpid(), total, total ); // always print the UNIX pid
    148146                // __cfaabi_dbg_bits_write( helpText, len );
    149         } // if
     147    } // if
    150148} // checkUnfreed
    151149
    152150extern "C" {
    153151void heapAppStart() {                                                                   // called by __cfaabi_appready_startup
    154         allocFree = 0;
     152        appStart = allocfree;
    155153} // heapAppStart
    156154
    157155void heapAppStop() {                                                                    // called by __cfaabi_appready_startdown
    158         fclose( stdin ); fclose( stdout );
    159156        checkUnfreed();
    160157} // heapAppStop
     
    171168                                struct RealHeader {
    172169                                        union {
    173                                                 // #comment TD : this code use byte size but the comment uses bit size
    174 
    175170                                                struct {                                                // 32-bit word => 64-bit header, 64-bit word => 128-bit header
    176171                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
     
    192187
    193188                                                };
    194 
    195                                                 // #comment TD : C++ code
    196189                                                #if BUCKLOCK == LOCKFREE
    197190                                                Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
    198191                                                #endif // LOCKFREE
    199192                                        };
    200                                 } real; // RealHeader
     193                                } real;
    201194                                struct FakeHeader {
    202195                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     
    209202                                        uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
    210203                                        #endif // __ORDER_BIG_ENDIAN__
    211                                 } fake; // FakeHeader
    212                         } kind; // Kind
     204                                } fake;
     205                        } kind;
    213206            } header; // Header
    214207            char pad[ALIGN - sizeof( Header )];
     
    223216            Storage * freeList;
    224217                #elif BUCKLOCK == LOCKFREE
    225                 // #comment TD : C++ code
    226218            StackLF<Storage> freeList;
    227219                #else
     
    249241static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    250242
    251 // #comment TD : This array is not const but it feels like it should be
    252243// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
    253244static unsigned int bucketSizes[NoBucketSizes] @= {             // different bucket sizes
    254         16, 32, 48, 64,
    255         64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
    256         256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
    257         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,
    258         8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
    259         16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
    260         32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
    261         65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
    262         131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
    263         262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
    264         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,
    265         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,
    266         4_194_304 + sizeof(HeapManager.Storage)
     245    16, 32, 48, 64,
     246    64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
     247    256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
     248    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,
     249    8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
     250    16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
     251    32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
     252    65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
     253    131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
     254    262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
     255    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,
     256    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,
     257    4_194_304 + sizeof(HeapManager.Storage)
    267258};
    268259#ifdef FASTLOOKUP
     
    273264
    274265#ifdef __CFA_DEBUG__
    275 static bool heapBoot = 0;                                                               // detect recursion during boot
     266static _Bool heapBoot = 0;                                                              // detect recursion during boot
    276267#endif // __CFA_DEBUG__
    277268static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    278269
    279 // #comment TD : The return type of this function should be commented
    280 static inline bool setMmapStart( size_t value ) {
    281         if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
    282         mmapStart = value;                                                                      // set global
    283 
    284         // find the closest bucket size less than or equal to the mmapStart size
    285         maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    286         assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    287         assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    288         return false;
     270
     271static inline _Bool setMmapStart( size_t value ) {
     272    if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     273    mmapStart = value;                                                                  // set global
     274
     275    // find the closest bucket size less than or equal to the mmapStart size
     276    maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     277    assert( maxBucketsUsed < NoBucketSizes );                   // subscript failure ?
     278    assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     279    return false;
    289280} // setMmapStart
    290281
    291282
    292283static void ?{}( HeapManager & manager ) with ( manager ) {
    293         pageSize = sysconf( _SC_PAGESIZE );
    294 
    295         for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     284    pageSize = sysconf( _SC_PAGESIZE );
     285
     286    for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    296287                freeLists[i].blockSize = bucketSizes[i];
    297         } // for
     288    } // for
    298289
    299290        #ifdef FASTLOOKUP
    300         unsigned int idx = 0;
    301         for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     291    unsigned int idx = 0;
     292    for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    302293                if ( i > bucketSizes[idx] ) idx += 1;
    303294                lookup[i] = idx;
    304         } // for
     295    } // for
    305296        #endif // FASTLOOKUP
    306297
    307         if ( setMmapStart( default_mmap_start() ) ) {
     298    if ( setMmapStart( default_mmap_start() ) ) {
    308299                abort( "HeapManager : internal error, mmap start initialization failure." );
    309         } // if
    310         heapExpand = default_heap_expansion();
    311 
    312         char * End = (char *)sbrk( 0 );
    313         sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    314         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     300    } // if
     301    heapExpand = default_heap_expansion();
     302
     303    char * End = (char *)sbrk( 0 );
     304    sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
     305    heapBegin = heapEnd = sbrk( 0 );                                    // get new start point
    315306} // HeapManager
    316307
     
    336327        #endif // __CFA_DEBUG__
    337328
    338         // #comment TD : This assertion seems redundent with the above code
    339329        assert( heapManager.heapBegin == 0 );
    340330        heapManager{};
     
    372362// Use "write" because streams may be shutdown when calls are made.
    373363static void printStats() {
    374         char helpText[512];
    375         __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
     364    char helpText[512];
     365        __cfaabi_dbg_bits_print_buffer( helpText, 512,
    376366                        "\nHeap statistics:\n"
    377367                        "  malloc: calls %u / storage %llu\n"
     
    396386} // printStats
    397387
    398 // #comment TD : Why do we have this?
     388
    399389static int printStatsXML( FILE * stream ) {
    400         char helpText[512];
    401         int len = snprintf( helpText, sizeof(helpText),
     390    char helpText[512];
     391    int len = snprintf( helpText, 512,
    402392                                                "<malloc version=\"1\">\n"
    403393                                                "<heap nr=\"0\">\n"
     
    424414                                                sbrk_calls, sbrk_storage
    425415                );
    426         return write( fileno( stream ), helpText, len );        // -1 => error
     416    return write( fileno( stream ), helpText, len );    // -1 => error
    427417} // printStatsXML
    428418#endif // __STATISTICS__
    429419
    430 // #comment TD : Is this the samething as Out-of-Memory?
     420
    431421static inline void noMemory() {
    432         abort( "Heap memory exhausted at %zu bytes.\n"
     422    abort( "Heap memory exhausted at %zu bytes.\n"
    433423                        "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    434424                        ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
     
    437427
    438428static inline void checkAlign( size_t alignment ) {
    439         if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
     429    if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
    440430                abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
    441         } // if
     431    } // if
    442432} // checkAlign
    443433
    444434
    445 static inline bool setHeapExpand( size_t value ) {
    446         if ( heapExpand < pageSize ) return true;
    447         heapExpand = value;
    448         return false;
     435static inline _Bool setHeapExpand( size_t value ) {
     436    if ( heapExpand < pageSize ) return true;
     437    heapExpand = value;
     438    return false;
    449439} // setHeapExpand
    450440
    451441
    452 static inline void checkHeader( bool check, const char * name, void * addr ) {
    453         if ( unlikely( check ) ) {                                                      // bad address ?
     442static inline void checkHeader( _Bool check, const char * name, void * addr ) {
     443    if ( unlikely( check ) ) {                                                  // bad address ?
    454444                abort( "Attempt to %s storage %p with address outside the heap.\n"
    455445                                "Possible cause is duplicate free on same block or overwriting of memory.",
    456446                                name, addr );
    457         } // if
     447    } // if
    458448} // checkHeader
    459449
    460 // #comment TD : function should be commented and/or have a more evocative name
    461 //               this isn't either a check or a constructor which is what I would expect this function to be
     450
    462451static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
    463         if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
     452    if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    464453                size_t offset = header->kind.fake.offset;
    465454                alignment = header->kind.fake.alignment & -2;   // remove flag from value
     
    468457                #endif // __CFA_DEBUG__
    469458                header = (HeapManager.Storage.Header *)((char *)header - offset);
    470         } // if
     459    } // if
    471460} // fakeHeader
    472461
    473 // #comment TD : Why is this a define
     462
    474463#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    475464
    476 static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    477         header = headerAddr( addr );
    478 
    479         if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
     465static inline _Bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
     466    header = headerAddr( addr );
     467
     468    if ( unlikely( heapEnd < addr ) ) {                                 // mmapped ?
    480469                fakeHeader( header, size, alignment );
    481470                size = header->kind.real.blockSize & -3;                // mmap size
    482471                return true;
    483         } // if
     472    } // if
    484473
    485474        #ifdef __CFA_DEBUG__
    486                         checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     475    checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    487476        #endif // __CFA_DEBUG__
    488 
    489         // #comment TD : This code looks weird...
    490         //               It's called as the first statement of both branches of the last if, with the same parameters in all cases
    491 
    492                 // header may be safe to dereference
    493                 fakeHeader( header, size, alignment );
     477    // header may be safe to dereference
     478    fakeHeader( header, size, alignment );
    494479        #ifdef __CFA_DEBUG__
    495                         checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     480    checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    496481        #endif // __CFA_DEBUG__
    497482
    498                 freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
     483    freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
    499484        #ifdef __CFA_DEBUG__
    500                         if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
    501                         abort( "Attempt to %s storage %p with corrupted header.\n"
    502                                 "Possible cause is duplicate free on same block or overwriting of header information.",
    503                                         name, addr );
    504                         } // if
     485    if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
     486                abort( "Attempt to %s storage %p with corrupted header.\n"
     487                          "Possible cause is duplicate free on same block or overwriting of header information.",
     488                           name, addr );
     489    } // if
    505490        #endif // __CFA_DEBUG__
    506                 size = freeElem->blockSize;
    507                 return false;
     491    size = freeElem->blockSize;
     492    return false;
    508493} // headers
    509494
    510495
    511496static inline void * extend( size_t size ) with ( heapManager ) {
    512         lock( extlock __cfaabi_dbg_ctx2 );
    513         ptrdiff_t rem = heapRemaining - size;
    514         if ( rem < 0 ) {
     497    lock( extlock __cfaabi_dbg_ctx2 );
     498    ptrdiff_t rem = heapRemaining - size;
     499    if ( rem < 0 ) {
    515500                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    516501
     
    530515#endif // __CFA_DEBUG__
    531516                rem = heapRemaining + increase - size;
    532         } // if
    533 
    534         HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
    535         heapRemaining = rem;
    536         heapEnd = (char *)heapEnd + size;
    537         unlock( extlock );
    538         return block;
     517    } // if
     518
     519    HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
     520    heapRemaining = rem;
     521    heapEnd = (char *)heapEnd + size;
     522    unlock( extlock );
     523    return block;
    539524} // extend
    540525
    541526
    542527static inline void * doMalloc( size_t size ) with ( heapManager ) {
    543         HeapManager.Storage * block;
    544 
    545         // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
    546         // along with the block and is a multiple of the alignment size.
    547 
    548         size_t tsize = size + sizeof(HeapManager.Storage);
    549         if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     528    HeapManager.Storage * block;
     529
     530    // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
     531    // along with the block and is a multiple of the alignment size.
     532
     533    size_t tsize = size + sizeof(HeapManager.Storage);
     534    if ( likely( tsize < mmapStart ) ) {                                // small size => sbrk
    550535                HeapManager.FreeHeader * freeElem =
    551536                        #ifdef FASTLOOKUP
     
    560545
    561546                #if defined( SPINLOCK )
    562                         lock( freeElem->lock __cfaabi_dbg_ctx2 );
    563                         block = freeElem->freeList;                                             // remove node from stack
     547                lock( freeElem->lock __cfaabi_dbg_ctx2 );
     548                block = freeElem->freeList;                                             // remove node from stack
    564549                #else
    565                         block = freeElem->freeList.pop();
     550                block = freeElem->freeList.pop();
    566551                #endif // SPINLOCK
    567552                if ( unlikely( block == 0 ) ) {                                 // no free block ?
     
    582567
    583568                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    584                 } else {                                                                                        // large size => mmap
     569    } else {                                                                                    // large size => mmap
    585570                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    586571                #ifdef __STATISTICS__
    587                         __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
    588                         __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );
     572                __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
     573                __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );
    589574                #endif // __STATISTICS__
    590575                block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
     
    598583#endif // __CFA_DEBUG__
    599584                block->header.kind.real.blockSize = tsize;              // storage size for munmap
    600                 } // if
    601 
    602                 void * area = &(block->data);                                           // adjust off header to user bytes
     585    } // if
     586
     587    void * area = &(block->data);                                               // adjust off header to user bytes
    603588
    604589        #ifdef __CFA_DEBUG__
    605                         assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
    606                         __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
    607                 if ( traceHeap() ) {
    608                         enum { BufferSize = 64 };
    609                         char helpText[BufferSize];
    610                         int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
    611                         // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
    612                         __cfaabi_dbg_bits_write( helpText, len );
    613                 } // if
     590    assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
     591    __atomic_add_fetch( &allocfree, tsize, __ATOMIC_SEQ_CST );
     592        if ( traceHeap() ) {
     593                enum { BufferSize = 64 };
     594                char helpText[BufferSize];
     595                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
     596                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
     597                __cfaabi_dbg_bits_write( helpText, len );
     598        } // if
    614599        #endif // __CFA_DEBUG__
    615600
    616         return area;
     601    return area;
    617602} // doMalloc
    618603
     
    620605static inline void doFree( void * addr ) with ( heapManager ) {
    621606        #ifdef __CFA_DEBUG__
    622                 if ( unlikely( heapManager.heapBegin == 0 ) ) {
    623                         abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
    624                 } // if
     607    if ( unlikely( heapManager.heapBegin == 0 ) ) {
     608                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
     609    } // if
    625610        #endif // __CFA_DEBUG__
    626611
    627         HeapManager.Storage.Header * header;
    628         HeapManager.FreeHeader * freeElem;
    629         size_t size, alignment;                                                         // not used (see realloc)
    630 
    631         if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
    632                 #ifdef __STATISTICS__
    633                         __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );
    634                         __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST );
     612    HeapManager.Storage.Header * header;
     613    HeapManager.FreeHeader * freeElem;
     614    size_t size, alignment;                                                             // not used (see realloc)
     615
     616    if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
     617                #ifdef __STATISTICS__
     618                __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );
     619                __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST );
    635620                #endif // __STATISTICS__
    636621                if ( munmap( header, size ) == -1 ) {
     
    641626                        #endif // __CFA_DEBUG__
    642627                } // if
    643                 } else {
     628    } else {
    644629                #ifdef __CFA_DEBUG__
    645                         // Set free memory to garbage so subsequent usages might fail.
    646                         memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
     630                // Set free memory to garbage so subsequent usages might fail.
     631                memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
    647632                #endif // __CFA_DEBUG__
    648633
    649634                #ifdef __STATISTICS__
    650                         free_storage += size;
     635                free_storage += size;
    651636                #endif // __STATISTICS__
    652637                #if defined( SPINLOCK )
    653                         lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    654                         header->kind.real.next = freeElem->freeList;    // push on stack
    655                         freeElem->freeList = (HeapManager.Storage *)header;
    656                         unlock( freeElem->lock );                                               // release spin lock
     638                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
     639                header->kind.real.next = freeElem->freeList;    // push on stack
     640                freeElem->freeList = (HeapManager.Storage *)header;
     641                unlock( freeElem->lock );                                               // release spin lock
    657642                #else
    658                         freeElem->freeList.push( *(HeapManager.Storage *)header );
     643                freeElem->freeList.push( *(HeapManager.Storage *)header );
    659644                #endif // SPINLOCK
    660                 } // if
     645    } // if
    661646
    662647        #ifdef __CFA_DEBUG__
    663                  __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );
    664                 if ( traceHeap() ) {
    665                         char helpText[64];
    666                         int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    667                         __cfaabi_dbg_bits_write( helpText, len );
    668                 } // if
     648    __atomic_add_fetch( &allocfree, -size, __ATOMIC_SEQ_CST );
     649    if ( traceHeap() ) {
     650                enum { BufferSize = 64 };
     651                char helpText[BufferSize];
     652                int len = snprintf( helpText, BufferSize, "Free( %p ) size:%zu\n", addr, size );
     653                __cfaabi_dbg_bits_write( helpText, len );
     654    } // if
    669655        #endif // __CFA_DEBUG__
    670656} // doFree
     
    672658
    673659size_t checkFree( HeapManager & manager ) with ( manager ) {
    674         size_t total = 0;
     660    size_t total = 0;
    675661        #ifdef __STATISTICS__
    676                 __cfaabi_dbg_bits_acquire();
    677                 __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
     662    __cfaabi_dbg_bits_acquire();
     663    __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
    678664        #endif // __STATISTICS__
    679         for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     665    for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
    680666                size_t size = freeLists[i].blockSize;
    681667                #ifdef __STATISTICS__
    682668                unsigned int N = 0;
    683669                #endif // __STATISTICS__
    684 
    685670                #if defined( SPINLOCK )
    686671                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
     
    692677                        N += 1;
    693678                        #endif // __STATISTICS__
    694                 } // for
    695 
    696                 #ifdef __STATISTICS__
    697                         __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
    698                         if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
     679            } // for
     680                #ifdef __STATISTICS__
     681            __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
     682            if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
    699683                #endif // __STATISTICS__
    700684        } // for
    701685        #ifdef __STATISTICS__
    702                 __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
    703                 __cfaabi_dbg_bits_release();
     686        __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
     687        __cfaabi_dbg_bits_release();
    704688        #endif // __STATISTICS__
    705689        return (char *)heapEnd - (char *)heapBegin - total;
    706690} // checkFree
    707691
    708 // #comment TD : This is not a good name, plus this feels like it could easily be folded into doMalloc
     692
    709693static inline void * malloc2( size_t size ) {                   // necessary for malloc statistics
    710694        assert( heapManager.heapBegin != 0 );
    711         void * area = doMalloc( size );
    712         if ( unlikely( area == 0 ) ) errno = ENOMEM;            // POSIX
    713         return area;
     695    void * area = doMalloc( size );
     696    if ( unlikely( area == 0 ) ) errno = ENOMEM;                // POSIX
     697    return area;
    714698} // malloc2
    715699
     
    717701static inline void * memalign2( size_t alignment, size_t size ) { // necessary for malloc statistics
    718702#ifdef __CFA_DEBUG__
    719         checkAlign( alignment );                                                        // check alignment
     703    checkAlign( alignment );                                                    // check alignment
    720704#endif // __CFA_DEBUG__
    721705
    722         // if alignment <= default alignment, do normal malloc as two headers are unnecessary
    723         if ( unlikely( alignment <= libAlign() ) ) return malloc2( size );
    724 
    725         // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for
    726         // administrative storage. NOTE, WHILE THERE ARE 2 HEADERS, THE FIRST ONE IS IMPLICITLY CREATED BY DOMALLOC.
    727         //      .-------------v-----------------v----------------v----------,
    728         //      | Real Header | ... padding ... |   Fake Header  | data ... |
    729         //      `-------------^-----------------^-+--------------^----------'
    730         //      |<--------------------------------' offset/align |<-- alignment boundary
    731 
    732         // subtract libAlign() because it is already the minimum alignment
    733         // add sizeof(Storage) for fake header
    734         // #comment TD : this is the only place that calls doMalloc without calling malloc2, why ?
    735         char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    736         if ( unlikely( area == 0 ) ) return area;
    737 
    738         // address in the block of the "next" alignment address
    739         char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
    740 
    741         // address of header from malloc
    742         HeapManager.Storage.Header * realHeader = headerAddr( area );
    743         // address of fake header * before* the alignment location
    744         HeapManager.Storage.Header * fakeHeader = headerAddr( user );
    745         // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
    746         fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
    747         // SKULLDUGGERY: odd alignment imples fake header
    748         fakeHeader->kind.fake.alignment = alignment | 1;
    749 
    750         return user;
     706    // if alignment <= default alignment, do normal malloc as two headers are unnecessary
     707    if ( unlikely( alignment <= libAlign() ) ) return malloc2( size );
     708
     709    // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for
     710    // administrative storage. NOTE, WHILE THERE ARE 2 HEADERS, THE FIRST ONE IS IMPLICITLY CREATED BY DOMALLOC.
     711    //      .-------------v-----------------v----------------v----------,
     712    //      | Real Header | ... padding ... |   Fake Header  | data ... |
     713    //      `-------------^-----------------^-+--------------^----------'
     714    //      |<--------------------------------' offset/align |<-- alignment boundary
     715
     716    // subtract libAlign() because it is already the minimum alignment
     717    // add sizeof(Storage) for fake header
     718    char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     719    if ( unlikely( area == 0 ) ) return area;
     720
     721    // address in the block of the "next" alignment address
     722    char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
     723
     724    // address of header from malloc
     725    HeapManager.Storage.Header * realHeader = headerAddr( area );
     726    // address of fake header * before* the alignment location
     727    HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     728    // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
     729    fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
     730    // SKULLDUGGERY: odd alignment imples fake header
     731    fakeHeader->kind.fake.alignment = alignment | 1;
     732
     733    return user;
    751734} // memalign2
    752735
    753736
    754737extern "C" {
    755         // The malloc() function allocates size bytes and returns a pointer to the
    756         // allocated memory. The memory is not initialized. If size is 0, then malloc()
    757         // returns either NULL, or a unique pointer value that can later be successfully
    758         // passed to free().
    759         void * malloc( size_t size ) {
    760                 #ifdef __STATISTICS__
    761                         __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST );
    762                         __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST );
     738    void * malloc( size_t size ) {
     739                #ifdef __STATISTICS__
     740                __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST );
     741                __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST );
    763742                #endif // __STATISTICS__
    764743
    765744                return malloc2( size );
    766                 } // malloc
    767 
    768         // The calloc() function allocates memory for an array of nmemb elements of
    769         // size bytes each and returns a pointer to the allocated memory. The memory
    770         // is set to zero. If nmemb or size is 0, then calloc() returns either NULL,
    771         // or a unique pointer value that can later be successfully passed to free().
    772                 void * calloc( size_t noOfElems, size_t elemSize ) {
     745    } // malloc
     746
     747
     748    void * calloc( size_t noOfElems, size_t elemSize ) {
    773749                size_t size = noOfElems * elemSize;
    774750                #ifdef __STATISTICS__
    775                         __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    776                         __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
     751                __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
     752                __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
    777753                #endif // __STATISTICS__
    778754
    779755                char * area = (char *)malloc2( size );
    780756                if ( unlikely( area == 0 ) ) return 0;
    781 
    782757                HeapManager.Storage.Header * header;
    783758                HeapManager.FreeHeader * freeElem;
    784759                size_t asize, alignment;
    785                 bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
     760                _Bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
    786761                #ifndef __CFA_DEBUG__
    787762                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     
    789764                #endif // __CFA_DEBUG__
    790765                        memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
    791 
    792766                header->kind.real.blockSize |= 2;               // mark as zero filled
    793767                return area;
    794                 } // calloc
    795 
    796         // #comment TD : Document this function
    797         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
     768    } // calloc
     769
     770
     771    void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
    798772                size_t size = noOfElems * elemSize;
    799773                #ifdef __STATISTICS__
    800                         __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    801                         __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
     774                __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     775                __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
    802776                #endif // __STATISTICS__
    803777
     
    807781                HeapManager.FreeHeader * freeElem;
    808782                size_t asize;
    809                 bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
     783                _Bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
    810784                #ifndef __CFA_DEBUG__
    811785                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     
    816790
    817791                return area;
    818                 } // cmemalign
    819 
    820         // The realloc() function changes the size of the memory block pointed to by
    821         // ptr to size bytes. The contents will be unchanged in the range from the
    822         // start of the region up to the minimum of the old and new sizes. If the new
    823         // size is larger than the old size, the added memory will not be initialized.
    824         // If ptr is NULL, then the call is equivalent to malloc(size), for all values
    825         // of size; if size is equal to zero, and ptr is not NULL, then the call is
    826         // equivalent to free(ptr). Unless ptr is NULL, it must have been returned by
    827         // an earlier call to malloc(), calloc() or realloc(). If the area pointed to
    828         // was moved, a free(ptr) is done.
    829                 void * realloc( void * addr, size_t size ) {
    830                 #ifdef __STATISTICS__
    831                         __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     792    } // cmemalign
     793
     794
     795    void * realloc( void * addr, size_t size ) {
     796                #ifdef __STATISTICS__
     797                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    832798                #endif // __STATISTICS__
    833799
     
    848814
    849815                #ifdef __STATISTICS__
    850                         __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     816                __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
    851817                #endif // __STATISTICS__
    852818
     
    860826                if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ?
    861827                        assert( (header->kind.real.blockSize & 1) == 0 );
    862                         bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
     828                        _Bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
    863829                        #ifndef __CFA_DEBUG__
    864830                        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     
    871837                free( addr );
    872838                return area;
    873         } // realloc
    874 
    875 
    876         // The obsolete function memalign() allocates size bytes and returns
    877         // a pointer to the allocated memory. The memory address will be a
    878         // multiple of alignment, which must be a power of two.
    879         void * memalign( size_t alignment, size_t size ) __attribute__ ((deprecated));
    880                 void * memalign( size_t alignment, size_t size ) {
     839    } // realloc
     840
     841
     842    void * memalign( size_t alignment, size_t size ) {
    881843                #ifdef __STATISTICS__
    882844                __atomic_add_fetch( &memalign_calls, 1, __ATOMIC_SEQ_CST );
     
    887849
    888850                return area;
    889                 } // memalign
    890 
    891         // The function aligned_alloc() is the same as memalign(), except for
    892         // the added restriction that size should be a multiple of alignment.
    893         void * aligned_alloc( size_t alignment, size_t size ) {
     851    } // memalign
     852
     853
     854    void * aligned_alloc( size_t alignment, size_t size ) {
    894855                return memalign( alignment, size );
    895         } // aligned_alloc
    896 
    897 
    898         // The function posix_memalign() allocates size bytes and places the address
    899         // of the allocated memory in *memptr. The address of the allocated memory
    900         // will be a multiple of alignment, which must be a power of two and a multiple
    901         // of sizeof(void *). If size is 0, then posix_memalign() returns either NULL,
    902         // or a unique pointer value that can later be successfully passed to free(3).
    903         int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
     856    } // aligned_alloc
     857
     858
     859    int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    904860                if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
    905861                * memptr = memalign( alignment, size );
    906862                if ( unlikely( * memptr == 0 ) ) return ENOMEM;
    907863                return 0;
    908         } // posix_memalign
    909 
    910         // The obsolete function valloc() allocates size bytes and returns a pointer
    911         // to the allocated memory. The memory address will be a multiple of the page size.
    912         // It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
    913         void * valloc( size_t size ) __attribute__ ((deprecated));
    914         void * valloc( size_t size ) {
     864    } // posix_memalign
     865
     866
     867    void * valloc( size_t size ) {
    915868                return memalign( pageSize, size );
    916         } // valloc
    917 
    918 
    919         // The free() function frees the memory space pointed to by ptr, which must
    920         // have been returned by a previous call to malloc(), calloc() or realloc().
    921         // Otherwise, or if free(ptr) has already been called before, undefined
    922         // behavior occurs. If ptr is NULL, no operation is performed.
    923         void free( void * addr ) {
    924                 #ifdef __STATISTICS__
    925                         __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );
    926                 #endif // __STATISTICS__
    927 
    928                 // #comment TD : To decrease nesting I would but the special case in the
    929                 //               else instead, plus it reads more naturally to have the
    930                 //               short / normal case instead
     869    } // valloc
     870
     871
     872    void free( void * addr ) {
     873                #ifdef __STATISTICS__
     874                __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );
     875                #endif // __STATISTICS__
     876
    931877                if ( unlikely( addr == 0 ) ) {                                  // special case
    932878                        #ifdef __CFA_DEBUG__
    933                                 if ( traceHeap() ) {
    934                                         #define nullmsg "Free( 0x0 ) size:0\n"
    935                                         // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    936                                         __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
    937                                 } // if
     879                        if ( traceHeap() ) {
     880                                #define nullmsg "Free( 0x0 ) size:0\n"
     881                                // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
     882                                __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
     883                        } // if
    938884                        #endif // __CFA_DEBUG__
    939885                        return;
     
    941887
    942888                doFree( addr );
    943         } // free
    944 
    945         // The mallopt() function adjusts parameters that control the behavior of the
    946         // memory-allocation functions (see malloc(3)). The param argument specifies
    947         // the parameter to be modified, and value specifies the new value for that
    948         // parameter.
    949                 int mallopt( int option, int value ) {
     889    } // free
     890
     891    int mallopt( int option, int value ) {
    950892                choose( option ) {
    951                         case M_TOP_PAD:
    952                                 if ( setHeapExpand( value ) ) fallthru default;
    953                         case M_MMAP_THRESHOLD:
    954                                 if ( setMmapStart( value ) ) fallthru default;
    955                         default:
    956                                 // #comment TD : 1 for unsopported feels wrong
    957                                 return 1;                                                                       // success, or unsupported
     893                  case M_TOP_PAD:
     894                        if ( setHeapExpand( value ) ) fallthru default;
     895                  case M_MMAP_THRESHOLD:
     896                        if ( setMmapStart( value ) ) fallthru default;
     897                  default:
     898                        return 1;                                                                       // success, or unsupported
    958899                } // switch
    959900                return 0;                                                                               // error
    960         } // mallopt
    961 
    962         // The malloc_trim() function attempts to release free memory at the top
    963         // of the heap (by calling sbrk(2) with a suitable argument).
     901    } // mallopt
     902
     903
    964904        int malloc_trim( size_t ) {
    965905                return 0;                                                                               // => impossible to release memory
    966906        } // malloc_trim
    967907
    968         // The malloc_usable_size() function returns the number of usable bytes in the
    969         // block pointed to by ptr, a pointer to a block of memory allocated by
    970         // malloc(3) or a related function.
    971                 size_t malloc_usable_size( void * addr ) {
     908    size_t malloc_usable_size( void * addr ) {
    972909                if ( unlikely( addr == 0 ) ) return 0;                  // null allocation has 0 size
    973 
    974910                HeapManager.Storage.Header * header;
    975911                HeapManager.FreeHeader * freeElem;
     
    979915                size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    980916                return usize;
    981         } // malloc_usable_size
    982 
    983 
    984                 // #comment TD : Document this function
    985         size_t malloc_alignment( void * addr ) {
     917    } // malloc_usable_size
     918
     919
     920    size_t malloc_alignment( void * addr ) {
    986921                if ( unlikely( addr == 0 ) ) return libAlign(); // minimum alignment
    987922                HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
     
    991926                        return libAlign ();                                                     // minimum alignment
    992927                } // if
    993                 } // malloc_alignment
    994 
    995 
    996                 // #comment TD : Document this function
    997         bool malloc_zero_fill( void * addr ) {
     928    } // malloc_alignment
     929
     930
     931    _Bool malloc_zero_fill( void * addr ) {
    998932                if ( unlikely( addr == 0 ) ) return false;              // null allocation is not zero fill
    999 
    1000933                HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
    1001934                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    1003936                } // if
    1004937                return (header->kind.real.blockSize & 2) != 0;  // zero filled (calloc/cmemalign) ?
    1005                 } // malloc_zero_fill
    1006 
    1007 
    1008         // #comment TD : Document this function
    1009         void malloc_stats( void ) {
    1010                 #ifdef __STATISTICS__
    1011                         printStats();
    1012                         if ( checkFree() ) checkFree( heapManager );
    1013                 #endif // __STATISTICS__
    1014                 } // malloc_stats
    1015 
    1016         // #comment TD : Document this function
    1017                 int malloc_stats_fd( int fd ) {
    1018                 #ifdef __STATISTICS__
    1019                         int temp = statfd;
    1020                         statfd = fd;
    1021                         return temp;
     938    } // malloc_zero_fill
     939
     940
     941    void malloc_stats( void ) {
     942                #ifdef __STATISTICS__
     943                printStats();
     944                if ( checkFree() ) checkFree( heapManager );
     945                #endif // __STATISTICS__
     946    } // malloc_stats
     947
     948
     949    int malloc_stats_fd( int fd ) {
     950                #ifdef __STATISTICS__
     951                int temp = statfd;
     952                statfd = fd;
     953                return temp;
    1022954                #else
    1023                         return -1;
    1024                 #endif // __STATISTICS__
    1025                 } // malloc_stats_fd
    1026 
    1027 
    1028         // #comment TD : Document this function
     955                return -1;
     956                #endif // __STATISTICS__
     957    } // malloc_stats_fd
     958
     959
    1029960        int malloc_info( int options, FILE * stream ) {
    1030961                return printStatsXML( stream );
     
    1032963
    1033964
    1034         // #comment TD : What are these two functions for?
    1035965        void * malloc_get_state( void ) {
    1036966                return 0;
    1037967        } // malloc_get_state
     968
    1038969
    1039970        int malloc_set_state( void * ptr ) {
Note: See TracChangeset for help on using the changeset viewer.