Changeset d46ed6e


Ignore:
Timestamp:
Jul 25, 2018, 6:20:35 PM (6 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
Children:
cf0de0e
Parents:
891790ef
Message:

first attempt for new thread-safe heap

Location:
src/libcfa
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/heap.c

    r891790ef rd46ed6e  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul 24 08:57:22 2018
    13 // Update Count     : 388
     12// Last Modified On : Wed Jul 25 16:42:02 2018
     13// Update Count     : 438
    1414//
    1515
     
    2525#include "bits/defs.h"                                                                  // likely, unlikely
    2626#include "bits/locks.h"                                                                 // __spinlock_t
     27#include "startup.h"                                                                    // STARTUP_PRIORITY_MEMORY
    2728#include "stdlib"                                                                               // bsearchl
    2829#include "malloc.h"
     
    7475
    7576
    76 struct HeapManager {
    77 //      struct FreeHeader;                                                                      // forward declaration
    78 
    79         struct Storage {
    80             struct Header {                                                                     // header
    81                         union Kind {
    82                                 struct RealHeader {
    83                                         union {
    84                                                 struct {                                                // 32-bit word => 64-bit header, 64-bit word => 128-bit header
    85                                                         #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32
    86                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    87                                                         #endif // __U_WORDSIZE__ == 32 && __U_WORDSIZE__ == 32
    88 
    89                                                         union {
    90 //                                                              FreeHeader * home;              // allocated block points back to home locations (must overlay alignment)
    91                                                                 void * home;                    // allocated block points back to home locations (must overlay alignment)
    92                                                                 size_t blockSize;               // size for munmap (must overlay alignment)
    93                                                                 #if BUCKLOCK == SPINLOCK
    94                                                                 Storage * next;                 // freed block points next freed block of same size
    95                                                                 #endif // SPINLOCK
    96                                                         };
    97 
    98                                                         #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32
    99                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    100                                                         #endif // __U_WORDSIZE__ == 32 && __U_WORDSIZE__ == 32
    101 
    102                                                 };
    103                                                 #if BUCKLOCK == LOCKFREE
    104                                                 Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
    105                                                 #endif // LOCKFREE
    106                                         };
    107                                 } real;
    108                                 struct FakeHeader {
    109                                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    110                                         uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
    111                                         #endif // __BYTE_ORDER__
    112 
    113                                         uint32_t offset;
    114 
    115                                         #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    116                                         uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
    117                                         #endif // __BYTE_ORDER__
    118                                 } fake;
    119                         } kind;
    120             } header; // Header
    121             char pad[ALIGN - sizeof( Header )];
    122             char data[0];                                                                       // storage
    123         }; // Storage
    124 
    125         static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
    126 
    127         struct FreeHeader {
    128                 #if BUCKLOCK == SPINLOCK
    129             __spinlock_t lock;                                                          // must be first field for alignment
    130             Storage * freeList;
    131                 #elif BUCKLOCK == LOCKFREE
    132             StackLF<Storage> freeList;
    133                 #else
    134                         #error undefined lock type for bucket lock
    135                 #endif // SPINLOCK
    136             size_t blockSize;                                                           // size of allocations on this list
    137         }; // FreeHeader
    138 
    139         // must be first fields for alignment
    140         __spinlock_t extlock;                                                           // protects allocation-buffer extension
    141         FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
    142 
    143         void * heapBegin;                                                                       // start of heap
    144         void * heapEnd;                                                                         // logical end of heap
    145         size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    146 }; // HeapManager
    147 
    148 #ifdef __CFA_DEBUG__
    149 static _Bool heapBoot = 0;                                                              // detect recursion during boot
    150 #endif // __CFA_DEBUG__
    151 static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    152 
    153 static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     77static _Bool traceHeap = false;
     78
     79inline _Bool traceHeap() {
     80        return traceHeap;
     81} // traceHeap
     82
     83_Bool traceHeapOn() {
     84        _Bool temp = traceHeap;
     85        traceHeap = true;
     86        return temp;
     87} // traceHeapOn
     88
     89_Bool traceHeapOff() {
     90        _Bool temp = traceHeap;
     91        traceHeap = false;
     92        return temp;
     93} // traceHeapOff
     94
     95
     96// static _Bool prtHeapTerm = false;
     97
     98// inline _Bool prtHeapTerm() {
     99//      return prtHeapTerm;
     100// } // prtHeapTerm
     101
     102// _Bool prtHeapTermOn() {
     103//      _Bool temp = traceHeap;
     104//      traceHeap = true;
     105//      return temp;
     106// } // prtHeapTermOn
     107
     108// _Bool prtHeapTermOff() {
     109//      _Bool temp = traceHeap;
     110//      traceHeap = false;
     111//      return temp;
     112// } // prtHeapTermOff
     113
    154114
    155115// statically allocated variables => zero filled.
     
    178138#endif // FASTLOOKUP
    179139static int mmapFd = -1;                                                                 // fake or actual fd for anonymous file
     140
     141static unsigned int allocfree;                                                  // running total of allocations minus frees
     142static unsigned int appStart;                                                   // storage allocation when application starts
     143
     144static void checkUnfreed() {
     145        #ifdef __CFA_DEBUG__
     146        unsigned int total = allocfree - appStart;
     147    if ( total != 0 ) {
     148                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     149                // char helpText[512];
     150                // int len = snprintf( helpText, 512, "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
     151                //                                      "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
     152                //                                      (long int)getpid(), total, total ); // always print the UNIX pid
     153                // __cfaabi_dbg_bits_write( helpText, len );
     154    } // if
     155        #endif // __CFA_DEBUG__
     156} // checkUnfreed
     157
    180158#ifdef __CFA_DEBUG__
    181 static unsigned int allocfree;                                                  // running total of allocations minus frees
     159extern "C" {
     160void heapAppStart() {                                                                   // called by __cfaabi_appready_startup
     161        appStart = allocfree;
     162} // heapAppStart
     163
     164void heapAppStop() {                                                                    // called by __cfaabi_appready_startdown
     165        checkUnfreed();
     166} // heapAppStop
     167} // extern "C"
    182168#endif // __CFA_DEBUG__
    183169
    184170
     171struct HeapManager {
     172//      struct FreeHeader;                                                                      // forward declaration
     173
     174        struct Storage {
     175            struct Header {                                                                     // header
     176                        union Kind {
     177                                struct RealHeader {
     178                                        union {
     179                                                struct {                                                // 32-bit word => 64-bit header, 64-bit word => 128-bit header
     180                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32
     181                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     182                                                        #endif // __U_WORDSIZE__ == 32 && __U_WORDSIZE__ == 32
     183
     184                                                        union {
     185//                                                              FreeHeader * home;              // allocated block points back to home locations (must overlay alignment)
     186                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
     187                                                                size_t blockSize;               // size for munmap (must overlay alignment)
     188                                                                #if BUCKLOCK == SPINLOCK
     189                                                                Storage * next;                 // freed block points next freed block of same size
     190                                                                #endif // SPINLOCK
     191                                                        };
     192
     193                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32
     194                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     195                                                        #endif // __U_WORDSIZE__ == 32 && __U_WORDSIZE__ == 32
     196
     197                                                };
     198                                                #if BUCKLOCK == LOCKFREE
     199                                                Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
     200                                                #endif // LOCKFREE
     201                                        };
     202                                } real;
     203                                struct FakeHeader {
     204                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     205                                        uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
     206                                        #endif // __BYTE_ORDER__
     207
     208                                        uint32_t offset;
     209
     210                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
     211                                        uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
     212                                        #endif // __BYTE_ORDER__
     213                                } fake;
     214                        } kind;
     215            } header; // Header
     216            char pad[ALIGN - sizeof( Header )];
     217            char data[0];                                                                       // storage
     218        }; // Storage
     219
     220        static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
     221
     222        struct FreeHeader {
     223                #if BUCKLOCK == SPINLOCK
     224            __spinlock_t lock;                                                          // must be first field for alignment
     225            Storage * freeList;
     226                #elif BUCKLOCK == LOCKFREE
     227            StackLF<Storage> freeList;
     228                #else
     229                        #error undefined lock type for bucket lock
     230                #endif // SPINLOCK
     231            size_t blockSize;                                                           // size of allocations on this list
     232        }; // FreeHeader
     233
     234        // must be first fields for alignment
     235        __spinlock_t extlock;                                                           // protects allocation-buffer extension
     236        FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
     237
     238        void * heapBegin;                                                                       // start of heap
     239        void * heapEnd;                                                                         // logical end of heap
     240        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
     241}; // HeapManager
     242
     243
     244static inline _Bool setMmapStart( size_t value ) {
     245    if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     246    mmapStart = value;                                                                  // set global
     247
     248    // find the closest bucket size less than or equal to the mmapStart size
     249    maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     250    assert( maxBucketsUsed < NoBucketSizes );                   // subscript failure ?
     251    assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     252    return false;
     253} // setMmapStart
     254
     255
     256static void ?{}( HeapManager & manager ) with ( manager ) {
     257    pageSize = sysconf( _SC_PAGESIZE );
     258   
     259    for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     260                freeLists[i].blockSize = bucketSizes[i];
     261    } // for
     262
     263        #ifdef FASTLOOKUP
     264    unsigned int idx = 0;
     265    for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     266                if ( i > bucketSizes[idx] ) idx += 1;
     267                lookup[i] = idx;
     268    } // for
     269        #endif // FASTLOOKUP
     270
     271    if ( setMmapStart( default_mmap_start() ) ) {
     272                abort( "HeapManager : internal error, mmap start initialization failure." );
     273    } // if
     274    heapExpand = default_heap_expansion();
     275
     276    char * End = (char *)sbrk( 0 );
     277    sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
     278    heapBegin = heapEnd = sbrk( 0 );                                    // get new start point
     279} // HeapManager
     280
     281
     282static void ^?{}( HeapManager & ) {
     283        #ifdef __STATISTICS__
     284        // if ( prtHeapTerm() ) {
     285        //      printStats();
     286        //      checkFree( heapManager, true );
     287        // } // if
     288        #endif // __STATISTICS__
     289} // ~HeapManager
     290
     291
     292#ifdef __CFA_DEBUG__
     293static _Bool heapBoot = 0;                                                              // detect recursion during boot
     294#endif // __CFA_DEBUG__
     295static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
     296
     297static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
     298void memory_startup( void ) {
     299        #ifdef __CFA_DEBUG__
     300        if ( unlikely( heapBoot ) ) {                                   // check for recursion during system boot
     301                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     302                abort( "boot() : internal error, recursively invoked during system boot." );
     303        } // if
     304        heapBoot = true;
     305        #endif // __CFA_DEBUG__
     306
     307        heapManager{};
     308} // memory_startup
     309
     310static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
     311void memory_shutdown( void ) {
     312        ^heapManager{};
     313} // memory_shutdown
     314
     315static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     316
     317
    185318#ifdef __STATISTICS__
    186 // Heap statistics
    187 static unsigned long long int mmap_storage;
     319static unsigned long long int mmap_storage;                             // heap statistics counters
    188320static unsigned int mmap_calls;
    189321static unsigned long long int munmap_storage;
     
    203335static unsigned long long int realloc_storage;
    204336static unsigned int realloc_calls;
    205 static int statfd;
     337
     338static int statfd;                                                                              // statistics file descriptor (changed by malloc_stats_fd)
    206339
    207340
    208341// Use "write" because streams may be shutdown when calls are made.
    209 static void print() {
     342static void printStats() {
    210343    char helpText[512];
    211344    int len = snprintf( helpText, 512,
     
    231364                );
    232365    write( statfd, helpText, len );
    233 } // print
    234 
    235 
    236 static int printXML( FILE * stream ) {
     366} // printStats
     367
     368
     369static int printStatsXML( FILE * stream ) {
    237370    char helpText[512];
    238371    int len = snprintf( helpText, 512,
     
    262395                );
    263396    return write( fileno( stream ), helpText, len );    // -1 => error
    264 } // printXML
     397} // printStatsXML
    265398#endif // __STATISTICS__
    266399
     
    287420
    288421
    289 static inline _Bool setMmapStart( size_t value ) {
    290     if ( value < pageSize || bucketSizes[NoBucketSizes-1] < value ) return true;
    291     mmapStart = value;                                                                  // set global
    292 
    293     // find the closest bucket size less than or equal to the mmapStart size
    294     maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    295     assert( maxBucketsUsed < NoBucketSizes );                   // subscript failure ?
    296     assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    297     return false;
    298 } // setMmapStart
    299 
    300 
    301422static inline void checkHeader( _Bool check, const char * name, void * addr ) {
    302423    if ( unlikely( check ) ) {                                                  // bad address ?
     
    306427    } // if
    307428} // checkHeader
     429
    308430
    309431static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
     
    448570    assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
    449571    __atomic_add_fetch( &allocfree, tsize, __ATOMIC_SEQ_CST );
    450 //    if ( uHeapControl::traceHeap() ) {
    451 //              enum { BufferSize = 64 };
    452 //              char helpText[BufferSize];
    453 //              int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
    454                 //int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
    455 //              uDebugWrite( STDERR_FILENO, helpText, len );
    456 //    } // if
     572        if ( traceHeap() ) {
     573                enum { BufferSize = 64 };
     574                char helpText[BufferSize];
     575                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
     576                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
     577                __cfaabi_dbg_bits_write( helpText, len );
     578        } // if
    457579        #endif // __CFA_DEBUG__
    458580
     
    505627        #ifdef __CFA_DEBUG__
    506628    __atomic_add_fetch( &allocfree, -size, __ATOMIC_SEQ_CST );
    507     // if ( uHeapControl::traceHeap() ) {
    508         //      enum { BufferSize = 64 };
    509         //      char helpText[BufferSize];
    510         //      int len = snprintf( helpText, BufferSize, "Free( %p ) size:%zu\n", addr, size );
    511         //      uDebugWrite( STDERR_FILENO, helpText, len );
    512     // } // if
     629    if ( traceHeap() ) {
     630                enum { BufferSize = 64 };
     631                char helpText[BufferSize];
     632                int len = snprintf( helpText, BufferSize, "Free( %p ) size:%zu\n", addr, size );
     633                __cfaabi_dbg_bits_write( helpText, len );
     634    } // if
    513635        #endif // __CFA_DEBUG__
    514636} // doFree
    515637
    516638
    517 // size_t checkFree( _Bool prt ) {
    518 //     size_t total = 0;
    519 // #ifdef __STATISTICS__
    520 //     uDebugAcquire();
    521 //     if ( prt ) uDebugPrt2( "\nBin lists (bin size : free blocks on list)\n" );
    522 // #endif // __STATISTICS__
    523 //     for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
    524 //      size_t size = freeLists[i].blockSize;
    525 // #ifdef __STATISTICS__
    526 //      unsigned int N = 0;
    527 // #endif // __STATISTICS__
    528 // #if defined( SPINLOCK )
    529 //      for ( Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
    530 // #else
    531 //          for ( Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
    532 // #endif // SPINLOCK
    533 //              total += size;
    534 // #ifdef __STATISTICS__
    535 //              N += 1;
    536 // #endif // __STATISTICS__
    537 //          } // for
    538 // #ifdef __STATISTICS__
    539 //          if ( prt ) uDebugPrt2( "%7zu, %-7u  ", size, N );
    540 //          if ( (i + 1) % 8 == 0 ) uDebugPrt2( "\n" );
    541 // #endif // __STATISTICS__
    542 //      } // for
    543 // #ifdef __STATISTICS__
    544 //      if ( prt ) uDebugPrt2( "\ntotal free blocks:%zu\n", total );
    545 //      uDebugRelease();
    546 // #endif // __STATISTICS__
    547 //      return (char *)heapEnd - (char *)heapBegin - total;
    548 //     } // for
    549 // } // checkFree
    550 
    551 
    552 static void ?{}( HeapManager & manager ) with ( manager ) {
    553     pageSize = sysconf( _SC_PAGESIZE );
    554    
    555     for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    556                 freeLists[i].blockSize = bucketSizes[i];
    557     } // for
    558 
    559         #ifdef FASTLOOKUP
    560     unsigned int idx = 0;
    561     for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    562                 if ( i > bucketSizes[idx] ) idx += 1;
    563                 lookup[i] = idx;
    564     } // for
    565         #endif // FASTLOOKUP
    566 
    567     if ( setMmapStart( default_mmap_start() ) ) {
    568                 abort( "HeapManager : internal error, mmap start initialization failure." );
    569     } // if
    570     heapExpand = default_heap_expansion();
    571 
    572     char * End = (char *)sbrk( 0 );
    573     sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    574     heapBegin = heapEnd = sbrk( 0 );                                    // get new start point
    575 } // HeapManager
    576 
    577 
    578 static void ^?{}( HeapManager & ) {
     639size_t checkFree( HeapManager & manager, _Bool prt ) with ( manager ) {
     640    size_t total = 0;
    579641        #ifdef __STATISTICS__
    580         // if ( prtHeapterm ) {
    581         //      print();
    582         //      heapManager.checkFree( true );
    583         // } // if
     642    __cfaabi_dbg_bits_acquire();
     643    if ( prt ) __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
    584644        #endif // __STATISTICS__
    585 
    586         #ifdef __CFA_DEBUG__
    587     if ( allocfree != 0 ) {
    588                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    589                 char helpText[512];
    590                 int len = snprintf( helpText, 512, "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
    591                                                         "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    592                                                         (long int)getpid(), allocfree, allocfree ); // always print the UNIX pid
    593                 __cfaabi_dbg_bits_write( helpText, len );
    594     } // if
    595         #endif // __CFA_DEBUG__
    596 } // ~HeapManager
     645    for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     646                size_t size = freeLists[i].blockSize;
     647                #ifdef __STATISTICS__
     648                unsigned int N = 0;
     649                #endif // __STATISTICS__
     650                #if defined( SPINLOCK )
     651                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
     652                #else
     653                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
     654                #endif // SPINLOCK
     655                        total += size;
     656                        #ifdef __STATISTICS__
     657                        N += 1;
     658                        #endif // __STATISTICS__
     659            } // for
     660                #ifdef __STATISTICS__
     661            if ( prt ) __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
     662            if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
     663                #endif // __STATISTICS__
     664        } // for
     665        #ifdef __STATISTICS__
     666        if ( prt ) __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
     667        __cfaabi_dbg_bits_release();
     668        #endif // __STATISTICS__
     669        return (char *)heapEnd - (char *)heapBegin - total;
     670} // checkFree
    597671
    598672
    599673static inline void * malloc2( size_t size ) {                   // necessary for malloc statistics
    600     if ( unlikely( heapManager.heapBegin == 0 ) ) {
    601                 #ifdef __CFA_DEBUG__
    602                 if ( unlikely( heapBoot ) ) {                                   // check for recursion during system boot
    603                         // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    604                         abort( "boot() : internal error, recursively invoked during system boot." );
    605                 } // if
    606                 heapBoot = true;
    607                 #endif // __CFA_DEBUG__
    608 
    609                 heapManager{};
    610         } // if
    611 
     674    assert( heapManager.heapBegin != 0 ) ;                              // heap started
    612675    void * area = doMalloc( size );
    613676    if ( unlikely( area == 0 ) ) errno = ENOMEM;                // POSIX
     
    793856
    794857                if ( unlikely( addr == 0 ) ) {                                  // special case
    795 // #ifdef __CFA_DEBUG__
    796 //          if ( uHeapControl::traceHeap() ) {
    797 // #            define nullmsg "Free( 0x0 ) size:0\n"
    798 //              // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    799 //              uDebugWrite( STDERR_FILENO, nullmsg, sizeof(nullmsg) - 1 );
    800 //          } // if
    801 // #endif // __CFA_DEBUG__
     858                        #ifdef __CFA_DEBUG__
     859                        if ( traceHeap() ) {
     860                                #define nullmsg "Free( 0x0 ) size:0\n"
     861                                // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
     862                                __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
     863                        } // if
     864                        #endif // __CFA_DEBUG__
    802865                        return;
    803866                } // exit
    804867
    805868                doFree( addr );
    806                 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    807869    } // free
    808870
     
    859921    void malloc_stats( void ) {
    860922                #ifdef __STATISTICS__
    861                 print();
    862                 // heapManager.checkFree( true );
     923                printStats();
     924                checkFree( heapManager, true );
    863925                #endif // __STATISTICS__
    864926    } // malloc_stats
     
    877939
    878940        int malloc_info( int options, FILE * stream ) {
    879                 return printXML( stream );
     941                return printStatsXML( stream );
    880942        } // malloc_info
    881943
  • src/libcfa/stdhdr/malloc.h

    r891790ef rd46ed6e  
    1010// Created On       : Thu Jul 20 15:58:16 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 16:00:12 2017
    13 // Update Count     : 4
     12// Last Modified On : Mon Jul 23 18:20:32 2018
     13// Update Count     : 8
    1414//
     15
     16
     17size_t default_mmap_start();                                                    // CFA extras
     18size_t default_heap_expansion();
     19extern "C" {
     20size_t malloc_alignment( void * );
     21_Bool malloc_zero_fill( void * );
     22int malloc_stats_fd( int fd );
     23void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize );
     24} // extern "C"
    1525
    1626extern "C" {
  • src/libcfa/stdlib

    r891790ef rd46ed6e  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 12 08:03:58 2018
    13 // Update Count     : 337
     12// Last Modified On : Mon Jul 23 07:44:47 2018
     13// Update Count     : 341
    1414//
    1515
    1616#pragma once
    1717
    18 #include <stdlib.h>                                                                             // allocation, strto*, ato*
     18#include <stdlib.h>                                                                             // *alloc, strto*, ato*
    1919extern "C" {
    2020        void * memalign( size_t align, size_t size );           // malloc.h
    2121        void * memset( void * dest, int c, size_t size );       // string.h
    2222        void * memcpy( void * dest, const void * src, size_t size ); // string.h
     23    void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA
    2324} // extern "C"
    2425
     
    3637
    3738        T * malloc( void ) {
    38                 // printf( "* malloc\n" );
    3939                return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    4040        } // malloc
     
    4848
    4949        T * calloc( size_t dim ) {
    50                 //printf( "X2\n" );
    5150                return (T *)(void *)calloc( dim, sizeof(T) );   // C calloc
    5251        } // calloc
    5352
    5453        T * realloc( T * ptr, size_t size ) {
    55                 //printf( "X3\n" );
    5654                return (T *)(void *)realloc( (void *)ptr, size );
    5755        } // realloc
    5856
    5957        T * memalign( size_t align ) {
    60                 //printf( "X4\n" );
    6158                return (T *)memalign( align, sizeof(T) );
    6259        } // memalign
    6360
    6461        T * aligned_alloc( size_t align ) {
    65                 //printf( "X5\n" );
    6662                return (T *)aligned_alloc( align, sizeof(T) );
    6763        } // aligned_alloc
    6864
    6965        int posix_memalign( T ** ptr, size_t align ) {
    70                 //printf( "X6\n" );
    7166                return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign
    7267        } // posix_memalign
     
    7671
    7772        T * alloc( void ) {
    78                 //printf( "X7\n" );
    7973                return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    8074        } // alloc
    8175
    8276        T * alloc( char fill ) {
    83                 //printf( "X8\n" );
    8477                T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) );     // C malloc
    8578                return (T *)memset( ptr, (int)fill, sizeof(T) );        // initial with fill value
     
    8780
    8881        T * alloc( size_t dim ) {
    89                 //printf( "X9\n" );
    9082                return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
    9183        } // alloc
    9284
    9385        T * alloc( size_t dim, char fill ) {
    94                 //printf( "X10\n" );
    9586                T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
    9687                return (T *)memset( ptr, (int)fill, dim * sizeof(T) );    // initial with fill value
     
    9889
    9990        T * alloc( T ptr[], size_t dim ) {
    100                 //printf( "X11\n" );
    10191                return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc
    10292        } // alloc
     
    10999static inline forall( dtype T | sized(T) ) {
    110100        T * align_alloc( size_t align ) {
    111                 //printf( "X13\n" );
    112101                return (T *)memalign( align, sizeof(T) );
    113102        } // align_alloc
    114103
    115104        T * align_alloc( size_t align, char fill ) {
    116                 //printf( "X14\n" );
    117105                T * ptr = (T *)memalign( align, sizeof(T) );
    118106                return (T *)memset( ptr, (int)fill, sizeof(T) );
     
    120108
    121109        T * align_alloc( size_t align, size_t dim ) {
    122                 //printf( "X15\n" );
    123110                return (T *)memalign( align, dim * sizeof(T) );
    124111        } // align_alloc
    125112
    126113        T * align_alloc( size_t align, size_t dim, char fill ) {
    127                 //printf( "X16\n" );
    128                 T * ptr = (T *)memalign( align, dim * sizeof(T) );
    129                 return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
     114                T * ptr;
     115                if ( fill == '\0' ) {
     116                        ptr = (T *)cmemalign( align, dim, sizeof(T) );
     117                } else {
     118                        ptr = (T *)memalign( align, dim * sizeof(T) );
     119                        return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
     120                } // if
     121                return ptr;
    130122        } // align_alloc
    131123} // distribution
     
    136128
    137129        T * memset( T * dest, char c ) {
    138                 //printf( "X17\n" );
    139130                return (T *)memset( dest, c, sizeof(T) );
    140131        } // memset
    141132
    142133        T * memcpy( T * dest, const T * src ) {
    143                 //printf( "X18\n" );
    144134                return (T *)memcpy( dest, src, sizeof(T) );
    145135        } // memcpy
     
    150140
    151141        T * memset( T dest[], size_t dim, char c ) {
    152                 //printf( "X19\n" );
    153142                return (T *)(void *)memset( dest, c, dim * sizeof(T) ); // C memset
    154143        } // memset
    155144
    156145        T * memcpy( T dest[], const T src[], size_t dim ) {
    157                 //printf( "X20\n" );
    158146                return (T *)(void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy
    159147        } // memcpy
Note: See TracChangeset for help on using the changeset viewer.