Changeset 31a5f418


Ignore:
Timestamp:
Apr 22, 2022, 6:36:18 PM (22 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
Children:
58e97d9
Parents:
16cc9f7
Message:

start update of heap allocator to new heap-per-thread version

Location:
libcfa/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    r16cc9f7 r31a5f418  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan  2 23:29:41 2022
    13 // Update Count     : 1058
     12// Last Modified On : Fri Apr 22 18:25:23 2022
     13// Update Count     : 1121
    1414//
    1515
    16 #include <unistd.h>                                                                             // sbrk, sysconf
    17 #include <stdlib.h>                                                                             // EXIT_FAILURE
    18 #include <stdbool.h>                                                                    // true, false
    19 #include <stdio.h>                                                                              // snprintf, fileno
    20 #include <errno.h>                                                                              // errno
    2116#include <string.h>                                                                             // memset, memcpy
    2217#include <limits.h>                                                                             // ULONG_MAX
     18#include <stdlib.h>                                                                             // EXIT_FAILURE
     19#include <errno.h>                                                                              // errno, ENOMEM, EINVAL
     20#include <unistd.h>                                                                             // STDERR_FILENO, sbrk, sysconf
    2321#include <malloc.h>                                                                             // memalign, malloc_usable_size
    2422#include <sys/mman.h>                                                                   // mmap, munmap
     23#include <sys/sysinfo.h>                                                                // get_nprocs
    2524
    2625#include "bits/align.hfa"                                                               // libAlign
     
    3130#include "bitmanip.hfa"                                                                 // is_pow2, ceiling2
    3231
     32#define FASTLOOKUP
     33#define __STATISTICS__
     34
     35
    3336static bool traceHeap = false;
    3437
     
    7073
    7174enum {
    72         // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
    73         // the brk address is extended by the extension amount.
    74         __CFA_DEFAULT_HEAP_EXPANSION__ = (10 * 1024 * 1024),
    75 
    76         // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
    77         // values greater than or equal to this value are mmap from the operating system.
    78         __CFA_DEFAULT_MMAP_START__ = (512 * 1024 + 1),
    79 };
    80 
    81 size_t default_mmap_start() __attribute__(( weak )) {
    82         return __CFA_DEFAULT_MMAP_START__;
    83 } // default_mmap_start
    84 
    85 size_t default_heap_expansion() __attribute__(( weak )) {
    86         return __CFA_DEFAULT_HEAP_EXPANSION__;
    87 } // default_heap_expansion
     75        // The default extension heap amount in units of bytes. When the current heap reaches the brk address, the brk
     76        // address is extended by the extension amount.
     77        __CFA_DEFAULT_HEAP_EXPANSION__ = 10 * 1024 * 1024,
     78
     79        // The mmap crossover point during allocation. Allocations less than this amount are allocated from buckets; values
     80        // greater than or equal to this value are mmap from the operating system.
     81        __CFA_DEFAULT_MMAP_START__ = 512 * 1024 + 1,
     82
     83        // The default unfreed storage amount in units of bytes. When the uC++ program ends it subtracts this amount from
     84        // the malloc/free counter to adjust for storage the program does not free.
     85        __CFA_DEFAULT_HEAP_UNFREED__ = 0
     86}; // enum
    8887
    8988
     
    135134
    136135// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    137 // Break recusion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
     136// Break recursion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    138137enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
    139138
    140 struct HeapManager {
     139struct Heap {
    141140        struct Storage {
    142141                struct Header {                                                                 // header
     
    145144                                        union {
    146145                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    147                                                         #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    148                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    149                                                         #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    150 
    151146                                                        union {
     147                                                                // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped
    152148                                                                // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
    153                                                                 // 2nd low-order bit => zero filled
    154149                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
    155150                                                                size_t blockSize;               // size for munmap (must overlay alignment)
    156151                                                                #if BUCKETLOCK == SPINLOCK
    157                                                                 Storage * next;                 // freed block points next freed block of same size
     152                                                                Storage * next;                 // freed block points to next freed block of same size
    158153                                                                #endif // SPINLOCK
    159154                                                        };
    160155                                                        size_t size;                            // allocation size in bytes
    161 
    162                                                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    163                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    164                                                         #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    165156                                                };
    166157                                                #if BUCKETLOCK == LOCKFREE
     
    171162
    172163                                struct FakeHeader {
    173                                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    174                                         uint32_t alignment;                                     // 1st low-order bit => fake header & alignment
    175                                         #endif // __ORDER_LITTLE_ENDIAN__
    176 
    177                                         uint32_t offset;
    178 
    179                                         #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    180                                         uint32_t alignment;                                     // low-order bits of home/blockSize used for tricks
    181                                         #endif // __ORDER_BIG_ENDIAN__
     164                                        uintptr_t alignment;                            // 1st low-order bit => fake header & alignment
     165                                        uintptr_t offset;
    182166                                } fake; // FakeHeader
    183167                        } kind; // Kind
    184168                } header; // Header
     169
    185170                char pad[libAlign() - sizeof( Header )];
    186171                char data[0];                                                                   // storage
    187172        }; // Storage
    188173
    189         static_assert( libAlign() >= sizeof( Storage ), "libAlign() < sizeof( Storage )" );
     174        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    190175
    191176        struct FreeHeader {
     
    206191        void * heapEnd;                                                                         // logical end of heap
    207192        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    208 }; // HeapManager
     193}; // Heap
    209194
    210195#if BUCKETLOCK == LOCKFREE
    211196static inline {
    212         Link(HeapManager.Storage) * ?`next( HeapManager.Storage * this ) { return &this->header.kind.real.next; }
    213         void ?{}( HeapManager.FreeHeader & ) {}
    214         void ^?{}( HeapManager.FreeHeader & ) {}
     197        Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
     198        void ?{}( Heap.FreeHeader & ) {}
     199        void ^?{}( Heap.FreeHeader & ) {}
    215200} // distribution
    216201#endif // LOCKFREE
    217202
    218 static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
    219 
    220 
    221 #define FASTLOOKUP
    222 #define __STATISTICS__
     203static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
     204
     205
     206#ifdef FASTLOOKUP
     207enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
     208static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
     209#endif // FASTLOOKUP
     210
     211static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
     212#ifdef __CFA_DEBUG__
     213static bool heapBoot = 0;                                                               // detect recursion during boot
     214#endif // __CFA_DEBUG__
     215
    223216
    224217// Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16.
     
    226219// malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed.
    227220static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    228         16 + sizeof(HeapManager.Storage), 32 + sizeof(HeapManager.Storage), 48 + sizeof(HeapManager.Storage), 64 + sizeof(HeapManager.Storage), // 4
    229         96 + sizeof(HeapManager.Storage), 112 + sizeof(HeapManager.Storage), 128 + sizeof(HeapManager.Storage), // 3
    230         160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
    231         320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
    232         640, 768, 896, 1_024 + sizeof(HeapManager.Storage), // 4
    233         1_536, 2_048 + sizeof(HeapManager.Storage), // 2
    234         2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), // 4
    235         6_144, 8_192 + sizeof(HeapManager.Storage), // 2
    236         9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(HeapManager.Storage), // 8
    237         18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(HeapManager.Storage), // 8
    238         36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(HeapManager.Storage), // 8
    239         73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(HeapManager.Storage), // 8
    240         147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(HeapManager.Storage), // 8
    241         294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(HeapManager.Storage), // 8
    242         655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), // 4
    243         1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), // 8
    244         2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(HeapManager.Storage), // 4
     221        16 + sizeof(Heap.Storage), 32 + sizeof(Heap.Storage), 48 + sizeof(Heap.Storage), 64 + sizeof(Heap.Storage), // 4
     222        96 + sizeof(Heap.Storage), 112 + sizeof(Heap.Storage), 128 + sizeof(Heap.Storage), // 3
     223        160, 192, 224, 256 + sizeof(Heap.Storage), // 4
     224        320, 384, 448, 512 + sizeof(Heap.Storage), // 4
     225        640, 768, 896, 1_024 + sizeof(Heap.Storage), // 4
     226        1_536, 2_048 + sizeof(Heap.Storage), // 2
     227        2_560, 3_072, 3_584, 4_096 + sizeof(Heap.Storage), // 4
     228        6_144, 8_192 + sizeof(Heap.Storage), // 2
     229        9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(Heap.Storage), // 8
     230        18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(Heap.Storage), // 8
     231        36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(Heap.Storage), // 8
     232        73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(Heap.Storage), // 8
     233        147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(Heap.Storage), // 8
     234        294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(Heap.Storage), // 8
     235        655_360, 786_432, 917_504, 1_048_576 + sizeof(Heap.Storage), // 4
     236        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
     237        2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(Heap.Storage), // 4
    245238};
    246239
    247240static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    248241
    249 #ifdef FASTLOOKUP
    250 enum { LookupSizes = 65_536 + sizeof(HeapManager.Storage) }; // number of fast lookup sizes
    251 static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    252 #endif // FASTLOOKUP
    253 
    254 static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
    255 #ifdef __CFA_DEBUG__
    256 static bool heapBoot = 0;                                                               // detect recursion during boot
    257 #endif // __CFA_DEBUG__
    258242
    259243// The constructor for heapManager is called explicitly in memory_startup.
    260 static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
     244static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    261245
    262246
    263247#ifdef __STATISTICS__
     248enum { CntTriples = 12 };                                                               // number of counter triples
     249enum { MALLOC, AALLOC, CALLOC, MEMALIGN, AMEMALIGN, CMEMALIGN, RESIZE, REALLOC, FREE };
     250
     251struct StatsOverlay {                                                                   // overlay for iteration
     252        unsigned int calls, calls_0;
     253        unsigned long long int request, alloc;
     254};
     255
    264256// Heap statistics counters.
    265 static unsigned int malloc_calls, malloc_0_calls;
    266 static unsigned long long int malloc_storage_request, malloc_storage_alloc;
    267 static unsigned int aalloc_calls, aalloc_0_calls;
    268 static unsigned long long int aalloc_storage_request, aalloc_storage_alloc;
    269 static unsigned int calloc_calls, calloc_0_calls;
    270 static unsigned long long int calloc_storage_request, calloc_storage_alloc;
    271 static unsigned int memalign_calls, memalign_0_calls;
    272 static unsigned long long int memalign_storage_request, memalign_storage_alloc;
    273 static unsigned int amemalign_calls, amemalign_0_calls;
    274 static unsigned long long int amemalign_storage_request, amemalign_storage_alloc;
    275 static unsigned int cmemalign_calls, cmemalign_0_calls;
    276 static unsigned long long int cmemalign_storage_request, cmemalign_storage_alloc;
    277 static unsigned int resize_calls, resize_0_calls;
    278 static unsigned long long int resize_storage_request, resize_storage_alloc;
    279 static unsigned int realloc_calls, realloc_0_calls;
    280 static unsigned long long int realloc_storage_request, realloc_storage_alloc;
    281 static unsigned int free_calls, free_null_calls;
    282 static unsigned long long int free_storage_request, free_storage_alloc;
    283 static unsigned int mmap_calls;
    284 static unsigned long long int mmap_storage_request, mmap_storage_alloc;
    285 static unsigned int munmap_calls;
    286 static unsigned long long int munmap_storage_request, munmap_storage_alloc;
     257union HeapStatistics {
     258        struct {                                                                                        // minimum qualification
     259                unsigned int malloc_calls, malloc_0_calls;
     260                unsigned long long int malloc_storage_request, malloc_storage_alloc;
     261                unsigned int aalloc_calls, aalloc_0_calls;
     262                unsigned long long int aalloc_storage_request, aalloc_storage_alloc;
     263                unsigned int calloc_calls, calloc_0_calls;
     264                unsigned long long int calloc_storage_request, calloc_storage_alloc;
     265                unsigned int memalign_calls, memalign_0_calls;
     266                unsigned long long int memalign_storage_request, memalign_storage_alloc;
     267                unsigned int amemalign_calls, amemalign_0_calls;
     268                unsigned long long int amemalign_storage_request, amemalign_storage_alloc;
     269                unsigned int cmemalign_calls, cmemalign_0_calls;
     270                unsigned long long int cmemalign_storage_request, cmemalign_storage_alloc;
     271                unsigned int resize_calls, resize_0_calls;
     272                unsigned long long int resize_storage_request, resize_storage_alloc;
     273                unsigned int realloc_calls, realloc_0_calls;
     274                unsigned long long int realloc_storage_request, realloc_storage_alloc;
     275                unsigned int free_calls, free_null_calls;
     276                unsigned long long int free_storage_request, free_storage_alloc;
     277                unsigned int away_pulls, away_pushes;
     278                unsigned long long int away_storage_request, away_storage_alloc;
     279                unsigned int mmap_calls, mmap_0_calls;                  // no zero calls
     280                unsigned long long int mmap_storage_request, mmap_storage_alloc;
     281                unsigned int munmap_calls, munmap_0_calls;              // no zero calls
     282                unsigned long long int munmap_storage_request, munmap_storage_alloc;
     283        };
     284        struct StatsOverlay counters[CntTriples];                       // overlay for iteration
     285}; // HeapStatistics
     286
     287static_assert( sizeof(HeapStatistics) == CntTriples * sizeof(StatsOverlay),
     288                           "Heap statistics counter-triplets does not match with array size" );
     289
     290static void HeapStatisticsCtor( HeapStatistics & stats ) {
     291        memset( &stats, '\0', sizeof(stats) );                          // very fast
     292        // for ( unsigned int i = 0; i < CntTriples; i += 1 ) {
     293        //      stats.counters[i].calls = stats.counters[i].calls_0 = stats.counters[i].request = stats.counters[i].alloc = 0;
     294        // } // for
     295} // HeapStatisticsCtor
     296
     297static HeapStatistics & ?+=?( HeapStatistics & lhs, const HeapStatistics & rhs ) {
     298        for ( unsigned int i = 0; i < CntTriples; i += 1 ) {
     299                lhs.counters[i].calls += rhs.counters[i].calls;
     300                lhs.counters[i].calls_0 += rhs.counters[i].calls_0;
     301                lhs.counters[i].request += rhs.counters[i].request;
     302                lhs.counters[i].alloc += rhs.counters[i].alloc;
     303        } // for
     304        return lhs;
     305} // ?+=?
     306
     307static HeapStatistics stats;                                                    // zero filled
    287308static unsigned int sbrk_calls;
    288309static unsigned long long int sbrk_storage;
     
    290311static int stats_fd = STDERR_FILENO;                                    // default stderr
    291312
     313#define prtFmt \
     314        "\nHeap statistics: (storage request / allocation)\n" \
     315        "  malloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     316        "  aalloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     317        "  calloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     318        "  memalign  >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     319        "  amemalign >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     320        "  cmemalign >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     321        "  resize    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     322        "  realloc   >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
     323        "  free      !null calls %'u; null calls %'u; storage %'llu / %'llu bytes\n" \
     324        "  sbrk      calls %'u; storage %'llu bytes\n"                                          \
     325        "  mmap      calls %'u; storage %'llu / %'llu bytes\n"                          \
     326        "  munmap    calls %'u; storage %'llu / %'llu bytes\n"                          \
     327
    292328// Use "write" because streams may be shutdown when calls are made.
    293 static void printStats() {
    294         char helpText[1024];
    295         __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    296                                                                 "\nHeap statistics: (storage request / allocation + header)\n"
    297                                                                 "  malloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    298                                                                 "  aalloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    299                                                                 "  calloc    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    300                                                                 "  memalign  >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    301                                                                 "  amemalign >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    302                                                                 "  cmemalign >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    303                                                                 "  resize    >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    304                                                                 "  realloc   >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n"
    305                                                                 "  free      !null calls %'u; null calls %'u; storage %'llu / %'llu bytes\n"
    306                                                                 "  sbrk      calls %'u; storage %'llu bytes\n"
    307                                                                 "  mmap      calls %'u; storage %'llu / %'llu bytes\n"
    308                                                                 "  munmap    calls %'u; storage %'llu / %'llu bytes\n",
    309                                                                 malloc_calls, malloc_0_calls, malloc_storage_request, malloc_storage_alloc,
    310                                                                 aalloc_calls, aalloc_0_calls, aalloc_storage_request, aalloc_storage_alloc,
    311                                                                 calloc_calls, calloc_0_calls, calloc_storage_request, calloc_storage_alloc,
    312                                                                 memalign_calls, memalign_0_calls, memalign_storage_request, memalign_storage_alloc,
    313                                                                 amemalign_calls, amemalign_0_calls, amemalign_storage_request, amemalign_storage_alloc,
    314                                                                 cmemalign_calls, cmemalign_0_calls, cmemalign_storage_request, cmemalign_storage_alloc,
    315                                                                 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc,
    316                                                                 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc,
    317                                                                 free_calls, free_null_calls, free_storage_request, free_storage_alloc,
    318                                                                 sbrk_calls, sbrk_storage,
    319                                                                 mmap_calls, mmap_storage_request, mmap_storage_alloc,
    320                                                                 munmap_calls, munmap_storage_request, munmap_storage_alloc
     329static void printStats() {                                                              // see malloc_stats
     330        char helpText[sizeof(prtFmt) + 1024];                           // space for message and values
     331        __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), prtFmt,
     332                        stats.malloc_calls, stats.malloc_0_calls, stats.malloc_storage_request, stats.malloc_storage_alloc,
     333                        stats.aalloc_calls, stats.aalloc_0_calls, stats.aalloc_storage_request, stats.aalloc_storage_alloc,
     334                        stats.calloc_calls, stats.calloc_0_calls, stats.calloc_storage_request, stats.calloc_storage_alloc,
     335                        stats.memalign_calls, stats.memalign_0_calls, stats.memalign_storage_request, stats.memalign_storage_alloc,
     336                        stats.amemalign_calls, stats.amemalign_0_calls, stats.amemalign_storage_request, stats.amemalign_storage_alloc,
     337                        stats.cmemalign_calls, stats.cmemalign_0_calls, stats.cmemalign_storage_request, stats.cmemalign_storage_alloc,
     338                        stats.resize_calls, stats.resize_0_calls, stats.resize_storage_request, stats.resize_storage_alloc,
     339                        stats.realloc_calls, stats.realloc_0_calls, stats.realloc_storage_request, stats.realloc_storage_alloc,
     340                        stats.free_calls, stats.free_null_calls, stats.free_storage_request, stats.free_storage_alloc,
     341                        sbrk_calls, sbrk_storage,
     342                        stats.mmap_calls, stats.mmap_storage_request, stats.mmap_storage_alloc,
     343                        stats.munmap_calls, stats.munmap_storage_request, stats.munmap_storage_alloc
    321344                );
    322345} // printStats
    323346
     347#define prtFmtXML \
     348        "<malloc version=\"1\">\n" \
     349        "<heap nr=\"0\">\n" \
     350        "<sizes>\n" \
     351        "</sizes>\n" \
     352        "<total type=\"malloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     353        "<total type=\"aalloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     354        "<total type=\"calloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     355        "<total type=\"memalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     356        "<total type=\"amemalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     357        "<total type=\"cmemalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     358        "<total type=\"resize\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     359        "<total type=\"realloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     360        "<total type=\"free\" !null=\"%'u;\" 0 null=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     361        "<total type=\"sbrk\" count=\"%'u;\" size=\"%'llu\"/> bytes\n" \
     362        "<total type=\"mmap\" count=\"%'u;\" size=\"%'llu / %'llu\" / > bytes\n" \
     363        "<total type=\"munmap\" count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
     364        "</malloc>"
     365
    324366static int printStatsXML( FILE * stream ) {                             // see malloc_info
    325         char helpText[1024];
    326         int len = snprintf( helpText, sizeof(helpText),
    327                                                 "<malloc version=\"1\">\n"
    328                                                 "<heap nr=\"0\">\n"
    329                                                 "<sizes>\n"
    330                                                 "</sizes>\n"
    331                                                 "<total type=\"malloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    332                                                 "<total type=\"aalloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    333                                                 "<total type=\"calloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    334                                                 "<total type=\"memalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    335                                                 "<total type=\"amemalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    336                                                 "<total type=\"cmemalign\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    337                                                 "<total type=\"resize\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    338                                                 "<total type=\"realloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    339                                                 "<total type=\"free\" !null=\"%'u;\" 0 null=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    340                                                 "<total type=\"sbrk\" count=\"%'u;\" size=\"%'llu\"/> bytes\n"
    341                                                 "<total type=\"mmap\" count=\"%'u;\" size=\"%'llu / %'llu\" / > bytes\n"
    342                                                 "<total type=\"munmap\" count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n"
    343                                                 "</malloc>",
    344                                                 malloc_calls, malloc_0_calls, malloc_storage_request, malloc_storage_alloc,
    345                                                 aalloc_calls, aalloc_0_calls, aalloc_storage_request, aalloc_storage_alloc,
    346                                                 calloc_calls, calloc_0_calls, calloc_storage_request, calloc_storage_alloc,
    347                                                 memalign_calls, memalign_0_calls, memalign_storage_request, memalign_storage_alloc,
    348                                                 amemalign_calls, amemalign_0_calls, amemalign_storage_request, amemalign_storage_alloc,
    349                                                 cmemalign_calls, cmemalign_0_calls, cmemalign_storage_request, cmemalign_storage_alloc,
    350                                                 resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc,
    351                                                 realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc,
    352                                                 free_calls, free_null_calls, free_storage_request, free_storage_alloc,
    353                                                 sbrk_calls, sbrk_storage,
    354                                                 mmap_calls, mmap_storage_request, mmap_storage_alloc,
    355                                                 munmap_calls, munmap_storage_request, munmap_storage_alloc
     367        char helpText[sizeof(prtFmtXML) + 1024];                        // space for message and values
     368        return __cfaabi_bits_print_buffer( fileno( stream ), helpText, sizeof(helpText), prtFmtXML,
     369                        stats.malloc_calls, stats.malloc_0_calls, stats.malloc_storage_request, stats.malloc_storage_alloc,
     370                        stats.aalloc_calls, stats.aalloc_0_calls, stats.aalloc_storage_request, stats.aalloc_storage_alloc,
     371                        stats.calloc_calls, stats.calloc_0_calls, stats.calloc_storage_request, stats.calloc_storage_alloc,
     372                        stats.memalign_calls, stats.memalign_0_calls, stats.memalign_storage_request, stats.memalign_storage_alloc,
     373                        stats.amemalign_calls, stats.amemalign_0_calls, stats.amemalign_storage_request, stats.amemalign_storage_alloc,
     374                        stats.cmemalign_calls, stats.cmemalign_0_calls, stats.cmemalign_storage_request, stats.cmemalign_storage_alloc,
     375                        stats.resize_calls, stats.resize_0_calls, stats.resize_storage_request, stats.resize_storage_alloc,
     376                        stats.realloc_calls, stats.realloc_0_calls, stats.realloc_storage_request, stats.realloc_storage_alloc,
     377                        stats.free_calls, stats.free_null_calls, stats.free_storage_request, stats.free_storage_alloc,
     378                        sbrk_calls, sbrk_storage,
     379                        stats.mmap_calls, stats.mmap_storage_request, stats.mmap_storage_alloc,
     380                        stats.munmap_calls, stats.munmap_storage_request, stats.munmap_storage_alloc
    356381                );
    357         __cfaabi_bits_write( fileno( stream ), helpText, len ); // ensures all bytes written or exit
    358         return len;
    359382} // printStatsXML
    360383#endif // __STATISTICS__
     
    394417// <-----------------<------------+-----------------------------> bsize (bucket size)
    395418//                   |fake-header | addr
    396 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    397 #define realHeader( header ) ((HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset))
     419#define headerAddr( addr ) ((Heap.Storage.Header *)( (char *)addr - sizeof(Heap.Storage) ))
     420#define realHeader( header ) ((Heap.Storage.Header *)((char *)header - header->kind.fake.offset))
    398421
    399422// <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
     
    422445
    423446
    424 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) {
     447static inline void fakeHeader( Heap.Storage.Header *& header, size_t & alignment ) {
    425448        if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    426449                alignment = header->kind.fake.alignment & -2;   // remove flag from value
     
    435458
    436459
    437 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem,
     460static inline bool headers( const char name[] __attribute__(( unused )), void * addr, Heap.Storage.Header *& header, Heap.FreeHeader *& freeElem,
    438461                                                        size_t & size, size_t & alignment ) with( heapManager ) {
    439462        header = headerAddr( addr );
     
    446469
    447470        #ifdef __CFA_DEBUG__
    448         checkHeader( header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     471        checkHeader( header < (Heap.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    449472        #endif // __CFA_DEBUG__
    450473
     
    452475        fakeHeader( header, alignment );
    453476        #ifdef __CFA_DEBUG__
    454         checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     477        checkHeader( header < (Heap.Storage.Header *)heapBegin || (Heap.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    455478        #endif // __CFA_DEBUG__
    456479
    457         freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
     480        freeElem = (Heap.FreeHeader *)((size_t)header->kind.real.home & -3);
    458481        #ifdef __CFA_DEBUG__
    459482        if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
     
    519542        } // if
    520543
    521         HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
     544        Heap.Storage * block = (Heap.Storage *)heapEnd;
    522545        heapRemaining = rem;
    523546        heapEnd = (char *)heapEnd + size;
     
    528551
    529552static inline void * doMalloc( size_t size ) with( heapManager ) {
    530         HeapManager.Storage * block;                                            // pointer to new block of storage
     553        Heap.Storage * block;                                           // pointer to new block of storage
    531554
    532555        // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
    533556        // along with the block and is a multiple of the alignment size.
    534557
    535   if ( unlikely( size > ULONG_MAX - sizeof(HeapManager.Storage) ) ) return 0p;
    536         size_t tsize = size + sizeof(HeapManager.Storage);
     558  if ( unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) return 0p;
     559        size_t tsize = size + sizeof(Heap.Storage);
    537560        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
    538561                size_t posn;
     
    542565                #endif // FASTLOOKUP
    543566                        posn = Bsearchl( (unsigned int)tsize, bucketSizes, (size_t)maxBucketsUsed );
    544                 HeapManager.FreeHeader * freeElem = &freeLists[posn];
     567                Heap.FreeHeader * freeElem = &freeLists[posn];
    545568                verify( freeElem <= &freeLists[maxBucketsUsed] ); // subscripting error ?
    546569                verify( tsize <= freeElem->blockSize );                 // search failure ?
     
    563586                        // and then carve it off.
    564587
    565                         block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
     588                        block = (Heap.Storage *)extend( tsize );        // mutual exclusion on call
    566589                #if BUCKETLOCK == SPINLOCK
    567590                } else {
     
    576599                tsize = ceiling2( tsize, __page_size );                 // must be multiple of page size
    577600                #ifdef __STATISTICS__
    578                 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
    579                 __atomic_add_fetch( &mmap_storage_request, size, __ATOMIC_SEQ_CST );
    580                 __atomic_add_fetch( &mmap_storage_alloc, tsize, __ATOMIC_SEQ_CST );
    581                 #endif // __STATISTICS__
    582 
    583                 block = (HeapManager.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
    584                 if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ?
     601                __atomic_add_fetch( &stats.mmap_calls, 1, __ATOMIC_SEQ_CST );
     602                __atomic_add_fetch( &stats.mmap_storage_request, size, __ATOMIC_SEQ_CST );
     603                __atomic_add_fetch( &stats.mmap_storage_alloc, tsize, __ATOMIC_SEQ_CST );
     604                #endif // __STATISTICS__
     605
     606                block = (Heap.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
     607                if ( block == (Heap.Storage *)MAP_FAILED ) { // failed ?
    585608                        if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory
    586609                        // Do not call strerror( errno ) as it may call malloc.
    587                         abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu errno:%d.", &heapManager, tsize, errno );
     610                        abort( "(Heap &)0x%p.doMalloc() : internal error, mmap failure, size:%zu errno:%d.", &heapManager, tsize, errno );
    588611                } //if
    589612                #ifdef __CFA_DEBUG__
     
    620643        #endif // __CFA_DEBUG__
    621644
    622         HeapManager.Storage.Header * header;
    623         HeapManager.FreeHeader * freeElem;
     645        Heap.Storage.Header * header;
     646        Heap.FreeHeader * freeElem;
    624647        size_t size, alignment;                                                         // not used (see realloc)
    625648
    626649        if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
    627650                #ifdef __STATISTICS__
    628                 __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );
    629                 __atomic_add_fetch( &munmap_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
    630                 __atomic_add_fetch( &munmap_storage_alloc, size, __ATOMIC_SEQ_CST );
     651                __atomic_add_fetch( &stats.munmap_calls, 1, __ATOMIC_SEQ_CST );
     652                __atomic_add_fetch( &stats.munmap_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
     653                __atomic_add_fetch( &stats.munmap_storage_alloc, size, __ATOMIC_SEQ_CST );
    631654                #endif // __STATISTICS__
    632655                if ( munmap( header, size ) == -1 ) {
     
    638661                #ifdef __CFA_DEBUG__
    639662                // Set free memory to garbage so subsequent usages might fail.
    640                 memset( ((HeapManager.Storage *)header)->data, '\xde', freeElem->blockSize - sizeof( HeapManager.Storage ) );
    641                 //Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );
     663                memset( ((Heap.Storage *)header)->data, '\xde', freeElem->blockSize - sizeof( Heap.Storage ) );
     664                //Memset( ((Heap.Storage *)header)->data, freeElem->blockSize - sizeof( Heap.Storage ) );
    642665                #endif // __CFA_DEBUG__
    643666
    644667                #ifdef __STATISTICS__
    645                 __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );
    646                 __atomic_add_fetch( &free_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
    647                 __atomic_add_fetch( &free_storage_alloc, size, __ATOMIC_SEQ_CST );
     668                __atomic_add_fetch( &stats.free_calls, 1, __ATOMIC_SEQ_CST );
     669                __atomic_add_fetch( &stats.free_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
     670                __atomic_add_fetch( &stats.free_storage_alloc, size, __ATOMIC_SEQ_CST );
    648671                #endif // __STATISTICS__
    649672
     
    651674                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    652675                header->kind.real.next = freeElem->freeList;    // push on stack
    653                 freeElem->freeList = (HeapManager.Storage *)header;
     676                freeElem->freeList = (Heap.Storage *)header;
    654677                unlock( freeElem->lock );                                               // release spin lock
    655678                #else
    656                 push( freeElem->freeList, *(HeapManager.Storage *)header );
     679                push( freeElem->freeList, *(Heap.Storage *)header );
    657680                #endif // BUCKETLOCK
    658681        } // if
     
    669692
    670693
    671 size_t prtFree( HeapManager & manager ) with( manager ) {
     694size_t prtFree( Heap & manager ) with( manager ) {
    672695        size_t total = 0;
    673696        #ifdef __STATISTICS__
     
    682705
    683706                #if BUCKETLOCK == SPINLOCK
    684                 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
     707                for ( Heap.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    685708                #else
    686709                        for(;;) {
    687 //              for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) {
    688 //              for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
    689 //                      HeapManager.Storage * temp = p->header.kind.real.next.top; // FIX ME: direct assignent fails, initialization works`
     710//              for ( Heap.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) {
     711//              for ( Heap.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
     712//                      Heap.Storage * temp = p->header.kind.real.next.top; // FIX ME: direct assignent fails, initialization works`
    690713//                      typeof(p) temp = (( p )`next)->top;                     // FIX ME: direct assignent fails, initialization works`
    691714//                      p = temp;
     
    710733
    711734
    712 static void ?{}( HeapManager & manager ) with( manager ) {
     735static void ?{}( Heap & manager ) with( manager ) {
    713736        __page_size = sysconf( _SC_PAGESIZE );
    714737        __map_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
     
    726749        #endif // FASTLOOKUP
    727750
    728         if ( ! setMmapStart( default_mmap_start() ) ) {
    729                 abort( "HeapManager : internal error, mmap start initialization failure." );
    730         } // if
    731         heapExpand = default_heap_expansion();
     751        if ( ! setMmapStart( malloc_mmap_start() ) ) {
     752                abort( "Heap : internal error, mmap start initialization failure." );
     753        } // if
     754        heapExpand = malloc_expansion();
    732755
    733756        char * end = (char *)sbrk( 0 );
    734757        heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment
    735 } // HeapManager
    736 
    737 
    738 static void ^?{}( HeapManager & ) {
     758} // Heap
     759
     760
     761static void ^?{}( Heap & ) {
    739762        #ifdef __STATISTICS__
    740763        if ( traceHeapTerm() ) {
     
    743766        } // if
    744767        #endif // __STATISTICS__
    745 } // ~HeapManager
     768} // ~Heap
    746769
    747770
     
    796819        // subtract libAlign() because it is already the minimum alignment
    797820        // add sizeof(Storage) for fake header
    798         char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     821        char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(Heap.Storage) );
    799822
    800823        // address in the block of the "next" alignment address
    801         char * user = (char *)ceiling2( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );
     824        char * user = (char *)ceiling2( (uintptr_t)(addr + sizeof(Heap.Storage)), alignment );
    802825
    803826        // address of header from malloc
    804         HeapManager.Storage.Header * realHeader = headerAddr( addr );
     827        Heap.Storage.Header * realHeader = headerAddr( addr );
    805828        realHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
    806829        // address of fake header * before* the alignment location
    807         HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     830        Heap.Storage.Header * fakeHeader = headerAddr( user );
    808831        // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
    809832        fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
     
    821844                #ifdef __STATISTICS__
    822845                if ( likely( size > 0 ) ) {
    823                         __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST );
    824                         __atomic_add_fetch( &malloc_storage_request, size, __ATOMIC_SEQ_CST );
     846                        __atomic_add_fetch( &stats.malloc_calls, 1, __ATOMIC_SEQ_CST );
     847                        __atomic_add_fetch( &stats.malloc_storage_request, size, __ATOMIC_SEQ_CST );
    825848                } else {
    826                         __atomic_add_fetch( &malloc_0_calls, 1, __ATOMIC_SEQ_CST );
     849                        __atomic_add_fetch( &stats.malloc_0_calls, 1, __ATOMIC_SEQ_CST );
    827850                } // if
    828851                #endif // __STATISTICS__
     
    837860                #ifdef __STATISTICS__
    838861                if ( likely( size > 0 ) ) {
    839                         __atomic_add_fetch( &aalloc_calls, 1, __ATOMIC_SEQ_CST );
    840                         __atomic_add_fetch( &aalloc_storage_request, size, __ATOMIC_SEQ_CST );
     862                        __atomic_add_fetch( &stats.aalloc_calls, 1, __ATOMIC_SEQ_CST );
     863                        __atomic_add_fetch( &stats.aalloc_storage_request, size, __ATOMIC_SEQ_CST );
    841864                } else {
    842                         __atomic_add_fetch( &aalloc_0_calls, 1, __ATOMIC_SEQ_CST );
     865                        __atomic_add_fetch( &stats.aalloc_0_calls, 1, __ATOMIC_SEQ_CST );
    843866                } // if
    844867                #endif // __STATISTICS__
     
    853876          if ( unlikely( size ) == 0 ) {                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
    854877                        #ifdef __STATISTICS__
    855                         __atomic_add_fetch( &calloc_0_calls, 1, __ATOMIC_SEQ_CST );
     878                        __atomic_add_fetch( &stats.calloc_0_calls, 1, __ATOMIC_SEQ_CST );
    856879                        #endif // __STATISTICS__
    857880                        return 0p;
    858881                } // if
    859882                #ifdef __STATISTICS__
    860                 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    861                 __atomic_add_fetch( &calloc_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
     883                __atomic_add_fetch( &stats.calloc_calls, 1, __ATOMIC_SEQ_CST );
     884                __atomic_add_fetch( &stats.calloc_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
    862885                #endif // __STATISTICS__
    863886
    864887                char * addr = (char *)mallocNoStats( size );
    865888
    866                 HeapManager.Storage.Header * header;
    867                 HeapManager.FreeHeader * freeElem;
     889                Heap.Storage.Header * header;
     890                Heap.FreeHeader * freeElem;
    868891                size_t bsize, alignment;
    869892
     
    894917          if ( unlikely( size == 0 ) ) {                                        // special cases
    895918                        #ifdef __STATISTICS__
    896                         __atomic_add_fetch( &resize_0_calls, 1, __ATOMIC_SEQ_CST );
     919                        __atomic_add_fetch( &stats.resize_0_calls, 1, __ATOMIC_SEQ_CST );
    897920                        #endif // __STATISTICS__
    898921                        free( oaddr );
     
    900923                } // if
    901924                #ifdef __STATISTICS__
    902                 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST );
     925                __atomic_add_fetch( &stats.resize_calls, 1, __ATOMIC_SEQ_CST );
    903926                #endif // __STATISTICS__
    904927
    905928          if ( unlikely( oaddr == 0p ) ) {
    906929                        #ifdef __STATISTICS__
    907                         __atomic_add_fetch( &resize_storage_request, size, __ATOMIC_SEQ_CST );
     930                        __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
    908931                        #endif // __STATISTICS__
    909932                        return mallocNoStats( size );
    910933                } // if
    911934
    912                 HeapManager.Storage.Header * header;
    913                 HeapManager.FreeHeader * freeElem;
     935                Heap.Storage.Header * header;
     936                Heap.FreeHeader * freeElem;
    914937                size_t bsize, oalign;
    915938                headers( "resize", oaddr, header, freeElem, bsize, oalign );
     
    924947
    925948                #ifdef __STATISTICS__
    926                 __atomic_add_fetch( &resize_storage_request, size, __ATOMIC_SEQ_CST );
     949                __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
    927950                #endif // __STATISTICS__
    928951
     
    939962          if ( unlikely( size == 0 ) ) {                                        // special cases
    940963                        #ifdef __STATISTICS__
    941                         __atomic_add_fetch( &realloc_0_calls, 1, __ATOMIC_SEQ_CST );
     964                        __atomic_add_fetch( &stats.realloc_0_calls, 1, __ATOMIC_SEQ_CST );
    942965                        #endif // __STATISTICS__
    943966                        free( oaddr );
     
    945968                } // if
    946969                #ifdef __STATISTICS__
    947                 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     970                __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
    948971                #endif // __STATISTICS__
    949972
    950973          if ( unlikely( oaddr == 0p ) ) {
    951974                        #ifdef __STATISTICS__
    952                         __atomic_add_fetch( &realloc_storage_request, size, __ATOMIC_SEQ_CST );
     975                        __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
    953976                        #endif // __STATISTICS__
    954977                        return mallocNoStats( size );
    955978                } // if
    956979
    957                 HeapManager.Storage.Header * header;
    958                 HeapManager.FreeHeader * freeElem;
     980                Heap.Storage.Header * header;
     981                Heap.FreeHeader * freeElem;
    959982                size_t bsize, oalign;
    960983                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     
    972995
    973996                #ifdef __STATISTICS__
    974                 __atomic_add_fetch( &realloc_storage_request, size, __ATOMIC_SEQ_CST );
     997                __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
    975998                #endif // __STATISTICS__
    976999
     
    10021025                #ifdef __STATISTICS__
    10031026                if ( likely( size > 0 ) ) {
    1004                         __atomic_add_fetch( &memalign_calls, 1, __ATOMIC_SEQ_CST );
    1005                         __atomic_add_fetch( &memalign_storage_request, size, __ATOMIC_SEQ_CST );
     1027                        __atomic_add_fetch( &stats.memalign_calls, 1, __ATOMIC_SEQ_CST );
     1028                        __atomic_add_fetch( &stats.memalign_storage_request, size, __ATOMIC_SEQ_CST );
    10061029                } else {
    1007                         __atomic_add_fetch( &memalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1030                        __atomic_add_fetch( &stats.memalign_0_calls, 1, __ATOMIC_SEQ_CST );
    10081031                } // if
    10091032                #endif // __STATISTICS__
     
    10181041                #ifdef __STATISTICS__
    10191042                if ( likely( size > 0 ) ) {
    1020                         __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    1021                         __atomic_add_fetch( &cmemalign_storage_request, size, __ATOMIC_SEQ_CST );
     1043                        __atomic_add_fetch( &stats.cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     1044                        __atomic_add_fetch( &stats.cmemalign_storage_request, size, __ATOMIC_SEQ_CST );
    10221045                } else {
    1023                         __atomic_add_fetch( &cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1046                        __atomic_add_fetch( &stats.cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
    10241047                } // if
    10251048                #endif // __STATISTICS__
     
    10341057          if ( unlikely( size ) == 0 ) {                                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
    10351058                        #ifdef __STATISTICS__
    1036                         __atomic_add_fetch( &cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1059                        __atomic_add_fetch( &stats.cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
    10371060                        #endif // __STATISTICS__
    10381061                        return 0p;
    10391062                } // if
    10401063                #ifdef __STATISTICS__
    1041                 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    1042                 __atomic_add_fetch( &cmemalign_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
     1064                __atomic_add_fetch( &stats.cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     1065                __atomic_add_fetch( &stats.cmemalign_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
    10431066                #endif // __STATISTICS__
    10441067
    10451068                char * addr = (char *)memalignNoStats( alignment, size );
    10461069
    1047                 HeapManager.Storage.Header * header;
    1048                 HeapManager.FreeHeader * freeElem;
     1070                Heap.Storage.Header * header;
     1071                Heap.FreeHeader * freeElem;
    10491072                size_t bsize;
    10501073
     
    11041127          if ( unlikely( addr == 0p ) ) {                                       // special case
    11051128                        #ifdef __STATISTICS__
    1106                         __atomic_add_fetch( &free_null_calls, 1, __ATOMIC_SEQ_CST );
     1129                        __atomic_add_fetch( &stats.free_null_calls, 1, __ATOMIC_SEQ_CST );
    11071130                        #endif // __STATISTICS__
    11081131
     
    11241147        size_t malloc_alignment( void * addr ) {
    11251148          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    1126                 HeapManager.Storage.Header * header = headerAddr( addr );
     1149                Heap.Storage.Header * header = headerAddr( addr );
    11271150                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11281151                        return header->kind.fake.alignment & -2;        // remove flag from value
     
    11371160          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    11381161                size_t ret;
    1139                 HeapManager.Storage.Header * header = headerAddr( addr );
     1162                Heap.Storage.Header * header = headerAddr( addr );
    11401163                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11411164                        ret = header->kind.fake.alignment & -2;         // remove flag from old value
     
    11511174        bool malloc_zero_fill( void * addr ) {
    11521175          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    1153                 HeapManager.Storage.Header * header = headerAddr( addr );
     1176                Heap.Storage.Header * header = headerAddr( addr );
    11541177                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11551178                        header = realHeader( header );                          // backup from fake to real header
     
    11611184        bool malloc_zero_fill_set$( void * addr ) {
    11621185          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    1163                 HeapManager.Storage.Header * header = headerAddr( addr );
     1186                Heap.Storage.Header * header = headerAddr( addr );
    11641187                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11651188                        header = realHeader( header );                          // backup from fake to real header
     
    11741197        size_t malloc_size( void * addr ) {
    11751198          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    1176                 HeapManager.Storage.Header * header = headerAddr( addr );
     1199                Heap.Storage.Header * header = headerAddr( addr );
    11771200                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11781201                        header = realHeader( header );                          // backup from fake to real header
     
    11841207        size_t malloc_size_set$( void * addr, size_t size ) {
    11851208          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    1186                 HeapManager.Storage.Header * header = headerAddr( addr );
     1209                Heap.Storage.Header * header = headerAddr( addr );
    11871210                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11881211                        header = realHeader( header );                          // backup from fake to real header
     
    11981221        size_t malloc_usable_size( void * addr ) {
    11991222          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    1200                 HeapManager.Storage.Header * header;
    1201                 HeapManager.FreeHeader * freeElem;
     1223                Heap.Storage.Header * header;
     1224                Heap.FreeHeader * freeElem;
    12021225                size_t bsize, alignment;
    12031226
     
    12751298                return 0;                                                                               // unsupported
    12761299        } // malloc_set_state
     1300
     1301        // Sets the amount (bytes) to extend the heap when there is insufficent free storage to service an allocation.
     1302        __attribute__((weak)) size_t malloc_expansion() { return __CFA_DEFAULT_HEAP_EXPANSION__; }
     1303
     1304        // Sets the crossover point between allocations occuring in the sbrk area or separately mmapped.
     1305        __attribute__((weak)) size_t malloc_mmap_start() { return __CFA_DEFAULT_MMAP_START__; }
     1306
     1307        // Amount subtracted to adjust for unfreed program storage (debug only).
     1308        __attribute__((weak)) size_t malloc_unfreed() { return __CFA_DEFAULT_HEAP_UNFREED__; }
    12771309} // extern "C"
    12781310
     
    12831315  if ( unlikely( size == 0 ) ) {                                                // special cases
    12841316                #ifdef __STATISTICS__
    1285                 __atomic_add_fetch( &resize_0_calls, 1, __ATOMIC_SEQ_CST );
     1317                __atomic_add_fetch( &stats.resize_0_calls, 1, __ATOMIC_SEQ_CST );
    12861318                #endif // __STATISTICS__
    12871319                free( oaddr );
     
    12961328  if ( unlikely( oaddr == 0p ) ) {
    12971329                #ifdef __STATISTICS__
    1298                 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST );
    1299                 __atomic_add_fetch( &resize_storage_request, size, __ATOMIC_SEQ_CST );
     1330                __atomic_add_fetch( &stats.resize_calls, 1, __ATOMIC_SEQ_CST );
     1331                __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
    13001332                #endif // __STATISTICS__
    13011333                return memalignNoStats( nalign, size );
     
    13031335
    13041336        // Attempt to reuse existing alignment.
    1305         HeapManager.Storage.Header * header = headerAddr( oaddr );
     1337        Heap.Storage.Header * header = headerAddr( oaddr );
    13061338        bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
    13071339        size_t oalign;
     
    13131345                        ) {
    13141346                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1315                         HeapManager.FreeHeader * freeElem;
     1347                        Heap.FreeHeader * freeElem;
    13161348                        size_t bsize, oalign;
    13171349                        headers( "resize", oaddr, header, freeElem, bsize, oalign );
     
    13321364
    13331365        #ifdef __STATISTICS__
    1334         __atomic_add_fetch( &resize_storage_request, size, __ATOMIC_SEQ_CST );
     1366        __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
    13351367        #endif // __STATISTICS__
    13361368
     
    13451377  if ( unlikely( size == 0 ) ) {                                                // special cases
    13461378                #ifdef __STATISTICS__
    1347                 __atomic_add_fetch( &realloc_0_calls, 1, __ATOMIC_SEQ_CST );
     1379                __atomic_add_fetch( &stats.realloc_0_calls, 1, __ATOMIC_SEQ_CST );
    13481380                #endif // __STATISTICS__
    13491381                free( oaddr );
     
    13581390  if ( unlikely( oaddr == 0p ) ) {
    13591391                #ifdef __STATISTICS__
    1360                 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    1361                 __atomic_add_fetch( &realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1392                __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
     1393                __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
    13621394                #endif // __STATISTICS__
    13631395                return memalignNoStats( nalign, size );
     
    13651397
    13661398        // Attempt to reuse existing alignment.
    1367         HeapManager.Storage.Header * header = headerAddr( oaddr );
     1399        Heap.Storage.Header * header = headerAddr( oaddr );
    13681400        bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
    13691401        size_t oalign;
     
    13821414
    13831415        #ifdef __STATISTICS__
    1384         __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    1385         __atomic_add_fetch( &realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1416        __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
     1417        __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
    13861418        #endif // __STATISTICS__
    13871419
    1388         HeapManager.FreeHeader * freeElem;
     1420        Heap.FreeHeader * freeElem;
    13891421        size_t bsize;
    13901422        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
  • libcfa/src/heap.hfa

    r16cc9f7 r31a5f418  
    1010// Created On       : Tue May 26 11:23:55 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  8 17:36:48 2020
    13 // Update Count     : 16
     12// Last Modified On : Thu Apr 21 22:52:25 2022
     13// Update Count     : 21
    1414//
    1515
    1616#pragma once
    1717
    18 size_t default_mmap_start();                                                    // CFA extras
    19 size_t default_heap_expansion();
     18#include <malloc.h>
    2019
    2120bool traceHeap();
     
    3433#ifndef M_MMAP_THRESHOLD
    3534#define M_MMAP_THRESHOLD (-1)
    36 #endif // M_TOP_PAD
     35#endif // M_MMAP_THRESHOLD
     36
    3737#ifndef M_TOP_PAD
    3838#define M_TOP_PAD (-2)
     
    4040
    4141extern "C" {
    42         void * aalloc( size_t dim, size_t elemSize );
    43         void * resize( void * oaddr, size_t size );
    44         void * amemalign( size_t align, size_t dim, size_t elemSize );
    45         void * cmemalign( size_t align, size_t dim, size_t elemSize );
     42        // New allocation operations.
     43        void * aalloc( size_t dim, size_t elemSize ) __attribute__ ((malloc));
     44        void * resize( void * oaddr, size_t size ) __attribute__ ((malloc));
     45        void * amemalign( size_t align, size_t dim, size_t elemSize ) __attribute__ ((malloc));
     46        void * cmemalign( size_t align, size_t dim, size_t elemSize ) __attribute__ ((malloc));
    4647        size_t malloc_alignment( void * addr );
    4748        bool malloc_zero_fill( void * addr );
    4849        size_t malloc_size( void * addr );
     50        int malloc_stats_fd( int fd );
    4951        size_t malloc_usable_size( void * addr );
    50         int malloc_stats_fd( int fd );
     52        size_t malloc_expansion();                                                      // heap expansion size (bytes)
     53        size_t malloc_mmap_start();                                                     // crossover allocation size from sbrk to mmap
     54        size_t malloc_unfreed();                                                        // heap unfreed size (bytes)
    5155} // extern "C"
    5256
    53 void * resize( void * oaddr, size_t nalign, size_t size );
    54 void * realloc( void * oaddr, size_t nalign, size_t size );
     57void * resize( void * oaddr, size_t alignment, size_t size );
     58void * realloc( void * oaddr, size_t alignment, size_t size );
     59void * reallocarray( void * oaddr, size_t nalign, size_t dim, size_t elemSize );
    5560
    5661// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.