Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    r9c438546 r1076d05  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 20:58:17 2020
    13 // Update Count     : 762
     12// Last Modified On : Wed May  6 17:29:26 2020
     13// Update Count     : 727
    1414//
    1515
     
    128128#define LOCKFREE 1
    129129#define BUCKETLOCK SPINLOCK
    130 #if BUCKETLOCK == SPINLOCK
    131 #elif BUCKETLOCK == LOCKFREE
    132 #include <stackLockFree.hfa>
    133 #else
    134         #error undefined lock type for bucket lock
     130#if BUCKETLOCK == LOCKFREE
     131#include <uStackLF.h>
    135132#endif // LOCKFREE
    136133
     
    140137
    141138struct HeapManager {
     139//      struct FreeHeader;                                                                      // forward declaration
     140
    142141        struct Storage {
    143142                struct Header {                                                                 // header
     
    147146                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    148147                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    149                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     148                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    150149                                                        #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    151150
    152151                                                        union {
    153                                                                 // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
     152//                                                              FreeHeader * home;              // allocated block points back to home locations (must overlay alignment)
    154153                                                                // 2nd low-order bit => zero filled
    155154                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
    156155                                                                size_t blockSize;               // size for munmap (must overlay alignment)
    157                                                                 #if BUCKETLOCK == SPINLOCK
     156                                                                #if BUCKLOCK == SPINLOCK
    158157                                                                Storage * next;                 // freed block points next freed block of same size
    159158                                                                #endif // SPINLOCK
    160159                                                        };
    161                                                         size_t size;                            // allocation size in bytes
    162160
    163161                                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    164                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     162                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    165163                                                        #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    166164                                                };
    167                                                 #if BUCKETLOCK == LOCKFREE
    168                                                 Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
     165                                                // future code
     166                                                #if BUCKLOCK == LOCKFREE
     167                                                Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
    169168                                                #endif // LOCKFREE
    170169                                        };
    171170                                } real; // RealHeader
    172 
    173171                                struct FakeHeader {
    174172                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    175                                         uint32_t alignment;                                     // 1st low-order bit => fake header & alignment
     173                                        // 1st low-order bit => fake header & alignment
     174                                        uint32_t alignment;
    176175                                        #endif // __ORDER_LITTLE_ENDIAN__
    177176
     
    183182                                } fake; // FakeHeader
    184183                        } kind; // Kind
     184                        size_t size;                                                            // allocation size in bytes
    185185                } header; // Header
    186186                char pad[libAlign() - sizeof( Header )];
     
    191191
    192192        struct FreeHeader {
    193                 #if BUCKETLOCK == SPINLOCK
     193                #if BUCKLOCK == SPINLOCK
    194194                __spinlock_t lock;                                                              // must be first field for alignment
    195195                Storage * freeList;
     196                #elif BUCKLOCK == LOCKFREE
     197                // future code
     198                StackLF<Storage> freeList;
    196199                #else
    197                 StackLF(Storage) freeList;
    198                 #endif // BUCKETLOCK
     200                        #error undefined lock type for bucket lock
     201                #endif // SPINLOCK
    199202                size_t blockSize;                                                               // size of allocations on this list
    200203        }; // FreeHeader
     
    208211        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    209212}; // HeapManager
    210 
    211 #if BUCKETLOCK == LOCKFREE
    212 static inline Link(HeapManager.Storage) * getNext( HeapManager.Storage * this ) { return &this->header.kind.real.next; }
    213 static inline void ?{}( HeapManager.FreeHeader & ) {}
    214 static inline void ^?{}( HeapManager.FreeHeader & ) {}
    215 #endif // LOCKFREE
    216213
    217214static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     
    254251static bool heapBoot = 0;                                                               // detect recursion during boot
    255252#endif // __CFA_DEBUG__
    256 
    257 // The constructor for heapManager is called explicitly in memory_startup.
    258253static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    259254
     
    359354
    360355
     356// static inline void noMemory() {
     357//      abort( "Heap memory exhausted at %zu bytes.\n"
     358//                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
     359//                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
     360// } // noMemory
     361
     362
    361363// thunk problem
    362364size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    404406
    405407
    406 // static inline void noMemory() {
    407 //      abort( "Heap memory exhausted at %zu bytes.\n"
    408 //                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    409 //                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
    410 // } // noMemory
    411 
    412 
    413408static inline void checkAlign( size_t alignment ) {
    414409        if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     
    438433
    439434
    440 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem,
    441                                                         size_t & size, size_t & alignment ) with( heapManager ) {
     435static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    442436        header = headerAddr( addr );
    443437
     
    471465
    472466
    473 static inline void * extend( size_t size ) with( heapManager ) {
     467static inline void * extend( size_t size ) with ( heapManager ) {
    474468        lock( extlock __cfaabi_dbg_ctx2 );
    475469        ptrdiff_t rem = heapRemaining - size;
     
    502496
    503497
    504 static inline void * doMalloc( size_t size ) with( heapManager ) {
     498static inline void * doMalloc( size_t size ) with ( heapManager ) {
    505499        HeapManager.Storage * block;                                            // pointer to new block of storage
    506500
     
    535529                // Spin until the lock is acquired for this particular size of block.
    536530
    537                 #if BUCKETLOCK == SPINLOCK
     531                #if defined( SPINLOCK )
    538532                lock( freeElem->lock __cfaabi_dbg_ctx2 );
    539533                block = freeElem->freeList;                                             // remove node from stack
    540534                #else
    541                 block = pop( freeElem->freeList );
    542                 #endif // BUCKETLOCK
     535                block = freeElem->freeList.pop();
     536                #endif // SPINLOCK
    543537                if ( unlikely( block == 0p ) ) {                                // no free block ?
    544                         #if BUCKETLOCK == SPINLOCK
     538                        #if defined( SPINLOCK )
    545539                        unlock( freeElem->lock );
    546                         #endif // BUCKETLOCK
     540                        #endif // SPINLOCK
    547541
    548542                        // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more
     
    550544
    551545                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    552         if ( unlikely( block == 0p ) ) return 0p;
    553                 #if BUCKETLOCK == SPINLOCK
     546  if ( unlikely( block == 0p ) ) return 0p;
     547                #if defined( SPINLOCK )
    554548                } else {
    555549                        freeElem->freeList = block->header.kind.real.next;
    556550                        unlock( freeElem->lock );
    557                 #endif // BUCKETLOCK
     551                #endif // SPINLOCK
    558552                } // if
    559553
     
    578572        } // if
    579573
    580         block->header.kind.real.size = size;                            // store allocation size
     574        block->header.size = size;                                                      // store allocation size
    581575        void * addr = &(block->data);                                           // adjust off header to user bytes
    582576
     
    597591
    598592
    599 static inline void doFree( void * addr ) with( heapManager ) {
     593static inline void doFree( void * addr ) with ( heapManager ) {
    600594        #ifdef __CFA_DEBUG__
    601595        if ( unlikely( heapManager.heapBegin == 0p ) ) {
     
    629623                free_storage += size;
    630624                #endif // __STATISTICS__
    631                 #if BUCKETLOCK == SPINLOCK
     625                #if defined( SPINLOCK )
    632626                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    633627                header->kind.real.next = freeElem->freeList;    // push on stack
     
    635629                unlock( freeElem->lock );                                               // release spin lock
    636630                #else
    637                 push( freeElem->freeList, *(HeapManager.Storage *)header );
    638                 #endif // BUCKETLOCK
     631                freeElem->freeList.push( *(HeapManager.Storage *)header );
     632                #endif // SPINLOCK
    639633        } // if
    640634
     
    651645
    652646
    653 size_t prtFree( HeapManager & manager ) with( manager ) {
     647size_t prtFree( HeapManager & manager ) with ( manager ) {
    654648        size_t total = 0;
    655649        #ifdef __STATISTICS__
     
    663657                #endif // __STATISTICS__
    664658
    665                 #if BUCKETLOCK == SPINLOCK
     659                #if defined( SPINLOCK )
    666660                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    667661                #else
    668                 for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
    669                         typeof(p) temp = getNext( p )->top;                     // FIX ME: direct assignent fails, initialization works
    670                         p = temp;
    671                 #endif // BUCKETLOCK
     662                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
     663                #endif // SPINLOCK
    672664                        total += size;
    673665                        #ifdef __STATISTICS__
     
    689681
    690682
    691 static void ?{}( HeapManager & manager ) with( manager ) {
     683static void ?{}( HeapManager & manager ) with ( manager ) {
    692684        pageSize = sysconf( _SC_PAGESIZE );
    693685
     
    11031095                        header = realHeader( header );                          // backup from fake to real header
    11041096                } // if
    1105                 return header->kind.real.size;
     1097                return header->size;
    11061098        } // malloc_size
    11071099
     
    11131105                        header = realHeader( header );                          // backup from fake to real header
    11141106                } // if
    1115                 size_t ret = header->kind.real.size;
    1116                 header->kind.real.size = size;
     1107                size_t ret = header->size;
     1108                header->size = size;
    11171109                return ret;
    11181110        } // $malloc_size_set
Note: See TracChangeset for help on using the changeset viewer.