Ignore:
Timestamp:
May 20, 2022, 10:36:45 AM (4 years ago)
Author:
m3zulfiq <m3zulfiq@…>
Branches:
ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
Children:
25fa20a
Parents:
29d8c02 (diff), 7831e8fb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    r29d8c02 r74ec742  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 25 18:51:36 2022
    13 // Update Count     : 1147
     12// Last Modified On : Fri Apr 29 19:05:03 2022
     13// Update Count     : 1167
    1414//
    1515
     
    3636static bool traceHeap = false;
    3737
    38 inline bool traceHeap() { return traceHeap; }
    39 
    40 bool traceHeapOn() {
     38inline bool traceHeap() libcfa_public { return traceHeap; }
     39
     40bool traceHeapOn() libcfa_public {
    4141        bool temp = traceHeap;
    4242        traceHeap = true;
     
    4444} // traceHeapOn
    4545
    46 bool traceHeapOff() {
     46bool traceHeapOff() libcfa_public {
    4747        bool temp = traceHeap;
    4848        traceHeap = false;
     
    5050} // traceHeapOff
    5151
    52 bool traceHeapTerm() { return false; }
     52bool traceHeapTerm() libcfa_public { return false; }
    5353
    5454
    5555static bool prtFree = false;
    5656
    57 bool prtFree() {
     57static bool prtFree() {
    5858        return prtFree;
    5959} // prtFree
    6060
    61 bool prtFreeOn() {
     61static bool prtFreeOn() {
    6262        bool temp = prtFree;
    6363        prtFree = true;
     
    6565} // prtFreeOn
    6666
    67 bool prtFreeOff() {
     67static bool prtFreeOff() {
    6868        bool temp = prtFree;
    6969        prtFree = false;
     
    8787
    8888
    89 #ifdef __CFA_DEBUG__
    90 static size_t allocUnfreed;                                                             // running total of allocations minus frees
    91 
    92 static void prtUnfreed() {
    93         if ( allocUnfreed != 0 ) {
    94                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    95                 char helpText[512];
    96                 int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n"
    97                                                         "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    98                                                         (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
    99                 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    100         } // if
    101 } // prtUnfreed
    102 
    103 extern int cfa_main_returned;                                                   // from interpose.cfa
    104 extern "C" {
    105         void heapAppStart() {                                                           // called by __cfaabi_appready_startup
    106                 allocUnfreed = 0;
    107         } // heapAppStart
    108 
    109         void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    110                 fclose( stdin ); fclose( stdout );
    111                 if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
    112         } // heapAppStop
    113 } // extern "C"
    114 #endif // __CFA_DEBUG__
    115 
    116 
    117 // statically allocated variables => zero filled.
    118 static size_t heapExpand;                                                               // sbrk advance
    119 static size_t mmapStart;                                                                // cross over point for mmap
    120 static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    121 // extern visibility, used by runtime kernel
    122 size_t __page_size;                                                                             // architecture pagesize
    123 int __map_prot;                                                                                 // common mmap/mprotect protection
    124 
    125 
    126 #define SPINLOCK 0
    127 #define LOCKFREE 1
    128 #define BUCKETLOCK SPINLOCK
    129 #if BUCKETLOCK == SPINLOCK
    130 #elif BUCKETLOCK == LOCKFREE
    131 #include <stackLockFree.hfa>
    132 #else
    133         #error undefined lock type for bucket lock
    134 #endif // LOCKFREE
    135 
    136 // Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    137 // Break recursion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    138 enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
    139 
    140 struct Heap {
    141         struct Storage {
    142                 struct Header {                                                                 // header
    143                         union Kind {
    144                                 struct RealHeader {
    145                                         union {
    146                                                 struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    147                                                         union {
    148                                                                 // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped
    149                                                                 // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
    150                                                                 void * home;                    // allocated block points back to home locations (must overlay alignment)
    151                                                                 size_t blockSize;               // size for munmap (must overlay alignment)
    152                                                                 #if BUCKETLOCK == SPINLOCK
    153                                                                 Storage * next;                 // freed block points to next freed block of same size
    154                                                                 #endif // SPINLOCK
    155                                                         };
    156                                                         size_t size;                            // allocation size in bytes
    157                                                 };
    158                                                 #if BUCKETLOCK == LOCKFREE
    159                                                 Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
    160                                                 #endif // LOCKFREE
    161                                         };
    162                                 } real; // RealHeader
    163 
    164                                 struct FakeHeader {
    165                                         uintptr_t alignment;                            // 1st low-order bit => fake header & alignment
    166                                         uintptr_t offset;
    167                                 } fake; // FakeHeader
    168                         } kind; // Kind
    169                 } header; // Header
    170 
    171                 char pad[libAlign() - sizeof( Header )];
    172                 char data[0];                                                                   // storage
    173         }; // Storage
    174 
    175         static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    176 
    177         struct FreeHeader {
    178                 #if BUCKETLOCK == SPINLOCK
    179                 __spinlock_t lock;                                                              // must be first field for alignment
    180                 Storage * freeList;
    181                 #else
    182                 StackLF(Storage) freeList;
    183                 #endif // BUCKETLOCK
    184                 size_t blockSize;                                                               // size of allocations on this list
    185         }; // FreeHeader
    186 
    187         // must be first fields for alignment
    188         __spinlock_t extlock;                                                           // protects allocation-buffer extension
    189         FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
    190 
    191         void * heapBegin;                                                                       // start of heap
    192         void * heapEnd;                                                                         // logical end of heap
    193         size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    194 }; // Heap
    195 
    196 #if BUCKETLOCK == LOCKFREE
    197 static inline {
    198         Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
    199         void ?{}( Heap.FreeHeader & ) {}
    200         void ^?{}( Heap.FreeHeader & ) {}
    201 } // distribution
    202 #endif // LOCKFREE
    203 
    204 static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
    205 
    206 
    207 #ifdef FASTLOOKUP
    208 enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
    209 static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    210 #endif // FASTLOOKUP
    211 
    212 static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
    213 #ifdef __CFA_DEBUG__
    214 static bool heapBoot = 0;                                                               // detect recursion during boot
    215 #endif // __CFA_DEBUG__
    216 
    217 
    218 // Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16.
    219 // Smaller multiples of 16 and powers of 2 are common allocation sizes, so make them generate the minimum required bucket size.
    220 // malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed.
    221 static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    222         16 + sizeof(Heap.Storage), 32 + sizeof(Heap.Storage), 48 + sizeof(Heap.Storage), 64 + sizeof(Heap.Storage), // 4
    223         96 + sizeof(Heap.Storage), 112 + sizeof(Heap.Storage), 128 + sizeof(Heap.Storage), // 3
    224         160, 192, 224, 256 + sizeof(Heap.Storage), // 4
    225         320, 384, 448, 512 + sizeof(Heap.Storage), // 4
    226         640, 768, 896, 1_024 + sizeof(Heap.Storage), // 4
    227         1_536, 2_048 + sizeof(Heap.Storage), // 2
    228         2_560, 3_072, 3_584, 4_096 + sizeof(Heap.Storage), // 4
    229         6_144, 8_192 + sizeof(Heap.Storage), // 2
    230         9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(Heap.Storage), // 8
    231         18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(Heap.Storage), // 8
    232         36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(Heap.Storage), // 8
    233         73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(Heap.Storage), // 8
    234         147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(Heap.Storage), // 8
    235         294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(Heap.Storage), // 8
    236         655_360, 786_432, 917_504, 1_048_576 + sizeof(Heap.Storage), // 4
    237         1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(Heap.Storage), // 8
    238         2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(Heap.Storage), // 4
    239 };
    240 
    241 static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    242 
    243 // The constructor for heapManager is called explicitly in memory_startup.
    244 static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    245 
    246 
    247 //####################### Memory Allocation Routines Helpers ####################
     89//####################### Heap Statistics ####################
    24890
    24991
     
    307149        return lhs;
    308150} // ?+=?
    309 
     151#endif // __STATISTICS__
     152
     153
     154#define SPINLOCK 0
     155#define LOCKFREE 1
     156#define BUCKETLOCK SPINLOCK
     157#if BUCKETLOCK == SPINLOCK
     158#elif BUCKETLOCK == LOCKFREE
     159#include <stackLockFree.hfa>
     160#else
     161        #error undefined lock type for bucket lock
     162#endif // LOCKFREE
     163
     164// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
     165// Break recursion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
     166enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
     167
     168struct Heap {
     169        struct Storage {
     170                struct Header {                                                                 // header
     171                        union Kind {
     172                                struct RealHeader {
     173                                        union {
     174                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
     175                                                        union {
     176                                                                // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped
     177                                                                // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
     178                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
     179                                                                size_t blockSize;               // size for munmap (must overlay alignment)
     180                                                                #if BUCKETLOCK == SPINLOCK
     181                                                                Storage * next;                 // freed block points to next freed block of same size
     182                                                                #endif // SPINLOCK
     183                                                        };
     184                                                        size_t size;                            // allocation size in bytes
     185                                                };
     186                                                #if BUCKETLOCK == LOCKFREE
     187                                                Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
     188                                                #endif // LOCKFREE
     189                                        };
     190                                } real; // RealHeader
     191
     192                                struct FakeHeader {
     193                                        uintptr_t alignment;                            // 1st low-order bit => fake header & alignment
     194                                        uintptr_t offset;
     195                                } fake; // FakeHeader
     196                        } kind; // Kind
     197                } header; // Header
     198
     199                char pad[libAlign() - sizeof( Header )];
     200                char data[0];                                                                   // storage
     201        }; // Storage
     202
     203        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
     204
     205        struct FreeHeader {
     206                size_t blockSize __attribute__(( aligned (8) )); // size of allocations on this list
     207                #if BUCKETLOCK == SPINLOCK
     208                __spinlock_t lock;
     209                Storage * freeList;
     210                #else
     211                StackLF(Storage) freeList;
     212                #endif // BUCKETLOCK
     213        } __attribute__(( aligned (8) )); // FreeHeader
     214
     215        FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
     216
     217        __spinlock_t extlock;                                                           // protects allocation-buffer extension
     218        void * heapBegin;                                                                       // start of heap
     219        void * heapEnd;                                                                         // logical end of heap
     220        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
     221}; // Heap
     222
     223#if BUCKETLOCK == LOCKFREE
     224static inline {
     225        Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
     226        void ?{}( Heap.FreeHeader & ) {}
     227        void ^?{}( Heap.FreeHeader & ) {}
     228} // distribution
     229#endif // LOCKFREE
     230
     231static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
     232
     233
     234#ifdef FASTLOOKUP
     235enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
     236static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
     237#endif // FASTLOOKUP
     238
     239static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
     240#ifdef __CFA_DEBUG__
     241static bool heapBoot = 0;                                                               // detect recursion during boot
     242#endif // __CFA_DEBUG__
     243
     244
     245// Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16.
     246// Smaller multiples of 16 and powers of 2 are common allocation sizes, so make them generate the minimum required bucket size.
     247// malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed.
     248static const unsigned int bucketSizes[] @= {                    // different bucket sizes
     249        16 + sizeof(Heap.Storage), 32 + sizeof(Heap.Storage), 48 + sizeof(Heap.Storage), 64 + sizeof(Heap.Storage), // 4
     250        96 + sizeof(Heap.Storage), 112 + sizeof(Heap.Storage), 128 + sizeof(Heap.Storage), // 3
     251        160, 192, 224, 256 + sizeof(Heap.Storage), // 4
     252        320, 384, 448, 512 + sizeof(Heap.Storage), // 4
     253        640, 768, 896, 1_024 + sizeof(Heap.Storage), // 4
     254        1_536, 2_048 + sizeof(Heap.Storage), // 2
     255        2_560, 3_072, 3_584, 4_096 + sizeof(Heap.Storage), // 4
     256        6_144, 8_192 + sizeof(Heap.Storage), // 2
     257        9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(Heap.Storage), // 8
     258        18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(Heap.Storage), // 8
     259        36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(Heap.Storage), // 8
     260        73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(Heap.Storage), // 8
     261        147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(Heap.Storage), // 8
     262        294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(Heap.Storage), // 8
     263        655_360, 786_432, 917_504, 1_048_576 + sizeof(Heap.Storage), // 4
     264        1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(Heap.Storage), // 8
     265        2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(Heap.Storage), // 4
     266};
     267
     268static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
     269
     270// The constructor for heapManager is called explicitly in memory_startup.
     271static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
     272
     273
     274//####################### Memory Allocation Routines Helpers ####################
     275
     276
     277#ifdef __CFA_DEBUG__
     278static size_t allocUnfreed;                                                             // running total of allocations minus frees
     279
     280static void prtUnfreed() {
     281        if ( allocUnfreed != 0 ) {
     282                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     283                char helpText[512];
     284                __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
     285                                                                        "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n"
     286                                                                        "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
     287                                                                        (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
     288        } // if
     289} // prtUnfreed
     290
     291extern int cfa_main_returned;                                                   // from interpose.cfa
     292extern "C" {
     293        void heapAppStart() {                                                           // called by __cfaabi_appready_startup
     294                allocUnfreed = 0;
     295        } // heapAppStart
     296
     297        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
     298                fclose( stdin ); fclose( stdout );
     299                if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
     300        } // heapAppStop
     301} // extern "C"
     302#endif // __CFA_DEBUG__
     303
     304
     305#ifdef __STATISTICS__
    310306static HeapStatistics stats;                                                    // zero filled
    311307static unsigned int sbrk_calls;
     
    387383
    388384
     385// statically allocated variables => zero filled.
     386static size_t heapExpand;                                                               // sbrk advance
     387static size_t mmapStart;                                                                // cross over point for mmap
     388static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
     389// extern visibility, used by runtime kernel
     390// would be cool to remove libcfa_public but it's needed for libcfathread
     391libcfa_public size_t __page_size;                                                       // architecture pagesize
     392libcfa_public int __map_prot;                                                           // common mmap/mprotect protection
     393
     394
    389395// thunk problem
    390396size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    490496        } else {
    491497                fakeHeader( header, alignment );
    492                 if ( unlikely( MmappedBit( header ) ) ) {
    493                         assert( addr < heapBegin || heapEnd < addr );
     498                if ( unlikely( MmappedBit( header ) ) ) {               // mmapped ?
     499                        verify( addr < heapBegin || heapEnd < addr );
    494500                        size = ClearStickyBits( header->kind.real.blockSize ); // mmap size
    495501                        return true;
     
    503509        checkHeader( header < (Heap.Storage.Header *)heapBegin || (Heap.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    504510
    505         if ( freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) {
    506                 abort( "Attempt to %s storage %p with corrupted header.\n"
    507                            "Possible cause is duplicate free on same block or overwriting of header information.",
    508                            name, addr );
    509         } // if
     511        Heap * homeManager;
     512        if ( unlikely( freeHead == 0p || // freed and only free-list node => null link
     513                                   // freed and link points at another free block not to a bucket in the bucket array.
     514                                   freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) ) {
     515                abort( "**** Error **** attempt to %s storage %p with corrupted header.\n"
     516                           "Possible cause is duplicate free on same block or overwriting of header information.",
     517                           name, addr );
     518        } // if
    510519        #endif // __CFA_DEBUG__
    511520
     
    560569                sbrk_storage += increase;
    561570                #endif // __STATISTICS__
     571
    562572                #ifdef __CFA_DEBUG__
    563573                // Set new memory to garbage so subsequent uninitialized usages might fail.
     
    565575                //Memset( (char *)heapEnd + heapRemaining, increase );
    566576                #endif // __CFA_DEBUG__
     577
    567578                rem = heapRemaining + increase - size;
    568579        } // if
     
    651662        __atomic_add_fetch( &allocUnfreed, tsize, __ATOMIC_SEQ_CST );
    652663        if ( traceHeap() ) {
    653                 enum { BufferSize = 64 };
    654                 char helpText[BufferSize];
    655                 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
    656                 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     664                char helpText[64];
     665                __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
     666                                                                        "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize ); // print debug/nodebug
    657667        } // if
    658668        #endif // __CFA_DEBUG__
     
    711721        if ( traceHeap() ) {
    712722                char helpText[64];
    713                 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    714                 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     723                __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
     724                                                                        "Free( %p ) size:%zu\n", addr, size ); // print debug/nodebug
    715725        } // if
    716726        #endif // __CFA_DEBUG__
     
    718728
    719729
    720 size_t prtFree( Heap & manager ) with( manager ) {
     730static size_t prtFree( Heap & manager ) with( manager ) {
    721731        size_t total = 0;
    722732        #ifdef __STATISTICS__
     
    870880        // Allocates size bytes and returns a pointer to the allocated memory.  The contents are undefined. If size is 0,
    871881        // then malloc() returns a unique pointer value that can later be successfully passed to free().
    872         void * malloc( size_t size ) {
     882        void * malloc( size_t size ) libcfa_public {
    873883                #ifdef __STATISTICS__
    874884                if ( likely( size > 0 ) ) {
     
    885895
    886896        // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes.
    887         void * aalloc( size_t dim, size_t elemSize ) {
     897        void * aalloc( size_t dim, size_t elemSize ) libcfa_public {
    888898                size_t size = dim * elemSize;
    889899                #ifdef __STATISTICS__
     
    901911
    902912        // Same as aalloc() with memory set to zero.
    903         void * calloc( size_t dim, size_t elemSize ) {
     913        void * calloc( size_t dim, size_t elemSize ) libcfa_public {
    904914                size_t size = dim * elemSize;
    905915          if ( unlikely( size ) == 0 ) {                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     
    942952        // not 0p, then the call is equivalent to free(oaddr). Unless oaddr is 0p, it must have been returned by an earlier
    943953        // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done.
    944         void * resize( void * oaddr, size_t size ) {
     954        void * resize( void * oaddr, size_t size ) libcfa_public {
    945955                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    946956          if ( unlikely( size == 0 ) ) {                                        // special cases
     
    987997        // Same as resize() but the contents are unchanged in the range from the start of the region up to the minimum of
    988998        // the old and new sizes.
    989         void * realloc( void * oaddr, size_t size ) {
     999        void * realloc( void * oaddr, size_t size ) libcfa_public {
    9901000                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    9911001          if ( unlikely( size == 0 ) ) {                                        // special cases
     
    10511061
    10521062        // Same as realloc() except the new allocation size is large enough for an array of nelem elements of size elsize.
    1053         void * reallocarray( void * oaddr, size_t dim, size_t elemSize ) {
     1063        void * reallocarray( void * oaddr, size_t dim, size_t elemSize ) libcfa_public {
    10541064                return realloc( oaddr, dim * elemSize );
    10551065        } // reallocarray
     
    10571067
    10581068        // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete)
    1059         void * memalign( size_t alignment, size_t size ) {
     1069        void * memalign( size_t alignment, size_t size ) libcfa_public {
    10601070                #ifdef __STATISTICS__
    10611071                if ( likely( size > 0 ) ) {
     
    10721082
    10731083        // Same as aalloc() with memory alignment.
    1074         void * amemalign( size_t alignment, size_t dim, size_t elemSize ) {
     1084        void * amemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
    10751085                size_t size = dim * elemSize;
    10761086                #ifdef __STATISTICS__
     
    10881098
    10891099        // Same as calloc() with memory alignment.
    1090         void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) {
     1100        void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
    10911101                size_t size = dim * elemSize;
    10921102          if ( unlikely( size ) == 0 ) {                                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     
    11271137        // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple
    11281138        // of alignment. This requirement is universally ignored.
    1129         void * aligned_alloc( size_t alignment, size_t size ) {
     1139        void * aligned_alloc( size_t alignment, size_t size ) libcfa_public {
    11301140                return memalign( alignment, size );
    11311141        } // aligned_alloc
     
    11361146        // is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later be successfully passed to
    11371147        // free(3).
    1138         int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
     1148        int posix_memalign( void ** memptr, size_t alignment, size_t size ) libcfa_public {
    11391149          if ( unlikely( alignment < libAlign() || ! is_pow2( alignment ) ) ) return EINVAL; // check alignment
    11401150                *memptr = memalign( alignment, size );
     
    11451155        // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the
    11461156        // page size.  It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
    1147         void * valloc( size_t size ) {
     1157        void * valloc( size_t size ) libcfa_public {
    11481158                return memalign( __page_size, size );
    11491159        } // valloc
     
    11511161
    11521162        // Same as valloc but rounds size to multiple of page size.
    1153         void * pvalloc( size_t size ) {
     1163        void * pvalloc( size_t size ) libcfa_public {
    11541164                return memalign( __page_size, ceiling2( size, __page_size ) ); // round size to multiple of page size
    11551165        } // pvalloc
     
    11591169        // or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is
    11601170        // 0p, no operation is performed.
    1161         void free( void * addr ) {
     1171        void free( void * addr ) libcfa_public {
    11621172          if ( unlikely( addr == 0p ) ) {                                       // special case
    11631173                        #ifdef __STATISTICS__
     
    11801190
    11811191        // Returns the alignment of an allocation.
    1182         size_t malloc_alignment( void * addr ) {
     1192        size_t malloc_alignment( void * addr ) libcfa_public {
    11831193          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    11841194                Heap.Storage.Header * header = HeaderAddr( addr );
     
    11921202
    11931203        // Returns true if the allocation is zero filled, e.g., allocated by calloc().
    1194         bool malloc_zero_fill( void * addr ) {
     1204        bool malloc_zero_fill( void * addr ) libcfa_public {
    11951205          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    11961206                Heap.Storage.Header * header = HeaderAddr( addr );
     
    12031213
    12041214        // Returns original total allocation size (not bucket size) => array size is dimension * sizeof(T).
    1205         size_t malloc_size( void * addr ) {
     1215        size_t malloc_size( void * addr ) libcfa_public {
    12061216          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    12071217                Heap.Storage.Header * header = HeaderAddr( addr );
     
    12151225        // Returns the number of usable bytes in the block pointed to by ptr, a pointer to a block of memory allocated by
    12161226        // malloc or a related function.
    1217         size_t malloc_usable_size( void * addr ) {
     1227        size_t malloc_usable_size( void * addr ) libcfa_public {
    12181228          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    12191229                Heap.Storage.Header * header;
     
    12271237
    12281238        // Prints (on default standard error) statistics about memory allocated by malloc and related functions.
    1229         void malloc_stats( void ) {
     1239        void malloc_stats( void ) libcfa_public {
    12301240                #ifdef __STATISTICS__
    12311241                printStats();
     
    12361246
    12371247        // Changes the file descriptor where malloc_stats() writes statistics.
    1238         int malloc_stats_fd( int fd __attribute__(( unused )) ) {
     1248        int malloc_stats_fd( int fd __attribute__(( unused )) ) libcfa_public {
    12391249                #ifdef __STATISTICS__
    12401250                int temp = stats_fd;
     
    12501260        // The string is printed on the file stream stream.  The exported string includes information about all arenas (see
    12511261        // malloc).
    1252         int malloc_info( int options, FILE * stream __attribute__(( unused )) ) {
     1262        int malloc_info( int options, FILE * stream __attribute__(( unused )) ) libcfa_public {
    12531263          if ( options != 0 ) { errno = EINVAL; return -1; }
    12541264                #ifdef __STATISTICS__
     
    12621272        // Adjusts parameters that control the behaviour of the memory-allocation functions (see malloc). The param argument
    12631273        // specifies the parameter to be modified, and value specifies the new value for that parameter.
    1264         int mallopt( int option, int value ) {
     1274        int mallopt( int option, int value ) libcfa_public {
    12651275          if ( value < 0 ) return 0;
    12661276                choose( option ) {
     
    12761286
    12771287        // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument).
    1278         int malloc_trim( size_t ) {
     1288        int malloc_trim( size_t ) libcfa_public {
    12791289                return 0;                                                                               // => impossible to release memory
    12801290        } // malloc_trim
     
    12851295        // structure dynamically allocated via malloc, and a pointer to that data structure is returned as the function
    12861296        // result.  (The caller must free this memory.)
    1287         void * malloc_get_state( void ) {
     1297        void * malloc_get_state( void ) libcfa_public {
    12881298                return 0p;                                                                              // unsupported
    12891299        } // malloc_get_state
     
    12921302        // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data
    12931303        // structure pointed to by state.
    1294         int malloc_set_state( void * ) {
     1304        int malloc_set_state( void * ) libcfa_public {
    12951305                return 0;                                                                               // unsupported
    12961306        } // malloc_set_state
     
    12981308
    12991309        // Sets the amount (bytes) to extend the heap when there is insufficent free storage to service an allocation.
    1300         __attribute__((weak)) size_t malloc_expansion() { return __CFA_DEFAULT_HEAP_EXPANSION__; }
     1310        __attribute__((weak)) size_t malloc_expansion() libcfa_public { return __CFA_DEFAULT_HEAP_EXPANSION__; }
    13011311
    13021312        // Sets the crossover point between allocations occuring in the sbrk area or separately mmapped.
    1303         __attribute__((weak)) size_t malloc_mmap_start() { return __CFA_DEFAULT_MMAP_START__; }
     1313        __attribute__((weak)) size_t malloc_mmap_start() libcfa_public { return __CFA_DEFAULT_MMAP_START__; }
    13041314
    13051315        // Amount subtracted to adjust for unfreed program storage (debug only).
    1306         __attribute__((weak)) size_t malloc_unfreed() { return __CFA_DEFAULT_HEAP_UNFREED__; }
     1316        __attribute__((weak)) size_t malloc_unfreed() libcfa_public { return __CFA_DEFAULT_HEAP_UNFREED__; }
    13071317} // extern "C"
    13081318
    13091319
    13101320// Must have CFA linkage to overload with C linkage realloc.
    1311 void * resize( void * oaddr, size_t nalign, size_t size ) {
     1321void * resize( void * oaddr, size_t nalign, size_t size ) libcfa_public {
    13121322        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    13131323  if ( unlikely( size == 0 ) ) {                                                // special cases
     
    13711381
    13721382
    1373 void * realloc( void * oaddr, size_t nalign, size_t size ) {
     1383void * realloc( void * oaddr, size_t nalign, size_t size ) libcfa_public {
    13741384        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    13751385  if ( unlikely( size == 0 ) ) {                                                // special cases
Note: See TracChangeset for help on using the changeset viewer.