Changes in / [4f102fa:a55472cc]


Ignore:
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/locks.hfa

    r4f102fa ra55472cc  
    1313// Created On       : Tue Oct 31 15:14:38 2017
    1414// Last Modified By : Peter A. Buhr
    15 // Last Modified On : Tue Sep 20 22:09:50 2022
    16 // Update Count     : 18
     15// Last Modified On : Mon Sep 19 18:51:53 2022
     16// Update Count     : 17
    1717//
    1818
     
    6464                        #ifndef NOEXPBACK
    6565                                // exponential spin
    66                                 for ( volatile unsigned int s; 0 ~ spin ) Pause();
     66                        for ( volatile unsigned int s; 0 ~ spin ) Pause();
    6767
    6868                                // slowly increase by powers of 2
  • libcfa/src/concurrency/kernel/startup.cfa

    r4f102fa ra55472cc  
    184184
    185185
    186 extern void heapManagerCtor();
    187 extern void heapManagerDtor();
    188 
    189186//=============================================================================================
    190187// Kernel Setup logic
     
    368365        proc->local_data = &__cfaabi_tls;
    369366
    370         heapManagerCtor();                                                                      // initialize heap
    371 
    372367        __cfa_io_start( proc );
    373368        register_tls( proc );
     
    421416        unregister_tls( proc );
    422417        __cfa_io_stop( proc );
    423 
    424         heapManagerDtor();                                                                      // de-initialize heap
    425418
    426419        return 0p;
  • libcfa/src/heap.cfa

    r4f102fa ra55472cc  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 11 15:08:33 2022
    13 // Update Count     : 1525
     12// Last Modified On : Fri Apr 29 19:05:03 2022
     13// Update Count     : 1167
    1414//
    1515
    16 #include <stdio.h>
    1716#include <string.h>                                                                             // memset, memcpy
    1817#include <limits.h>                                                                             // ULONG_MAX
     
    2221#include <malloc.h>                                                                             // memalign, malloc_usable_size
    2322#include <sys/mman.h>                                                                   // mmap, munmap
    24 extern "C" {
    2523#include <sys/sysinfo.h>                                                                // get_nprocs
    26 } // extern "C"
    2724
    2825#include "bits/align.hfa"                                                               // libAlign
    2926#include "bits/defs.hfa"                                                                // likely, unlikely
    3027#include "bits/locks.hfa"                                                               // __spinlock_t
    31 #include "concurrency/kernel/fwd.hfa"                                   // __POLL_PREEMPTION
    3228#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    33 #include "math.hfa"                                                                             // ceiling, min
     29#include "math.hfa"                                                                             // min
    3430#include "bitmanip.hfa"                                                                 // is_pow2, ceiling2
    3531
    36 // supported mallopt options
    37 #ifndef M_MMAP_THRESHOLD
    38 #define M_MMAP_THRESHOLD (-1)
    39 #endif // M_MMAP_THRESHOLD
    40 
    41 #ifndef M_TOP_PAD
    42 #define M_TOP_PAD (-2)
    43 #endif // M_TOP_PAD
    44 
    45 #define FASTLOOKUP                                                                              // use O(1) table lookup from allocation size to bucket size
    46 #define RETURNSPIN                                                                              // toggle spinlock / lockfree stack
    47 #define OWNERSHIP                                                                               // return freed memory to owner thread
    48 
    49 #define CACHE_ALIGN 64
    50 #define CALIGN __attribute__(( aligned(CACHE_ALIGN) ))
    51 
    52 #define TLSMODEL __attribute__(( tls_model("initial-exec") ))
    53 
    54 //#define __STATISTICS__
    55 
    56 enum {
    57         // The default extension heap amount in units of bytes. When the current heap reaches the brk address, the brk
    58         // address is extended by the extension amount.
    59         __CFA_DEFAULT_HEAP_EXPANSION__ = 10 * 1024 * 1024,
    60 
    61         // The mmap crossover point during allocation. Allocations less than this amount are allocated from buckets; values
    62         // greater than or equal to this value are mmap from the operating system.
    63         __CFA_DEFAULT_MMAP_START__ = 512 * 1024 + 1,
    64 
    65         // The default unfreed storage amount in units of bytes. When the uC++ program ends it subtracts this amount from
    66         // the malloc/free counter to adjust for storage the program does not free.
    67         __CFA_DEFAULT_HEAP_UNFREED__ = 0
    68 }; // enum
    69 
    70 
    71 //####################### Heap Trace/Print ####################
     32#define FASTLOOKUP
     33#define __STATISTICS__
    7234
    7335
     
    9355static bool prtFree = false;
    9456
    95 bool prtFree() {
     57static bool prtFree() {
    9658        return prtFree;
    9759} // prtFree
    9860
    99 bool prtFreeOn() {
     61static bool prtFreeOn() {
    10062        bool temp = prtFree;
    10163        prtFree = true;
     
    10365} // prtFreeOn
    10466
    105 bool prtFreeOff() {
     67static bool prtFreeOff() {
    10668        bool temp = prtFree;
    10769        prtFree = false;
     
    11072
    11173
    112 //######################### Spin Lock #########################
    113 
    114 
    115 // pause to prevent excess processor bus usage
    116 #if defined( __i386 ) || defined( __x86_64 )
    117         #define Pause() __asm__ __volatile__ ( "pause" : : : )
    118 #elif defined(__ARM_ARCH)
    119         #define Pause() __asm__ __volatile__ ( "YIELD" : : : )
    120 #else
    121         #error unsupported architecture
    122 #endif
    123 
    124 typedef volatile uintptr_t SpinLock_t CALIGN;                   // aligned addressable word-size
    125 
    126 static inline __attribute__((always_inline)) void lock( volatile SpinLock_t & slock ) {
    127         enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
    128         unsigned int spin = SPIN_START;
    129 
    130         for ( unsigned int i = 1;; i += 1 ) {
    131           if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_SEQ_CST ) == 0 ) break; // Fence
    132                 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause(); // exponential spin
    133                 spin += spin;                                                                   // powers of 2
    134                 //if ( i % 64 == 0 ) spin += spin;                              // slowly increase by powers of 2
    135                 if ( spin > SPIN_END ) spin = SPIN_END;                 // cap spinning
    136         } // for
    137 } // spin_lock
    138 
    139 static inline __attribute__((always_inline)) void unlock( volatile SpinLock_t & slock ) {
    140         __atomic_clear( &slock, __ATOMIC_SEQ_CST );                     // Fence
    141 } // spin_unlock
     74enum {
     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
    14287
    14388
     
    175120                unsigned int free_calls, free_null_calls;
    176121                unsigned long long int free_storage_request, free_storage_alloc;
    177                 unsigned int return_pulls, return_pushes;
    178                 unsigned long long int return_storage_request, return_storage_alloc;
     122                unsigned int away_pulls, away_pushes;
     123                unsigned long long int away_storage_request, away_storage_alloc;
    179124                unsigned int mmap_calls, mmap_0_calls;                  // no zero calls
    180125                unsigned long long int mmap_storage_request, mmap_storage_alloc;
     
    186131
    187132static_assert( sizeof(HeapStatistics) == CntTriples * sizeof(StatsOverlay),
    188                            "Heap statistics counter-triplets does not match with array size" );
     133                           "Heap statistics counter-triplets does not match with array size" );
    189134
    190135static void HeapStatisticsCtor( HeapStatistics & stats ) {
     
    258203        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    259204
    260         struct __attribute__(( aligned (8) )) FreeHeader {
    261                 size_t blockSize __attribute__(( aligned(8) )); // size of allocations on this list
     205        struct FreeHeader {
     206                size_t blockSize __attribute__(( aligned (8) )); // size of allocations on this list
    262207                #if BUCKETLOCK == SPINLOCK
    263                 #ifdef OWNERSHIP
    264                 #ifdef RETURNSPIN
    265                 SpinLock_t returnLock;
    266                 #endif // RETURNSPIN
    267                 Storage * returnList;                                                   // other thread return list
    268                 #endif // OWNERSHIP
    269                 Storage * freeList;                                                             // thread free list
     208                __spinlock_t lock;
     209                Storage * freeList;
    270210                #else
    271211                StackLF(Storage) freeList;
    272212                #endif // BUCKETLOCK
    273                 Heap * homeManager;                                                             // heap owner (free storage to bucket, from bucket to heap)
    274         }; // FreeHeader
     213        } __attribute__(( aligned (8) )); // FreeHeader
    275214
    276215        FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
    277         void * heapBuffer;                                                                      // start of free storage in buffer
    278         size_t heapReserve;                                                                     // amount of remaining free storage in buffer
    279 
    280         #if defined( __STATISTICS__ ) || defined( __CFA_DEBUG__ )
    281         Heap * nextHeapManager;                                                         // intrusive link of existing heaps; traversed to collect statistics or check unfreed storage
    282         #endif // __STATISTICS__ || __CFA_DEBUG__
    283         Heap * nextFreeHeapManager;                                                     // intrusive link of free heaps from terminated threads; reused by new threads
    284 
    285         #ifdef __CFA_DEBUG__
    286         int64_t allocUnfreed;                                                           // running total of allocations minus frees; can be negative
    287         #endif // __CFA_DEBUG__
    288 
    289         #ifdef __STATISTICS__
    290         HeapStatistics stats;                                                           // local statistic table for this heap
    291         #endif // __STATISTICS__
     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
    292221}; // Heap
    293222
    294223#if BUCKETLOCK == LOCKFREE
    295 inline __attribute__((always_inline))
    296 static {
     224static inline {
    297225        Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
    298226        void ?{}( Heap.FreeHeader & ) {}
     
    301229#endif // LOCKFREE
    302230
    303 
    304 struct HeapMaster {
    305         SpinLock_t extLock;                                                                     // protects allocation-buffer extension
    306         SpinLock_t mgrLock;                                                                     // protects freeHeapManagersList, heapManagersList, heapManagersStorage, heapManagersStorageEnd
    307 
    308         void * heapBegin;                                                                       // start of heap
    309         void * heapEnd;                                                                         // logical end of heap
    310         size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    311         size_t pageSize;                                                                        // architecture pagesize
    312         size_t heapExpand;                                                                      // sbrk advance
    313         size_t mmapStart;                                                                       // cross over point for mmap
    314         unsigned int maxBucketsUsed;                                            // maximum number of buckets in use
    315 
    316         Heap * heapManagersList;                                                        // heap-list head
    317         Heap * freeHeapManagersList;                                            // free-list head
    318 
    319         // Heap superblocks are not linked; heaps in superblocks are linked via intrusive links.
    320         Heap * heapManagersStorage;                                                     // next heap to use in heap superblock
    321         Heap * heapManagersStorageEnd;                                          // logical heap outside of superblock's end
    322 
    323         #ifdef __STATISTICS__
    324         HeapStatistics stats;                                                           // global stats for thread-local heaps to add there counters when exiting
    325         unsigned long int threads_started, threads_exited;      // counts threads that have started and exited
    326         unsigned long int reused_heap, new_heap;                        // counts reusability of heaps
    327         unsigned int sbrk_calls;
    328         unsigned long long int sbrk_storage;
    329         int stats_fd;
    330         #endif // __STATISTICS__
    331 }; // HeapMaster
     231static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
    332232
    333233
    334234#ifdef FASTLOOKUP
    335 enum { LookupSizes = 65_536 + sizeof(Heap.Storage) };   // number of fast lookup sizes
     235enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
    336236static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    337237#endif // FASTLOOKUP
    338238
    339 static volatile bool heapMasterBootFlag = false;                // trigger for first heap
    340 static HeapMaster heapMaster @= {};                                             // program global
    341 
    342 static void heapMasterCtor();
    343 static void heapMasterDtor();
    344 static Heap * getHeap();
     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__
    345243
    346244
     
    370268static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    371269
    372 
    373 // extern visibility, used by runtime kernel
    374 libcfa_public size_t __page_size;                                               // architecture pagesize
    375 libcfa_public int __map_prot;                                                   // common mmap/mprotect protection
    376 
    377 
    378 // Thread-local storage is allocated lazily when the storage is accessed.
    379 static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing
    380 static __thread Heap * volatile heapManager CALIGN TLSMODEL;
    381 static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing
    382 
    383 
    384 // declare helper functions for HeapMaster
    385 void noMemory();                                                                                // forward, called by "builtin_new" when malloc returns 0
    386 
    387 
    388 // generic Bsearchl does not inline, so substitute with hand-coded binary-search.
    389 inline __attribute__((always_inline))
    390 static size_t Bsearchl( unsigned int key, const unsigned int vals[], size_t dim ) {
    391         size_t l = 0, m, h = dim;
    392         while ( l < h ) {
    393                 m = (l + h) / 2;
    394                 if ( (unsigned int &)(vals[m]) < key ) {                // cast away const
    395                         l = m + 1;
    396                 } else {
    397                         h = m;
    398                 } // if
    399         } // while
    400         return l;
    401 } // Bsearchl
    402 
    403 
    404 void heapMasterCtor() with( heapMaster ) {
    405         // Singleton pattern to initialize heap master
    406 
    407         verify( bucketSizes[0] == (16 + sizeof(Heap.Storage)) );
    408 
    409         __page_size = sysconf( _SC_PAGESIZE );
    410         __map_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
    411 
    412         ?{}( extLock );
    413         ?{}( mgrLock );
    414 
    415         char * end = (char *)sbrk( 0 );
    416         heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
    417         heapRemaining = 0;
    418         heapExpand = malloc_expansion();
    419         mmapStart = malloc_mmap_start();
    420 
    421         // find the closest bucket size less than or equal to the mmapStart size
    422         maxBucketsUsed = Bsearchl( mmapStart, bucketSizes, NoBucketSizes ); // binary search
    423 
    424         verify( (mmapStart >= pageSize) && (bucketSizes[NoBucketSizes - 1] >= mmapStart) );
    425         verify( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    426         verify( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    427 
    428         heapManagersList = 0p;
    429         freeHeapManagersList = 0p;
    430 
    431         heapManagersStorage = 0p;
    432         heapManagersStorageEnd = 0p;
    433 
    434         #ifdef __STATISTICS__
    435         HeapStatisticsCtor( stats );                                            // clear statistic counters
    436         threads_started = threads_exited = 0;
    437         reused_heap = new_heap = 0;
    438         sbrk_calls = sbrk_storage = 0;
    439         stats_fd = STDERR_FILENO;
    440         #endif // __STATISTICS__
    441 
    442         #ifdef FASTLOOKUP
    443         for ( unsigned int i = 0, idx = 0; i < LookupSizes; i += 1 ) {
    444                 if ( i > bucketSizes[idx] ) idx += 1;
    445                 lookup[i] = idx;
    446                 verify( i <= bucketSizes[idx] );
    447                 verify( (i <= 32 && idx == 0) || (i > bucketSizes[idx - 1]) );
    448         } // for
    449         #endif // FASTLOOKUP
    450 
    451         heapMasterBootFlag = true;
    452 } // heapMasterCtor
    453 
    454 
    455 #define NO_MEMORY_MSG "insufficient heap memory available to allocate %zd new bytes."
    456 
    457 Heap * getHeap() with( heapMaster ) {
    458         Heap * heap;
    459         if ( freeHeapManagersList ) {                                           // free heap for reused ?
    460                 heap = freeHeapManagersList;
    461                 freeHeapManagersList = heap->nextFreeHeapManager;
    462 
    463                 #ifdef __STATISTICS__
    464                 reused_heap += 1;
    465                 #endif // __STATISTICS__
    466         } else {                                                                                        // free heap not found, create new
    467                 // Heap size is about 12K, FreeHeader (128 bytes because of cache alignment) * NoBucketSizes (91) => 128 heaps *
    468                 // 12K ~= 120K byte superblock.  Where 128-heap superblock handles a medium sized multi-processor server.
    469                 size_t remaining = heapManagersStorageEnd - heapManagersStorage; // remaining free heaps in superblock
    470                 if ( ! heapManagersStorage || remaining != 0 ) {
    471                         // Each block of heaps is a multiple of the number of cores on the computer.
    472                         int HeapDim = get_nprocs();                                     // get_nprocs_conf does not work
    473                         size_t size = HeapDim * sizeof( Heap );
    474 
    475                         heapManagersStorage = (Heap *)mmap( 0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
    476                         if ( unlikely( heapManagersStorage == (Heap *)MAP_FAILED ) ) { // failed ?
    477                                 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, size ); // no memory
    478                                 // Do not call strerror( errno ) as it may call malloc.
    479                                 abort( "attempt to allocate block of heaps of size %zu bytes and mmap failed with errno %d.", size, errno );
    480                         } // if
    481                         heapManagersStorageEnd = &heapManagersStorage[HeapDim]; // outside array
    482                 } // if
    483 
    484                 heap = heapManagersStorage;
    485                 heapManagersStorage = heapManagersStorage + 1; // bump next heap
    486 
    487                 #if defined( __STATISTICS__ ) || defined( __CFA_DEBUG__ )
    488                 heap->nextHeapManager = heapManagersList;
    489                 #endif // __STATISTICS__ || __CFA_DEBUG__
    490                 heapManagersList = heap;
    491 
    492                 #ifdef __STATISTICS__
    493                 new_heap += 1;
    494                 #endif // __STATISTICS__
    495 
    496                 with( *heap ) {
    497                         for ( unsigned int j = 0; j < NoBucketSizes; j += 1 ) { // initialize free lists
    498                                 #ifdef OWNERSHIP
    499                                 #ifdef RETURNSPIN
    500                                 ?{}( freeLists[j].returnLock );
    501                                 #endif // RETURNSPIN
    502                                 freeLists[j].returnList = 0p;
    503                                 #endif // OWNERSHIP
    504                                 freeLists[j].freeList = 0p;
    505                                 freeLists[j].homeManager = heap;
    506                                 freeLists[j].blockSize = bucketSizes[j];
    507                         } // for
    508        
    509                         heapBuffer = 0p;
    510                         heapReserve = 0;
    511                         nextFreeHeapManager = 0p;
    512                         #ifdef __CFA_DEBUG__
    513                         allocUnfreed = 0;
    514                         #endif // __CFA_DEBUG__
    515                 } // with
    516         } // if
    517         return heap;
    518 } // getHeap
    519 
    520 
    521 void heapManagerCtor() libcfa_public {
    522         if ( unlikely( ! heapMasterBootFlag ) ) heapMasterCtor();
    523 
    524         lock( heapMaster.mgrLock );             // protect heapMaster counters
    525 
    526         // get storage for heap manager
    527 
    528         heapManager = getHeap();
    529 
    530         #ifdef __STATISTICS__
    531         HeapStatisticsCtor( heapManager->stats );                       // heap local
    532         heapMaster.threads_started += 1;
    533         #endif // __STATISTICS__
    534 
    535         unlock( heapMaster.mgrLock );
    536 } // heapManagerCtor
    537 
    538 
    539 void heapManagerDtor() libcfa_public {
    540         lock( heapMaster.mgrLock );
    541 
    542         // place heap on list of free heaps for reusability
    543         heapManager->nextFreeHeapManager = heapMaster.freeHeapManagersList;
    544         heapMaster.freeHeapManagersList = heapManager;
    545 
    546         #ifdef __STATISTICS__
    547         heapMaster.threads_exited += 1;
    548         #endif // __STATISTICS__
    549 
    550         // Do not set heapManager to NULL because it is used after Cforall is shutdown but before the program shuts down.
    551 
    552         unlock( heapMaster.mgrLock );
    553 } // heapManagerDtor
     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
    554272
    555273
    556274//####################### Memory Allocation Routines Helpers ####################
    557275
     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
    558290
    559291extern int cfa_main_returned;                                                   // from interpose.cfa
    560292extern "C" {
    561         void memory_startup( void ) {
    562                 if ( ! heapMasterBootFlag ) heapManagerCtor();  // sanity check
    563         } // memory_startup
    564 
    565         void memory_shutdown( void ) {
    566                 heapManagerDtor();
    567         } // memory_shutdown
    568 
    569293        void heapAppStart() {                                                           // called by __cfaabi_appready_startup
    570                 verify( heapManager );
    571                 #ifdef __CFA_DEBUG__
    572                 heapManager->allocUnfreed = 0;                                  // clear prior allocation counts
    573                 #endif // __CFA_DEBUG__
    574 
    575                 #ifdef __STATISTICS__
    576                 HeapStatisticsCtor( heapManager->stats );               // clear prior statistic counters
    577                 #endif // __STATISTICS__
     294                allocUnfreed = 0;
    578295        } // heapAppStart
    579296
    580297        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    581                 fclose( stdin ); fclose( stdout );                              // free buffer storage
    582           if ( ! cfa_main_returned ) return;                            // do not check unfreed storage if exit called
    583 
    584                 #ifdef __CFA_DEBUG__
    585                 // allocUnfreed is set to 0 when a heap is created and it accumulates any unfreed storage during its multiple thread
    586                 // usages.  At the end, add up each heap allocUnfreed value across all heaps to get the total unfreed storage.
    587                 long long int allocUnfreed = 0;
    588                 for ( Heap * heap = heapMaster.heapManagersList; heap; heap = heap->nextHeapManager ) {
    589                         allocUnfreed += heap->allocUnfreed;
    590                 } // for
    591 
    592                 allocUnfreed -= malloc_unfreed();                               // subtract any user specified unfreed storage
    593                 if ( allocUnfreed > 0 ) {
    594                         // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    595                         char helpText[512];
    596                         __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    597                                                                                 "CFA warning (UNIX pid:%ld) : program terminating with %llu(0x%llx) bytes of storage allocated but not freed.\n"
    598                                                                                 "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    599                                                                                 (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
    600                 } // if
    601                 #endif // __CFA_DEBUG__
     298                fclose( stdin ); fclose( stdout );
     299                if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
    602300        } // heapAppStop
    603301} // extern "C"
     302#endif // __CFA_DEBUG__
    604303
    605304
    606305#ifdef __STATISTICS__
    607306static HeapStatistics stats;                                                    // zero filled
     307static unsigned int sbrk_calls;
     308static unsigned long long int sbrk_storage;
     309// Statistics file descriptor (changed by malloc_stats_fd).
     310static int stats_fd = STDERR_FILENO;                                    // default stderr
    608311
    609312#define prtFmt \
     
    618321        "  realloc   >0 calls %'u; 0 calls %'u; storage %'llu / %'llu bytes\n" \
    619322        "  free      !null calls %'u; null calls %'u; storage %'llu / %'llu bytes\n" \
    620         "  return    pulls %'u; pushes %'u; storage %'llu / %'llu bytes\n" \
    621         "  sbrk      calls %'u; storage %'llu bytes\n" \
    622         "  mmap      calls %'u; storage %'llu / %'llu bytes\n" \
    623         "  munmap    calls %'u; storage %'llu / %'llu bytes\n" \
    624         "  threads   started %'lu; exited %'lu\n" \
    625         "  heaps     new %'lu; reused %'lu\n"
     323        "  sbrk      calls %'u; storage %'llu bytes\n"                                          \
     324        "  mmap      calls %'u; storage %'llu / %'llu bytes\n"                          \
     325        "  munmap    calls %'u; storage %'llu / %'llu bytes\n"                          \
    626326
    627327// Use "write" because streams may be shutdown when calls are made.
    628 static int printStats( HeapStatistics & stats ) with( heapMaster, stats ) {     // see malloc_stats
     328static int printStats() {                                                               // see malloc_stats
    629329        char helpText[sizeof(prtFmt) + 1024];                           // space for message and values
    630         return __cfaabi_bits_print_buffer( stats_fd, helpText, sizeof(helpText), prtFmt,
    631                         malloc_calls, malloc_0_calls, malloc_storage_request, malloc_storage_alloc,
    632                         aalloc_calls, aalloc_0_calls, aalloc_storage_request, aalloc_storage_alloc,
    633                         calloc_calls, calloc_0_calls, calloc_storage_request, calloc_storage_alloc,
    634                         memalign_calls, memalign_0_calls, memalign_storage_request, memalign_storage_alloc,
    635                         amemalign_calls, amemalign_0_calls, amemalign_storage_request, amemalign_storage_alloc,
    636                         cmemalign_calls, cmemalign_0_calls, cmemalign_storage_request, cmemalign_storage_alloc,
    637                         resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc,
    638                         realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc,
    639                         free_calls, free_null_calls, free_storage_request, free_storage_alloc,
    640                         return_pulls, return_pushes, return_storage_request, return_storage_alloc,
     330        return __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), prtFmt,
     331                        stats.malloc_calls, stats.malloc_0_calls, stats.malloc_storage_request, stats.malloc_storage_alloc,
     332                        stats.aalloc_calls, stats.aalloc_0_calls, stats.aalloc_storage_request, stats.aalloc_storage_alloc,
     333                        stats.calloc_calls, stats.calloc_0_calls, stats.calloc_storage_request, stats.calloc_storage_alloc,
     334                        stats.memalign_calls, stats.memalign_0_calls, stats.memalign_storage_request, stats.memalign_storage_alloc,
     335                        stats.amemalign_calls, stats.amemalign_0_calls, stats.amemalign_storage_request, stats.amemalign_storage_alloc,
     336                        stats.cmemalign_calls, stats.cmemalign_0_calls, stats.cmemalign_storage_request, stats.cmemalign_storage_alloc,
     337                        stats.resize_calls, stats.resize_0_calls, stats.resize_storage_request, stats.resize_storage_alloc,
     338                        stats.realloc_calls, stats.realloc_0_calls, stats.realloc_storage_request, stats.realloc_storage_alloc,
     339                        stats.free_calls, stats.free_null_calls, stats.free_storage_request, stats.free_storage_alloc,
    641340                        sbrk_calls, sbrk_storage,
    642                         mmap_calls, mmap_storage_request, mmap_storage_alloc,
    643                         munmap_calls, munmap_storage_request, munmap_storage_alloc,
    644                         threads_started, threads_exited,
    645                         new_heap, reused_heap
     341                        stats.mmap_calls, stats.mmap_storage_request, stats.mmap_storage_alloc,
     342                        stats.munmap_calls, stats.munmap_storage_request, stats.munmap_storage_alloc
    646343                );
    647344} // printStats
     
    661358        "<total type=\"realloc\" >0 count=\"%'u;\" 0 count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
    662359        "<total type=\"free\" !null=\"%'u;\" 0 null=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
    663         "<total type=\"return\" pulls=\"%'u;\" 0 pushes=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
    664360        "<total type=\"sbrk\" count=\"%'u;\" size=\"%'llu\"/> bytes\n" \
    665361        "<total type=\"mmap\" count=\"%'u;\" size=\"%'llu / %'llu\" / > bytes\n" \
    666362        "<total type=\"munmap\" count=\"%'u;\" size=\"%'llu / %'llu\"/> bytes\n" \
    667         "<total type=\"threads\" started=\"%'lu;\" exited=\"%'lu\"/>\n" \
    668         "<total type=\"heaps\" new=\"%'lu;\" reused=\"%'lu\"/>\n" \
    669363        "</malloc>"
    670364
    671 static int printStatsXML( HeapStatistics & stats, FILE * stream ) with( heapMaster, stats ) { // see malloc_info
     365static int printStatsXML( FILE * stream ) {                             // see malloc_info
    672366        char helpText[sizeof(prtFmtXML) + 1024];                        // space for message and values
    673367        return __cfaabi_bits_print_buffer( fileno( stream ), helpText, sizeof(helpText), prtFmtXML,
    674                         malloc_calls, malloc_0_calls, malloc_storage_request, malloc_storage_alloc,
    675                         aalloc_calls, aalloc_0_calls, aalloc_storage_request, aalloc_storage_alloc,
    676                         calloc_calls, calloc_0_calls, calloc_storage_request, calloc_storage_alloc,
    677                         memalign_calls, memalign_0_calls, memalign_storage_request, memalign_storage_alloc,
    678                         amemalign_calls, amemalign_0_calls, amemalign_storage_request, amemalign_storage_alloc,
    679                         cmemalign_calls, cmemalign_0_calls, cmemalign_storage_request, cmemalign_storage_alloc,
    680                         resize_calls, resize_0_calls, resize_storage_request, resize_storage_alloc,
    681                         realloc_calls, realloc_0_calls, realloc_storage_request, realloc_storage_alloc,
    682                         free_calls, free_null_calls, free_storage_request, free_storage_alloc,
    683                         return_pulls, return_pushes, return_storage_request, return_storage_alloc,
     368                        stats.malloc_calls, stats.malloc_0_calls, stats.malloc_storage_request, stats.malloc_storage_alloc,
     369                        stats.aalloc_calls, stats.aalloc_0_calls, stats.aalloc_storage_request, stats.aalloc_storage_alloc,
     370                        stats.calloc_calls, stats.calloc_0_calls, stats.calloc_storage_request, stats.calloc_storage_alloc,
     371                        stats.memalign_calls, stats.memalign_0_calls, stats.memalign_storage_request, stats.memalign_storage_alloc,
     372                        stats.amemalign_calls, stats.amemalign_0_calls, stats.amemalign_storage_request, stats.amemalign_storage_alloc,
     373                        stats.cmemalign_calls, stats.cmemalign_0_calls, stats.cmemalign_storage_request, stats.cmemalign_storage_alloc,
     374                        stats.resize_calls, stats.resize_0_calls, stats.resize_storage_request, stats.resize_storage_alloc,
     375                        stats.realloc_calls, stats.realloc_0_calls, stats.realloc_storage_request, stats.realloc_storage_alloc,
     376                        stats.free_calls, stats.free_null_calls, stats.free_storage_request, stats.free_storage_alloc,
    684377                        sbrk_calls, sbrk_storage,
    685                         mmap_calls, mmap_storage_request, mmap_storage_alloc,
    686                     munmap_calls, munmap_storage_request, munmap_storage_alloc,
    687                         threads_started, threads_exited,
    688                         new_heap, reused_heap
     378                        stats.mmap_calls, stats.mmap_storage_request, stats.mmap_storage_alloc,
     379                        stats.munmap_calls, stats.munmap_storage_request, stats.munmap_storage_alloc
    689380                );
    690381} // printStatsXML
    691 
    692 static HeapStatistics & collectStats( HeapStatistics & stats ) with( heapMaster ) {
    693         lock( mgrLock );
    694 
    695         stats += heapMaster.stats;
    696         for ( Heap * heap = heapManagersList; heap; heap = heap->nextHeapManager ) {
    697                 stats += heap->stats;
    698         } // for
    699 
    700         unlock( mgrLock );
    701         return stats;
    702 } // collectStats
    703382#endif // __STATISTICS__
    704383
    705384
    706 static bool setMmapStart( size_t value ) with( heapMaster ) { // true => mmapped, false => sbrk
     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
     395// thunk problem
     396size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     397        size_t l = 0, m, h = dim;
     398        while ( l < h ) {
     399                m = (l + h) / 2;
     400                if ( (unsigned int &)(vals[m]) < key ) {                // cast away const
     401                        l = m + 1;
     402                } else {
     403                        h = m;
     404                } // if
     405        } // while
     406        return l;
     407} // Bsearchl
     408
     409
     410static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
    707411  if ( value < __page_size || bucketSizes[NoBucketSizes - 1] < value ) return false;
    708412        mmapStart = value;                                                                      // set global
    709413
    710414        // find the closest bucket size less than or equal to the mmapStart size
    711         maxBucketsUsed = Bsearchl( mmapStart, bucketSizes, NoBucketSizes ); // binary search
    712         verify( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    713         verify( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     415        maxBucketsUsed = Bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     416        assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
     417        assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    714418        return true;
    715419} // setMmapStart
     
    734438
    735439
    736 inline __attribute__((always_inline))
    737 static void checkAlign( size_t alignment ) {
     440static inline void checkAlign( size_t alignment ) {
    738441        if ( unlikely( alignment < libAlign() || ! is_pow2( alignment ) ) ) {
    739442                abort( "**** Error **** alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
     
    742445
    743446
    744 inline __attribute__((always_inline))
    745 static void checkHeader( bool check, const char name[], void * addr ) {
     447static inline void checkHeader( bool check, const char name[], void * addr ) {
    746448        if ( unlikely( check ) ) {                                                      // bad address ?
    747449                abort( "**** Error **** attempt to %s storage %p with address outside the heap.\n"
     
    768470
    769471
    770 inline __attribute__((always_inline))
    771 static void fakeHeader( Heap.Storage.Header *& header, size_t & alignment ) {
     472static inline void fakeHeader( Heap.Storage.Header *& header, size_t & alignment ) {
    772473        if ( unlikely( AlignmentBit( header ) ) ) {                     // fake header ?
    773474                alignment = ClearAlignmentBit( header );                // clear flag from value
     
    782483
    783484
    784 inline __attribute__((always_inline))
    785 static bool headers( const char name[] __attribute__(( unused )), void * addr, Heap.Storage.Header *& header,
    786                                                         Heap.FreeHeader *& freeHead, size_t & size, size_t & alignment ) with( heapMaster, *heapManager ) {
     485static inline bool headers( const char name[] __attribute__(( unused )), void * addr, Heap.Storage.Header *& header,
     486                                                        Heap.FreeHeader *& freeHead, size_t & size, size_t & alignment ) with( heapManager ) {
    787487        header = HeaderAddr( addr );
    788488
     
    809509        checkHeader( header < (Heap.Storage.Header *)heapBegin || (Heap.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    810510
    811         Heap * homeManager;
    812511        if ( unlikely( freeHead == 0p || // freed and only free-list node => null link
    813512                                   // freed and link points at another free block not to a bucket in the bucket array.
    814                                    (homeManager = freeHead->homeManager, freeHead < &homeManager->freeLists[0] ||
    815                                         &homeManager->freeLists[NoBucketSizes] <= freeHead ) ) ) {
     513                                   freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) ) {
    816514                abort( "**** Error **** attempt to %s storage %p with corrupted header.\n"
    817515                           "Possible cause is duplicate free on same block or overwriting of header information.",
     
    823521} // headers
    824522
    825 
    826 static void * master_extend( size_t size ) with( heapMaster ) {
    827         lock( extLock );
     523// #ifdef __CFA_DEBUG__
     524// #if __SIZEOF_POINTER__ == 4
     525// #define MASK 0xdeadbeef
     526// #else
     527// #define MASK 0xdeadbeefdeadbeef
     528// #endif
     529// #define STRIDE size_t
     530
     531// static void * Memset( void * addr, STRIDE size ) {           // debug only
     532//      if ( size % sizeof(STRIDE) != 0 ) abort( "Memset() : internal error, size %zd not multiple of %zd.", size, sizeof(STRIDE) );
     533//      if ( (STRIDE)addr % sizeof(STRIDE) != 0 ) abort( "Memset() : internal error, addr %p not multiple of %zd.", addr, sizeof(STRIDE) );
     534
     535//      STRIDE * end = (STRIDE *)addr + size / sizeof(STRIDE);
     536//      for ( STRIDE * p = (STRIDE *)addr; p < end; p += 1 ) *p = MASK;
     537//      return addr;
     538// } // Memset
     539// #endif // __CFA_DEBUG__
     540
     541
     542#define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes."
     543
     544static inline void * extend( size_t size ) with( heapManager ) {
     545        lock( extlock __cfaabi_dbg_ctx2 );
    828546
    829547        ptrdiff_t rem = heapRemaining - size;
     
    831549                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    832550
    833                 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, libAlign() );
     551                size_t increase = ceiling2( size > heapExpand ? size : heapExpand, __page_size );
    834552                // Do not call abort or strerror( errno ) as they may call malloc.
    835                 if ( unlikely( sbrk( increase ) == (void *)-1 ) ) {     // failed, no memory ?
    836                         unlock( extLock );
     553                if ( sbrk( increase ) == (void *)-1 ) {                 // failed, no memory ?
     554                        unlock( extlock );
    837555                        __cfaabi_bits_print_nolock( STDERR_FILENO, NO_MEMORY_MSG, size );
    838556                        _exit( EXIT_FAILURE );                                          // give up
    839557                } // if
    840                 rem = heapRemaining + increase - size;
     558
     559                // Make storage executable for thunks.
     560                if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) {
     561                        unlock( extlock );
     562                        __cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno );
     563                        _exit( EXIT_FAILURE );
     564                } // if
    841565
    842566                #ifdef __STATISTICS__
     
    844568                sbrk_storage += increase;
    845569                #endif // __STATISTICS__
     570
     571                #ifdef __CFA_DEBUG__
     572                // Set new memory to garbage so subsequent uninitialized usages might fail.
     573                memset( (char *)heapEnd + heapRemaining, '\xde', increase );
     574                //Memset( (char *)heapEnd + heapRemaining, increase );
     575                #endif // __CFA_DEBUG__
     576
     577                rem = heapRemaining + increase - size;
    846578        } // if
    847579
     
    849581        heapRemaining = rem;
    850582        heapEnd = (char *)heapEnd + size;
    851 
    852         unlock( extLock );
     583        unlock( extlock );
    853584        return block;
    854 } // master_extend
    855 
    856 
    857 __attribute__(( noinline ))
    858 static void * manager_extend( size_t size ) with( *heapManager ) {
    859         ptrdiff_t rem = heapReserve - size;
    860 
    861         if ( unlikely( rem < 0 ) ) {                                            // negative
    862                 // If the size requested is bigger than the current remaining reserve, use the current reserve to populate
    863                 // smaller freeLists, and increase the reserve.
    864 
    865                 rem = heapReserve;                                                              // positive
    866 
    867                 if ( rem >= bucketSizes[0] ) {                                  // minimal size ? otherwise ignore
    868                         size_t bucket;
    869                         #ifdef FASTLOOKUP
    870                         if ( likely( rem < LookupSizes ) ) bucket = lookup[rem];
    871                         #endif // FASTLOOKUP
    872                                 bucket = Bsearchl( rem, bucketSizes, heapMaster.maxBucketsUsed );
    873                         verify( 0 <= bucket && bucket <= heapMaster.maxBucketsUsed );
    874                         Heap.FreeHeader * freeHead = &(freeLists[bucket]);
    875 
    876                         // The remaining storage many not be bucket size, whereas all other allocations are. Round down to previous
    877                         // bucket size in this case.
    878                         if ( unlikely( freeHead->blockSize > (size_t)rem ) ) freeHead -= 1;
    879                         Heap.Storage * block = (Heap.Storage *)heapBuffer;
    880 
    881                         block->header.kind.real.next = freeHead->freeList; // push on stack
    882                         freeHead->freeList = block;
    883                 } // if
    884 
    885                 size_t increase = ceiling( size > ( heapMaster.heapExpand / 10 ) ? size : ( heapMaster.heapExpand / 10 ), libAlign() );
    886                 heapBuffer = master_extend( increase );
    887                 rem = increase - size;
    888         } // if
    889 
    890         Heap.Storage * block = (Heap.Storage *)heapBuffer;
    891         heapReserve = rem;
    892         heapBuffer = (char *)heapBuffer + size;
    893 
    894         return block;
    895 } // manager_extend
    896 
    897 
    898 #define BOOT_HEAP_MANAGER \
    899         if ( unlikely( ! heapMasterBootFlag ) ) { \
    900                 heapManagerCtor(); /* trigger for first heap */ \
    901         } /* if */
    902 
    903 #ifdef __STATISTICS__
    904 #define STAT_NAME __counter
    905 #define STAT_PARM , unsigned int STAT_NAME
    906 #define STAT_ARG( name ) , name
    907 #define STAT_0_CNT( counter ) stats.counters[counter].calls_0 += 1
    908 #else
    909 #define STAT_NAME
    910 #define STAT_PARM
    911 #define STAT_ARG( name )
    912 #define STAT_0_CNT( counter )
    913 #endif // __STATISTICS__
    914 
    915 #define PROLOG( counter, ... ) \
    916         BOOT_HEAP_MANAGER; \
    917         if ( unlikely( size == 0 ) ||                                           /* 0 BYTE ALLOCATION RETURNS NULL POINTER */ \
    918                 unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) { /* error check */ \
    919                 STAT_0_CNT( counter ); \
    920                 __VA_ARGS__; \
    921                 return 0p; \
    922         } /* if */
    923 
    924 
    925 #define SCRUB_SIZE 1024lu
    926 // Do not use '\xfe' for scrubbing because dereferencing an address composed of it causes a SIGSEGV *without* a valid IP
    927 // pointer in the interrupt frame.
    928 #define SCRUB '\xff'
    929 
    930 static void * doMalloc( size_t size STAT_PARM ) libcfa_nopreempt with( *heapManager ) {
    931         PROLOG( STAT_NAME );
    932 
    933         verify( heapManager );
    934         Heap.Storage * block;                                                           // pointer to new block of storage
     585} // extend
     586
     587
     588static inline void * doMalloc( size_t size ) with( heapManager ) {
     589        Heap.Storage * block;                                           // pointer to new block of storage
    935590
    936591        // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
    937592        // along with the block and is a multiple of the alignment size.
     593
    938594        size_t tsize = size + sizeof(Heap.Storage);
    939595
    940         #ifdef __STATISTICS__
    941         stats.counters[STAT_NAME].calls += 1;
    942         stats.counters[STAT_NAME].request += size;
    943         #endif // __STATISTICS__
    944 
    945         #ifdef __CFA_DEBUG__
    946         allocUnfreed += size;
    947         #endif // __CFA_DEBUG__
    948 
    949         if ( likely( tsize < heapMaster.mmapStart ) ) {         // small size => sbrk
    950                 size_t bucket;
     596        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     597                size_t posn;
    951598                #ifdef FASTLOOKUP
    952                 if ( likely( tsize < LookupSizes ) ) bucket = lookup[tsize];
     599                if ( tsize < LookupSizes ) posn = lookup[tsize];
    953600                else
    954601                #endif // FASTLOOKUP
    955                         bucket = Bsearchl( tsize, bucketSizes, heapMaster.maxBucketsUsed );
    956                 verify( 0 <= bucket && bucket <= heapMaster.maxBucketsUsed );
    957                 Heap.FreeHeader * freeHead = &freeLists[bucket];
    958 
    959                 verify( freeHead <= &freeLists[heapMaster.maxBucketsUsed] ); // subscripting error ?
    960                 verify( tsize <= freeHead->blockSize );                 // search failure ?
    961 
    962                 tsize = freeHead->blockSize;                                    // total space needed for request
    963                 #ifdef __STATISTICS__
    964                 stats.counters[STAT_NAME].alloc += tsize;
    965                 #endif // __STATISTICS__
     602                        posn = Bsearchl( (unsigned int)tsize, bucketSizes, (size_t)maxBucketsUsed );
     603                Heap.FreeHeader * freeElem = &freeLists[posn];
     604                verify( freeElem <= &freeLists[maxBucketsUsed] ); // subscripting error ?
     605                verify( tsize <= freeElem->blockSize );                 // search failure ?
     606                tsize = freeElem->blockSize;                                    // total space needed for request
    966607
    967608                // Spin until the lock is acquired for this particular size of block.
    968609
    969610                #if BUCKETLOCK == SPINLOCK
    970                 block = freeHead->freeList;                                             // remove node from stack
     611                lock( freeElem->lock __cfaabi_dbg_ctx2 );
     612                block = freeElem->freeList;                                             // remove node from stack
    971613                #else
    972                 block = pop( freeHead->freeList );
     614                block = pop( freeElem->freeList );
    973615                #endif // BUCKETLOCK
    974616                if ( unlikely( block == 0p ) ) {                                // no free block ?
    975                         #ifdef OWNERSHIP
    976                         // Freelist for that size is empty, so carve it out of the heap, if there is enough left, or get some more
     617                        #if BUCKETLOCK == SPINLOCK
     618                        unlock( freeElem->lock );
     619                        #endif // BUCKETLOCK
     620
     621                        // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more
    977622                        // and then carve it off.
    978                         #ifdef RETURNSPIN
    979                         #if BUCKETLOCK == SPINLOCK
    980                         lock( freeHead->returnLock );
    981                         block = freeHead->returnList;
    982                         freeHead->returnList = 0p;
    983                         unlock( freeHead->returnLock );
    984                         #else
    985                         block = __atomic_exchange_n( &freeHead->returnList, nullptr, __ATOMIC_SEQ_CST );
    986                         #endif // RETURNSPIN
    987 
    988                         if ( likely( block == 0p ) ) {                  // return list also empty?
    989                         #endif // OWNERSHIP
    990                                 // Do not leave kernel thread as manager_extend accesses heapManager.
    991                                 disable_interrupts();
    992                                 block = (Heap.Storage *)manager_extend( tsize ); // mutual exclusion on call
    993                                 enable_interrupts( false );
    994 
    995                                 // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
    996 
    997                                 #ifdef __CFA_DEBUG__
    998                                 // Scrub new memory so subsequent uninitialized usages might fail. Only scrub the first 1024 bytes.
    999                                 memset( block->data, SCRUB, min( SCRUB_SIZE, tsize - sizeof(Heap.Storage) ) );
    1000                                 #endif // __CFA_DEBUG__
    1001                         #endif // BUCKETLOCK
    1002                         #ifdef OWNERSHIP
    1003                         } else {                                                                        // merge returnList into freeHead
    1004                                 #ifdef __STATISTICS__
    1005                                 stats.return_pulls += 1;
    1006                                 #endif // __STATISTICS__
    1007 
    1008                                 // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
    1009 
    1010                                 freeHead->freeList = block->header.kind.real.next;
    1011                         } // if
    1012                         #endif // OWNERSHIP
     623
     624                        block = (Heap.Storage *)extend( tsize );        // mutual exclusion on call
     625                #if BUCKETLOCK == SPINLOCK
    1013626                } else {
    1014                         // Memory is scrubbed in doFree.
    1015                         freeHead->freeList = block->header.kind.real.next;
    1016                 } // if
    1017 
    1018                 block->header.kind.real.home = freeHead;                // pointer back to free list of apropriate size
     627                        freeElem->freeList = block->header.kind.real.next;
     628                        unlock( freeElem->lock );
     629                #endif // BUCKETLOCK
     630                } // if
     631
     632                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    1019633        } else {                                                                                        // large size => mmap
    1020634  if ( unlikely( size > ULONG_MAX - __page_size ) ) return 0p;
    1021635                tsize = ceiling2( tsize, __page_size );                 // must be multiple of page size
    1022636                #ifdef __STATISTICS__
    1023                 stats.counters[STAT_NAME].alloc += tsize;
    1024                 stats.mmap_calls += 1;
    1025                 stats.mmap_storage_request += size;
    1026                 stats.mmap_storage_alloc += tsize;
    1027                 #endif // __STATISTICS__
    1028 
    1029                 disable_interrupts();
    1030                 block = (Heap.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
    1031                 enable_interrupts( false );
    1032 
    1033                 // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
    1034 
    1035                 if ( unlikely( block == (Heap.Storage *)MAP_FAILED ) ) { // failed ?
     637                __atomic_add_fetch( &stats.mmap_calls, 1, __ATOMIC_SEQ_CST );
     638                __atomic_add_fetch( &stats.mmap_storage_request, size, __ATOMIC_SEQ_CST );
     639                __atomic_add_fetch( &stats.mmap_storage_alloc, tsize, __ATOMIC_SEQ_CST );
     640                #endif // __STATISTICS__
     641
     642                block = (Heap.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
     643                if ( block == (Heap.Storage *)MAP_FAILED ) { // failed ?
    1036644                        if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory
    1037645                        // Do not call strerror( errno ) as it may call malloc.
    1038                         abort( "attempt to allocate large object (> %zu) of size %zu bytes and mmap failed with errno %d.", size, heapMaster.mmapStart, errno );
    1039                 } // if
     646                        abort( "(Heap &)0x%p.doMalloc() : internal error, mmap failure, size:%zu errno:%d.", &heapManager, tsize, errno );
     647                } //if
     648                #ifdef __CFA_DEBUG__
     649                // Set new memory to garbage so subsequent uninitialized usages might fail.
     650                memset( block, '\xde', tsize );
     651                //Memset( block, tsize );
     652                #endif // __CFA_DEBUG__
    1040653                block->header.kind.real.blockSize = MarkMmappedBit( tsize ); // storage size for munmap
    1041 
    1042                 #ifdef __CFA_DEBUG__
    1043                 // Scrub new memory so subsequent uninitialized usages might fail. Only scrub the first 1024 bytes.  The rest of
    1044                 // the storage set to 0 by mmap.
    1045                 memset( block->data, SCRUB, min( SCRUB_SIZE, tsize - sizeof(Heap.Storage) ) );
    1046                 #endif // __CFA_DEBUG__
    1047654        } // if
    1048655
     
    1052659
    1053660        #ifdef __CFA_DEBUG__
     661        __atomic_add_fetch( &allocUnfreed, tsize, __ATOMIC_SEQ_CST );
    1054662        if ( traceHeap() ) {
    1055663                char helpText[64];
     
    1059667        #endif // __CFA_DEBUG__
    1060668
    1061 //      poll_interrupts();                                                                      // call rollforward
    1062 
    1063669        return addr;
    1064670} // doMalloc
    1065671
    1066672
    1067 static void doFree( void * addr ) libcfa_nopreempt with( *heapManager ) {
    1068         verify( addr );
    1069 
    1070         // detect free after thread-local storage destruction and use global stats in that case
     673static inline void doFree( void * addr ) with( heapManager ) {
     674        #ifdef __CFA_DEBUG__
     675        if ( unlikely( heapManager.heapBegin == 0p ) ) {
     676                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
     677        } // if
     678        #endif // __CFA_DEBUG__
    1071679
    1072680        Heap.Storage.Header * header;
    1073         Heap.FreeHeader * freeHead;
    1074         size_t size, alignment;
    1075 
    1076         bool mapped = headers( "free", addr, header, freeHead, size, alignment );
    1077         #if defined( __STATISTICS__ ) || defined( __CFA_DEBUG__ )
    1078         size_t rsize = header->kind.real.size;                          // optimization
    1079         #endif // __STATISTICS__ || __CFA_DEBUG__
    1080 
    1081         #ifdef __STATISTICS__
    1082         stats.free_storage_request += rsize;
    1083         stats.free_storage_alloc += size;
    1084         #endif // __STATISTICS__
    1085 
    1086         #ifdef __CFA_DEBUG__
    1087         allocUnfreed -= rsize;
    1088         #endif // __CFA_DEBUG__
    1089 
    1090         if ( unlikely( mapped ) ) {                                                     // mmapped ?
    1091                 #ifdef __STATISTICS__
    1092                 stats.munmap_calls += 1;
    1093                 stats.munmap_storage_request += rsize;
    1094                 stats.munmap_storage_alloc += size;
    1095                 #endif // __STATISTICS__
    1096 
    1097                 // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
    1098 
    1099                 // Does not matter where this storage is freed.
    1100                 if ( unlikely( munmap( header, size ) == -1 ) ) {
    1101                         // Do not call strerror( errno ) as it may call malloc.
    1102                         abort( "attempt to deallocate large object %p and munmap failed with errno %d.\n"
    1103                                    "Possible cause is invalid delete pointer: either not allocated or with corrupt header.",
    1104                                    addr, errno );
     681        Heap.FreeHeader * freeElem;
     682        size_t size, alignment;                                                         // not used (see realloc)
     683
     684        if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
     685                #ifdef __STATISTICS__
     686                __atomic_add_fetch( &stats.munmap_calls, 1, __ATOMIC_SEQ_CST );
     687                __atomic_add_fetch( &stats.munmap_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
     688                __atomic_add_fetch( &stats.munmap_storage_alloc, size, __ATOMIC_SEQ_CST );
     689                #endif // __STATISTICS__
     690                if ( munmap( header, size ) == -1 ) {
     691                        abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n"
     692                                   "Possible cause is invalid pointer.",
     693                                   addr );
    1105694                } // if
    1106695        } else {
    1107696                #ifdef __CFA_DEBUG__
    1108                 // memset is NOT always inlined!
    1109                 disable_interrupts();
    1110                 // Scrub old memory so subsequent usages might fail. Only scrub the first/last SCRUB_SIZE bytes.
    1111                 char * data = ((Heap.Storage *)header)->data;   // data address
    1112                 size_t dsize = size - sizeof(Heap.Storage);             // data size
    1113                 if ( dsize <= SCRUB_SIZE * 2 ) {
    1114                         memset( data, SCRUB, dsize );                           // scrub all
    1115                 } else {
    1116                         memset( data, SCRUB, SCRUB_SIZE );                      // scrub front
    1117                         memset( data + dsize - SCRUB_SIZE, SCRUB, SCRUB_SIZE ); // scrub back
    1118                 } // if
    1119                 enable_interrupts( false );
     697                // Set free memory to garbage so subsequent usages might fail.
     698                memset( ((Heap.Storage *)header)->data, '\xde', freeElem->blockSize - sizeof( Heap.Storage ) );
     699                //Memset( ((Heap.Storage *)header)->data, freeElem->blockSize - sizeof( Heap.Storage ) );
    1120700                #endif // __CFA_DEBUG__
    1121701
    1122                 if ( likely( heapManager == freeHead->homeManager ) ) { // belongs to this thread
    1123                         header->kind.real.next = freeHead->freeList; // push on stack
    1124                         freeHead->freeList = (Heap.Storage *)header;
    1125                 } else {                                                                                // return to thread owner
    1126                         verify( heapManager );
    1127 
    1128                         #ifdef OWNERSHIP
    1129                         #ifdef RETURNSPIN
    1130                         lock( freeHead->returnLock );
    1131                         header->kind.real.next = freeHead->returnList; // push to bucket return list
    1132                         freeHead->returnList = (Heap.Storage *)header;
    1133                         unlock( freeHead->returnLock );
    1134                         #else                                                                           // lock free
    1135                         header->kind.real.next = freeHead->returnList; // link new node to top node
    1136                         // CAS resets header->kind.real.next = freeHead->returnList on failure
    1137                         while ( ! __atomic_compare_exchange_n( &freeHead->returnList, &header->kind.real.next, header,
    1138                                                                                                    false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) );
    1139                         #endif // RETURNSPIN
    1140 
    1141                         #else                                                                           // no OWNERSHIP
    1142 
    1143                         freeHead = &heap->freeLists[ClearStickyBits( header->kind.real.home ) - &freeHead->homeManager->freeLists[0]];
    1144                         header->kind.real.next = freeHead->freeList; // push on stack
    1145                         freeHead->freeList = (Heap.Storage *)header;
    1146                         #endif // ! OWNERSHIP
    1147 
    1148                         #ifdef __U_STATISTICS__
    1149                         stats.return_pushes += 1;
    1150                         stats.return_storage_request += rsize;
    1151                         stats.return_storage_alloc += size;
    1152                         #endif // __U_STATISTICS__
    1153 
    1154                         // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
    1155                 } // if
     702                #ifdef __STATISTICS__
     703                __atomic_add_fetch( &stats.free_calls, 1, __ATOMIC_SEQ_CST );
     704                __atomic_add_fetch( &stats.free_storage_request, header->kind.real.size, __ATOMIC_SEQ_CST );
     705                __atomic_add_fetch( &stats.free_storage_alloc, size, __ATOMIC_SEQ_CST );
     706                #endif // __STATISTICS__
     707
     708                #if BUCKETLOCK == SPINLOCK
     709                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
     710                header->kind.real.next = freeElem->freeList;    // push on stack
     711                freeElem->freeList = (Heap.Storage *)header;
     712                unlock( freeElem->lock );                                               // release spin lock
     713                #else
     714                push( freeElem->freeList, *(Heap.Storage *)header );
     715                #endif // BUCKETLOCK
    1156716        } // if
    1157717
    1158718        #ifdef __CFA_DEBUG__
     719        __atomic_add_fetch( &allocUnfreed, -size, __ATOMIC_SEQ_CST );
    1159720        if ( traceHeap() ) {
    1160721                char helpText[64];
     
    1163724        } // if
    1164725        #endif // __CFA_DEBUG__
    1165 
    1166 //      poll_interrupts();                                                                      // call rollforward
    1167726} // doFree
    1168727
    1169728
    1170 size_t prtFree( Heap & manager ) with( manager ) {
     729static size_t prtFree( Heap & manager ) with( manager ) {
    1171730        size_t total = 0;
    1172731        #ifdef __STATISTICS__
     
    1174733        __cfaabi_bits_print_nolock( STDERR_FILENO, "\nBin lists (bin size : free blocks on list)\n" );
    1175734        #endif // __STATISTICS__
    1176         for ( unsigned int i = 0; i < heapMaster.maxBucketsUsed; i += 1 ) {
     735        for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
    1177736                size_t size = freeLists[i].blockSize;
    1178737                #ifdef __STATISTICS__
     
    1205764        __cfaabi_bits_release();
    1206765        #endif // __STATISTICS__
    1207         return (char *)heapMaster.heapEnd - (char *)heapMaster.heapBegin - total;
     766        return (char *)heapEnd - (char *)heapBegin - total;
    1208767} // prtFree
    1209768
    1210769
    1211 #ifdef __STATISTICS__
    1212 static void incCalls( long int statName ) libcfa_nopreempt {
    1213         heapManager->stats.counters[statName].calls += 1;
    1214 } // incCalls
    1215 
    1216 static void incZeroCalls( long int statName ) libcfa_nopreempt {
    1217         heapManager->stats.counters[statName].calls_0 += 1;
    1218 } // incZeroCalls
    1219 #endif // __STATISTICS__
    1220 
    1221 #ifdef __CFA_DEBUG__
    1222 static void incUnfreed( size_t offset ) libcfa_nopreempt {
    1223         heapManager->allocUnfreed += offset;
    1224 } // incUnfreed
    1225 #endif // __CFA_DEBUG__
    1226 
    1227 
    1228 static void * memalignNoStats( size_t alignment, size_t size STAT_PARM ) {
     770static void ?{}( Heap & manager ) with( manager ) {
     771        __page_size = sysconf( _SC_PAGESIZE );
     772        __map_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
     773
     774        for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     775                freeLists[i].blockSize = bucketSizes[i];
     776        } // for
     777
     778        #ifdef FASTLOOKUP
     779        unsigned int idx = 0;
     780        for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     781                if ( i > bucketSizes[idx] ) idx += 1;
     782                lookup[i] = idx;
     783        } // for
     784        #endif // FASTLOOKUP
     785
     786        if ( ! setMmapStart( malloc_mmap_start() ) ) {
     787                abort( "Heap : internal error, mmap start initialization failure." );
     788        } // if
     789        heapExpand = malloc_expansion();
     790
     791        char * end = (char *)sbrk( 0 );
     792        heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment
     793} // Heap
     794
     795
     796static void ^?{}( Heap & ) {
     797        #ifdef __STATISTICS__
     798        if ( traceHeapTerm() ) {
     799                printStats();
     800                // prtUnfreed() called in heapAppStop()
     801        } // if
     802        #endif // __STATISTICS__
     803} // ~Heap
     804
     805
     806static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
     807void memory_startup( void ) {
     808        #ifdef __CFA_DEBUG__
     809        if ( heapBoot ) {                                                                       // check for recursion during system boot
     810                abort( "boot() : internal error, recursively invoked during system boot." );
     811        } // if
     812        heapBoot = true;
     813        #endif // __CFA_DEBUG__
     814
     815        //verify( heapManager.heapBegin != 0 );
     816        //heapManager{};
     817        if ( heapManager.heapBegin == 0p ) heapManager{};       // sanity check
     818} // memory_startup
     819
     820static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
     821void memory_shutdown( void ) {
     822        ^heapManager{};
     823} // memory_shutdown
     824
     825
     826static inline void * mallocNoStats( size_t size ) {             // necessary for malloc statistics
     827        verify( heapManager.heapBegin != 0p );                          // called before memory_startup ?
     828  if ( unlikely( size ) == 0 ) return 0p;                               // 0 BYTE ALLOCATION RETURNS NULL POINTER
     829
     830#if __SIZEOF_POINTER__ == 8
     831        verify( size < ((typeof(size_t))1 << 48) );
     832#endif // __SIZEOF_POINTER__ == 8
     833        return doMalloc( size );
     834} // mallocNoStats
     835
     836
     837static inline void * memalignNoStats( size_t alignment, size_t size ) {
     838  if ( unlikely( size ) == 0 ) return 0p;                               // 0 BYTE ALLOCATION RETURNS NULL POINTER
     839
     840        #ifdef __CFA_DEBUG__
    1229841        checkAlign( alignment );                                                        // check alignment
    1230 
    1231         // if alignment <= default alignment or size == 0, do normal malloc as two headers are unnecessary
    1232   if ( unlikely( alignment <= libAlign() || size == 0 ) ) return doMalloc( size STAT_ARG( STAT_NAME ) );
     842        #endif // __CFA_DEBUG__
     843
     844        // if alignment <= default alignment, do normal malloc as two headers are unnecessary
     845  if ( unlikely( alignment <= libAlign() ) ) return mallocNoStats( size );
    1233846
    1234847        // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for
     
    1241854        // subtract libAlign() because it is already the minimum alignment
    1242855        // add sizeof(Storage) for fake header
    1243         size_t offset = alignment - libAlign() + sizeof(Heap.Storage);
    1244         char * addr = (char *)doMalloc( size + offset STAT_ARG( STAT_NAME ) );
     856        char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(Heap.Storage) );
    1245857
    1246858        // address in the block of the "next" alignment address
     
    1248860
    1249861        // address of header from malloc
    1250         Heap.Storage.Header * realHeader = HeaderAddr( addr );
    1251         realHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
    1252         #ifdef __CFA_DEBUG__
    1253         incUnfreed( -offset );                                                          // adjustment off the offset from call to doMalloc
    1254         #endif // __CFA_DEBUG__
    1255 
    1256         // address of fake header *before* the alignment location
     862        Heap.Storage.Header * RealHeader = HeaderAddr( addr );
     863        RealHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
     864        // address of fake header * before* the alignment location
    1257865        Heap.Storage.Header * fakeHeader = HeaderAddr( user );
    1258 
    1259866        // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
    1260         fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
     867        fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)RealHeader;
    1261868        // SKULLDUGGERY: odd alignment implies fake header
    1262869        fakeHeader->kind.fake.alignment = MarkAlignmentBit( alignment );
     
    1273880        // then malloc() returns a unique pointer value that can later be successfully passed to free().
    1274881        void * malloc( size_t size ) libcfa_public {
    1275                 return doMalloc( size STAT_ARG( MALLOC ) );
     882                #ifdef __STATISTICS__
     883                if ( likely( size > 0 ) ) {
     884                        __atomic_add_fetch( &stats.malloc_calls, 1, __ATOMIC_SEQ_CST );
     885                        __atomic_add_fetch( &stats.malloc_storage_request, size, __ATOMIC_SEQ_CST );
     886                } else {
     887                        __atomic_add_fetch( &stats.malloc_0_calls, 1, __ATOMIC_SEQ_CST );
     888                } // if
     889                #endif // __STATISTICS__
     890
     891                return mallocNoStats( size );
    1276892        } // malloc
    1277893
     
    1279895        // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes.
    1280896        void * aalloc( size_t dim, size_t elemSize ) libcfa_public {
    1281                 return doMalloc( dim * elemSize STAT_ARG( AALLOC ) );
     897                size_t size = dim * elemSize;
     898                #ifdef __STATISTICS__
     899                if ( likely( size > 0 ) ) {
     900                        __atomic_add_fetch( &stats.aalloc_calls, 1, __ATOMIC_SEQ_CST );
     901                        __atomic_add_fetch( &stats.aalloc_storage_request, size, __ATOMIC_SEQ_CST );
     902                } else {
     903                        __atomic_add_fetch( &stats.aalloc_0_calls, 1, __ATOMIC_SEQ_CST );
     904                } // if
     905                #endif // __STATISTICS__
     906
     907                return mallocNoStats( size );
    1282908        } // aalloc
    1283909
     
    1286912        void * calloc( size_t dim, size_t elemSize ) libcfa_public {
    1287913                size_t size = dim * elemSize;
    1288                 char * addr = (char *)doMalloc( size STAT_ARG( CALLOC ) );
    1289 
    1290           if ( unlikely( addr == NULL ) ) return NULL;          // stop further processing if 0p is returned
     914          if ( unlikely( size ) == 0 ) {                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     915                        #ifdef __STATISTICS__
     916                        __atomic_add_fetch( &stats.calloc_0_calls, 1, __ATOMIC_SEQ_CST );
     917                        #endif // __STATISTICS__
     918                        return 0p;
     919                } // if
     920                #ifdef __STATISTICS__
     921                __atomic_add_fetch( &stats.calloc_calls, 1, __ATOMIC_SEQ_CST );
     922                __atomic_add_fetch( &stats.calloc_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
     923                #endif // __STATISTICS__
     924
     925                char * addr = (char *)mallocNoStats( size );
    1291926
    1292927                Heap.Storage.Header * header;
    1293                 Heap.FreeHeader * freeHead;
     928                Heap.FreeHeader * freeElem;
    1294929                size_t bsize, alignment;
    1295930
     
    1297932                bool mapped =
    1298933                        #endif // __CFA_DEBUG__
    1299                         headers( "calloc", addr, header, freeHead, bsize, alignment );
     934                        headers( "calloc", addr, header, freeElem, bsize, alignment );
    1300935
    1301936                #ifndef __CFA_DEBUG__
    1302937                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    1303                 if ( likely( ! mapped ) )
     938                if ( ! mapped )
    1304939                #endif // __CFA_DEBUG__
    1305940                        // <-------0000000000000000000000000000UUUUUUUUUUUUUUUUUUUUUUUUU> bsize (bucket size) U => undefined
     
    1317952        // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done.
    1318953        void * resize( void * oaddr, size_t size ) libcfa_public {
    1319           if ( unlikely( oaddr == 0p ) ) {                              // => malloc( size )
    1320                         return doMalloc( size STAT_ARG( RESIZE ) );
    1321                 } // if
    1322 
    1323                 PROLOG( RESIZE, doFree( oaddr ) );                              // => free( oaddr )
     954                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     955          if ( unlikely( size == 0 ) ) {                                        // special cases
     956                        #ifdef __STATISTICS__
     957                        __atomic_add_fetch( &stats.resize_0_calls, 1, __ATOMIC_SEQ_CST );
     958                        #endif // __STATISTICS__
     959                        free( oaddr );
     960                        return 0p;
     961                } // if
     962                #ifdef __STATISTICS__
     963                __atomic_add_fetch( &stats.resize_calls, 1, __ATOMIC_SEQ_CST );
     964                #endif // __STATISTICS__
     965
     966          if ( unlikely( oaddr == 0p ) ) {
     967                        #ifdef __STATISTICS__
     968                        __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
     969                        #endif // __STATISTICS__
     970                        return mallocNoStats( size );
     971                } // if
    1324972
    1325973                Heap.Storage.Header * header;
    1326                 Heap.FreeHeader * freeHead;
     974                Heap.FreeHeader * freeElem;
    1327975                size_t bsize, oalign;
    1328                 headers( "resize", oaddr, header, freeHead, bsize, oalign );
     976                headers( "resize", oaddr, header, freeElem, bsize, oalign );
    1329977
    1330978                size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
     
    1332980                if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
    1333981                        ClearZeroFillBit( header );                                     // no alignment and turn off 0 fill
    1334                         #ifdef __CFA_DEBUG__
    1335                         incUnfreed( size - header->kind.real.size ); // adjustment off the size difference
    1336                         #endif // __CFA_DEBUG__
    1337982                        header->kind.real.size = size;                          // reset allocation size
    1338                         #ifdef __STATISTICS__
    1339                         incCalls( RESIZE );
    1340                         #endif // __STATISTICS__
    1341983                        return oaddr;
    1342984                } // if
    1343985
     986                #ifdef __STATISTICS__
     987                __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
     988                #endif // __STATISTICS__
     989
    1344990                // change size, DO NOT preserve STICKY PROPERTIES.
    1345                 doFree( oaddr );                                                                // free previous storage
    1346 
    1347                 return doMalloc( size STAT_ARG( RESIZE ) );             // create new area
     991                free( oaddr );
     992                return mallocNoStats( size );                                   // create new area
    1348993        } // resize
    1349994
     
    1352997        // the old and new sizes.
    1353998        void * realloc( void * oaddr, size_t size ) libcfa_public {
    1354           if ( unlikely( oaddr == 0p ) ) {                                      // => malloc( size )
    1355                   return doMalloc( size STAT_ARG( REALLOC ) );
    1356                 } // if
    1357 
    1358                 PROLOG( REALLOC, doFree( oaddr ) );                             // => free( oaddr )
     999                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1000          if ( unlikely( size == 0 ) ) {                                        // special cases
     1001                        #ifdef __STATISTICS__
     1002                        __atomic_add_fetch( &stats.realloc_0_calls, 1, __ATOMIC_SEQ_CST );
     1003                        #endif // __STATISTICS__
     1004                        free( oaddr );
     1005                        return 0p;
     1006                } // if
     1007                #ifdef __STATISTICS__
     1008                __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
     1009                #endif // __STATISTICS__
     1010
     1011          if ( unlikely( oaddr == 0p ) ) {
     1012                        #ifdef __STATISTICS__
     1013                        __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1014                        #endif // __STATISTICS__
     1015                        return mallocNoStats( size );
     1016                } // if
    13591017
    13601018                Heap.Storage.Header * header;
    1361                 Heap.FreeHeader * freeHead;
     1019                Heap.FreeHeader * freeElem;
    13621020                size_t bsize, oalign;
    1363                 headers( "realloc", oaddr, header, freeHead, bsize, oalign );
     1021                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    13641022
    13651023                size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
     
    13671025                bool ozfill = ZeroFillBit( header );                    // old allocation zero filled
    13681026          if ( unlikely( size <= odsize ) && odsize <= size * 2 ) { // allow up to 50% wasted storage
    1369                         #ifdef __CFA_DEBUG__
    1370                         incUnfreed( size - header->kind.real.size ); // adjustment off the size difference
    1371                         #endif // __CFA_DEBUG__
    1372                         header->kind.real.size = size;                          // reset allocation size
     1027                        header->kind.real.size = size;                          // reset allocation size
    13731028                        if ( unlikely( ozfill ) && size > osize ) {     // previous request zero fill and larger ?
    13741029                                memset( (char *)oaddr + osize, '\0', size - osize ); // initialize added storage
    13751030                        } // if
    1376                         #ifdef __STATISTICS__
    1377                         incCalls( REALLOC );
    1378                         #endif // __STATISTICS__
    13791031                        return oaddr;
    13801032                } // if
    13811033
     1034                #ifdef __STATISTICS__
     1035                __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1036                #endif // __STATISTICS__
     1037
    13821038                // change size and copy old content to new storage
    13831039
    13841040                void * naddr;
    1385                 if ( likely( oalign <= libAlign() ) ) {                 // previous request not aligned ?
    1386                         naddr = doMalloc( size STAT_ARG( REALLOC ) ); // create new area
     1041                if ( likely( oalign == libAlign() ) ) {                 // previous request not aligned ?
     1042                        naddr = mallocNoStats( size );                          // create new area
    13871043                } else {
    1388                         naddr = memalignNoStats( oalign, size STAT_ARG( REALLOC ) ); // create new aligned area
    1389                 } // if
    1390 
    1391                 headers( "realloc", naddr, header, freeHead, bsize, oalign );
    1392                 // To preserve prior fill, the entire bucket must be copied versus the size.
     1044                        naddr = memalignNoStats( oalign, size );        // create new aligned area
     1045                } // if
     1046
     1047                headers( "realloc", naddr, header, freeElem, bsize, oalign );
    13931048                memcpy( naddr, oaddr, min( osize, size ) );             // copy bytes
    1394                 doFree( oaddr );                                                                // free previous storage
     1049                free( oaddr );
    13951050
    13961051                if ( unlikely( ozfill ) ) {                                             // previous request zero fill ?
     
    14121067        // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete)
    14131068        void * memalign( size_t alignment, size_t size ) libcfa_public {
    1414                 return memalignNoStats( alignment, size STAT_ARG( MEMALIGN ) );
     1069                #ifdef __STATISTICS__
     1070                if ( likely( size > 0 ) ) {
     1071                        __atomic_add_fetch( &stats.memalign_calls, 1, __ATOMIC_SEQ_CST );
     1072                        __atomic_add_fetch( &stats.memalign_storage_request, size, __ATOMIC_SEQ_CST );
     1073                } else {
     1074                        __atomic_add_fetch( &stats.memalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1075                } // if
     1076                #endif // __STATISTICS__
     1077
     1078                return memalignNoStats( alignment, size );
    14151079        } // memalign
    14161080
     
    14181082        // Same as aalloc() with memory alignment.
    14191083        void * amemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
    1420                 return memalignNoStats( alignment, dim * elemSize STAT_ARG( AMEMALIGN ) );
     1084                size_t size = dim * elemSize;
     1085                #ifdef __STATISTICS__
     1086                if ( likely( size > 0 ) ) {
     1087                        __atomic_add_fetch( &stats.cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     1088                        __atomic_add_fetch( &stats.cmemalign_storage_request, size, __ATOMIC_SEQ_CST );
     1089                } else {
     1090                        __atomic_add_fetch( &stats.cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1091                } // if
     1092                #endif // __STATISTICS__
     1093
     1094                return memalignNoStats( alignment, size );
    14211095        } // amemalign
    14221096
     
    14251099        void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
    14261100                size_t size = dim * elemSize;
    1427                 char * addr = (char *)memalignNoStats( alignment, size STAT_ARG( CMEMALIGN ) );
    1428 
    1429           if ( unlikely( addr == NULL ) ) return NULL;          // stop further processing if 0p is returned
     1101          if ( unlikely( size ) == 0 ) {                                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     1102                        #ifdef __STATISTICS__
     1103                        __atomic_add_fetch( &stats.cmemalign_0_calls, 1, __ATOMIC_SEQ_CST );
     1104                        #endif // __STATISTICS__
     1105                        return 0p;
     1106                } // if
     1107                #ifdef __STATISTICS__
     1108                __atomic_add_fetch( &stats.cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     1109                __atomic_add_fetch( &stats.cmemalign_storage_request, dim * elemSize, __ATOMIC_SEQ_CST );
     1110                #endif // __STATISTICS__
     1111
     1112                char * addr = (char *)memalignNoStats( alignment, size );
    14301113
    14311114                Heap.Storage.Header * header;
    1432                 Heap.FreeHeader * freeHead;
     1115                Heap.FreeHeader * freeElem;
    14331116                size_t bsize;
    14341117
     
    14361119                bool mapped =
    14371120                        #endif // __CFA_DEBUG__
    1438                         headers( "cmemalign", addr, header, freeHead, bsize, alignment );
     1121                        headers( "cmemalign", addr, header, freeElem, bsize, alignment );
    14391122
    14401123                // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     
    14861169        // 0p, no operation is performed.
    14871170        void free( void * addr ) libcfa_public {
    1488 //              verify( heapManager );
    1489 
    14901171          if ( unlikely( addr == 0p ) ) {                                       // special case
    14911172                        #ifdef __STATISTICS__
    1492                   if ( heapManager )
    1493                         incZeroCalls( FREE );
     1173                        __atomic_add_fetch( &stats.free_null_calls, 1, __ATOMIC_SEQ_CST );
    14941174                        #endif // __STATISTICS__
     1175
     1176                        // #ifdef __CFA_DEBUG__
     1177                        // if ( traceHeap() ) {
     1178                        //      #define nullmsg "Free( 0x0 ) size:0\n"
     1179                        //      // Do not debug print free( 0p ), as it can cause recursive entry from sprintf.
     1180                        //      __cfaabi_dbg_write( nullmsg, sizeof(nullmsg) - 1 );
     1181                        // } // if
     1182                        // #endif // __CFA_DEBUG__
    14951183                        return;
    1496                 } // if
    1497 
    1498                 #ifdef __STATISTICS__
    1499                 incCalls( FREE );
    1500                 #endif // __STATISTICS__
    1501 
    1502                 doFree( addr );                                                                 // handles heapManager == nullptr
     1184                } // exit
     1185
     1186                doFree( addr );
    15031187        } // free
    15041188
     
    15431227          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    15441228                Heap.Storage.Header * header;
    1545                 Heap.FreeHeader * freeHead;
     1229                Heap.FreeHeader * freeElem;
    15461230                size_t bsize, alignment;
    15471231
    1548                 headers( "malloc_usable_size", addr, header, freeHead, bsize, alignment );
     1232                headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
    15491233                return DataStorage( bsize, addr, header );              // data storage in bucket
    15501234        } // malloc_usable_size
     
    15541238        void malloc_stats( void ) libcfa_public {
    15551239                #ifdef __STATISTICS__
    1556                 HeapStatistics stats;
    1557                 HeapStatisticsCtor( stats );
    1558                 if ( printStats( collectStats( stats ) ) == -1 ) {
    1559                 #else
    1560                 #define MALLOC_STATS_MSG "malloc_stats statistics disabled.\n"
    1561                 if ( write( STDERR_FILENO, MALLOC_STATS_MSG, sizeof( MALLOC_STATS_MSG ) - 1 /* size includes '\0' */ ) == -1 ) {
    1562                 #endif // __STATISTICS__
    1563                         abort( "write failed in malloc_stats" );
    1564                 } // if
     1240                printStats();
     1241                if ( prtFree() ) prtFree( heapManager );
     1242                #endif // __STATISTICS__
    15651243        } // malloc_stats
    15661244
     
    15691247        int malloc_stats_fd( int fd __attribute__(( unused )) ) libcfa_public {
    15701248                #ifdef __STATISTICS__
    1571                 int temp = heapMaster.stats_fd;
    1572                 heapMaster.stats_fd = fd;
     1249                int temp = stats_fd;
     1250                stats_fd = fd;
    15731251                return temp;
    15741252                #else
     
    15841262          if ( options != 0 ) { errno = EINVAL; return -1; }
    15851263                #ifdef __STATISTICS__
    1586                 HeapStatistics stats;
    1587                 HeapStatisticsCtor( stats );
    1588                 return printStatsXML( collectStats( stats ), stream ); // returns bytes written or -1
     1264                return printStatsXML( stream );
    15891265                #else
    15901266                return 0;                                                                               // unsupported
     
    15991275                choose( option ) {
    16001276                  case M_TOP_PAD:
    1601                         heapMaster.heapExpand = ceiling2( value, __page_size );
     1277                        heapExpand = ceiling2( value, __page_size );
    16021278                        return 1;
    16031279                  case M_MMAP_THRESHOLD:
     
    16431319// Must have CFA linkage to overload with C linkage realloc.
    16441320void * resize( void * oaddr, size_t nalign, size_t size ) libcfa_public {
    1645   if ( unlikely( oaddr == 0p ) ) {                                              // => malloc( size )
    1646                 return memalignNoStats( nalign, size STAT_ARG( RESIZE ) );
    1647         } // if
    1648 
    1649         PROLOG( RESIZE, doFree( oaddr ) );                                      // => free( oaddr )
     1321        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1322  if ( unlikely( size == 0 ) ) {                                                // special cases
     1323                #ifdef __STATISTICS__
     1324                __atomic_add_fetch( &stats.resize_0_calls, 1, __ATOMIC_SEQ_CST );
     1325                #endif // __STATISTICS__
     1326                free( oaddr );
     1327                return 0p;
     1328        } // if
     1329
     1330        if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum
     1331        #ifdef __CFA_DEBUG__
     1332        else checkAlign( nalign );                                                      // check alignment
     1333        #endif // __CFA_DEBUG__
     1334
     1335  if ( unlikely( oaddr == 0p ) ) {
     1336                #ifdef __STATISTICS__
     1337                __atomic_add_fetch( &stats.resize_calls, 1, __ATOMIC_SEQ_CST );
     1338                __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
     1339                #endif // __STATISTICS__
     1340                return memalignNoStats( nalign, size );
     1341        } // if
    16501342
    16511343        // Attempt to reuse existing alignment.
     
    16551347
    16561348        if ( unlikely( isFakeHeader ) ) {
    1657                 checkAlign( nalign );                                                   // check alignment
    16581349                oalign = ClearAlignmentBit( header );                   // old alignment
    16591350                if ( unlikely( (uintptr_t)oaddr % nalign == 0   // lucky match ?
     
    16621353                        ) ) {
    16631354                        HeaderAddr( oaddr )->kind.fake.alignment = MarkAlignmentBit( nalign ); // update alignment (could be the same)
    1664                         Heap.FreeHeader * freeHead;
     1355                        Heap.FreeHeader * freeElem;
    16651356                        size_t bsize, oalign;
    1666                         headers( "resize", oaddr, header, freeHead, bsize, oalign );
     1357                        headers( "resize", oaddr, header, freeElem, bsize, oalign );
    16671358                        size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
    16681359
     
    16701361                                HeaderAddr( oaddr )->kind.fake.alignment = MarkAlignmentBit( nalign ); // update alignment (could be the same)
    16711362                                ClearZeroFillBit( header );                             // turn off 0 fill
    1672                                 #ifdef __CFA_DEBUG__
    1673                                 incUnfreed( size - header->kind.real.size ); // adjustment off the size difference
    1674                                 #endif // __CFA_DEBUG__
    16751363                                header->kind.real.size = size;                  // reset allocation size
    1676                                 #ifdef __STATISTICS__
    1677                                 incCalls( RESIZE );
    1678                                 #endif // __STATISTICS__
    16791364                                return oaddr;
    16801365                        } // if
     
    16851370        } // if
    16861371
     1372        #ifdef __STATISTICS__
     1373        __atomic_add_fetch( &stats.resize_storage_request, size, __ATOMIC_SEQ_CST );
     1374        #endif // __STATISTICS__
     1375
    16871376        // change size, DO NOT preserve STICKY PROPERTIES.
    1688         doFree( oaddr );                                                                        // free previous storage
    1689         return memalignNoStats( nalign, size STAT_ARG( RESIZE ) ); // create new aligned area
     1377        free( oaddr );
     1378        return memalignNoStats( nalign, size );                         // create new aligned area
    16901379} // resize
    16911380
    16921381
    16931382void * realloc( void * oaddr, size_t nalign, size_t size ) libcfa_public {
    1694   if ( unlikely( oaddr == 0p ) ) {                                              // => malloc( size )
    1695                 return memalignNoStats( nalign, size STAT_ARG( REALLOC ) );
    1696         } // if
    1697 
    1698         PROLOG( REALLOC, doFree( oaddr ) );                                     // => free( oaddr )
     1383        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1384  if ( unlikely( size == 0 ) ) {                                                // special cases
     1385                #ifdef __STATISTICS__
     1386                __atomic_add_fetch( &stats.realloc_0_calls, 1, __ATOMIC_SEQ_CST );
     1387                #endif // __STATISTICS__
     1388                free( oaddr );
     1389                return 0p;
     1390        } // if
     1391
     1392        if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum
     1393        #ifdef __CFA_DEBUG__
     1394        else checkAlign( nalign );                                                      // check alignment
     1395        #endif // __CFA_DEBUG__
     1396
     1397  if ( unlikely( oaddr == 0p ) ) {
     1398                #ifdef __STATISTICS__
     1399                __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
     1400                __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1401                #endif // __STATISTICS__
     1402                return memalignNoStats( nalign, size );
     1403        } // if
    16991404
    17001405        // Attempt to reuse existing alignment.
     
    17031408        size_t oalign;
    17041409        if ( unlikely( isFakeHeader ) ) {
    1705                 checkAlign( nalign );                                                   // check alignment
    17061410                oalign = ClearAlignmentBit( header );                   // old alignment
    17071411                if ( unlikely( (uintptr_t)oaddr % nalign == 0   // lucky match ?
     
    17171421        } // if
    17181422
    1719         Heap.FreeHeader * freeHead;
     1423        #ifdef __STATISTICS__
     1424        __atomic_add_fetch( &stats.realloc_calls, 1, __ATOMIC_SEQ_CST );
     1425        __atomic_add_fetch( &stats.realloc_storage_request, size, __ATOMIC_SEQ_CST );
     1426        #endif // __STATISTICS__
     1427
     1428        Heap.FreeHeader * freeElem;
    17201429        size_t bsize;
    1721         headers( "realloc", oaddr, header, freeHead, bsize, oalign );
     1430        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    17221431
    17231432        // change size and copy old content to new storage
     
    17261435        bool ozfill = ZeroFillBit( header );                            // old allocation zero filled
    17271436
    1728         void * naddr = memalignNoStats( nalign, size STAT_ARG( REALLOC ) ); // create new aligned area
    1729 
    1730         headers( "realloc", naddr, header, freeHead, bsize, oalign );
     1437        void * naddr = memalignNoStats( nalign, size );         // create new aligned area
     1438
     1439        headers( "realloc", naddr, header, freeElem, bsize, oalign );
    17311440        memcpy( naddr, oaddr, min( osize, size ) );                     // copy bytes
    1732         doFree( oaddr );                                                                        // free previous storage
     1441        free( oaddr );
    17331442
    17341443        if ( unlikely( ozfill ) ) {                                                     // previous request zero fill ?
     
    17421451
    17431452
    1744 void * reallocarray( void * oaddr, size_t nalign, size_t dim, size_t elemSize ) __THROW {
    1745         return realloc( oaddr, nalign, dim * elemSize );
    1746 } // reallocarray
    1747 
    1748 
    17491453// Local Variables: //
    17501454// tab-width: 4 //
  • libcfa/src/heap.hfa

    r4f102fa ra55472cc  
    1010// Created On       : Tue May 26 11:23:55 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct  4 19:08:55 2022
    13 // Update Count     : 23
     12// Last Modified On : Thu Apr 21 22:52:25 2022
     13// Update Count     : 21
    1414//
    1515
     
    3030bool checkFreeOff();
    3131
     32// supported mallopt options
     33#ifndef M_MMAP_THRESHOLD
     34#define M_MMAP_THRESHOLD (-1)
     35#endif // M_MMAP_THRESHOLD
     36
     37#ifndef M_TOP_PAD
     38#define M_TOP_PAD (-2)
     39#endif // M_TOP_PAD
     40
    3241extern "C" {
    3342        // New allocation operations.
     
    4049        size_t malloc_size( void * addr );
    4150        int malloc_stats_fd( int fd );
     51        size_t malloc_usable_size( void * addr );
    4252        size_t malloc_expansion();                                                      // heap expansion size (bytes)
    4353        size_t malloc_mmap_start();                                                     // crossover allocation size from sbrk to mmap
  • libcfa/src/startup.cfa

    r4f102fa ra55472cc  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Oct  6 13:51:57 2022
    13 // Update Count     : 57
     12// Last Modified On : Mon Jan 17 16:41:54 2022
     13// Update Count     : 55
    1414//
    1515
     
    2424
    2525extern "C" {
    26         void __cfaabi_memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
    27         void __cfaabi_memory_startup( void ) {
    28                 extern void memory_startup();
    29                 memory_startup();
    30         } // __cfaabi_memory_startup
    31 
    32         void __cfaabi_memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
    33         void __cfaabi_memory_shutdown( void ) {
    34                 extern void memory_shutdown();
    35                 memory_shutdown();
    36         } // __cfaabi_memory_shutdown
    37 
    3826        void __cfaabi_appready_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_APPREADY ) ));
    3927        void __cfaabi_appready_startup( void ) {
    4028                tzset();                                                                                // initialize time global variables
     29                #ifdef __CFA_DEBUG__
    4130                extern void heapAppStart();
    4231                heapAppStart();
     32                #endif // __CFA_DEBUG__
    4333        } // __cfaabi_appready_startup
    4434
    4535        void __cfaabi_appready_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_APPREADY ) ));
    4636        void __cfaabi_appready_shutdown( void ) {
     37                #ifdef __CFA_DEBUG__
    4738                extern void heapAppStop();
    4839                heapAppStop();
     40                #endif // __CFA_DEBUG__
    4941        } // __cfaabi_appready_shutdown
    5042
  • libcfa/src/stdhdr/assert.h

    r4f102fa ra55472cc  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct  9 21:28:22 2022
    13 // Update Count     : 16
     12// Last Modified On : Tue Feb  4 12:58:49 2020
     13// Update Count     : 15
    1414//
    1515
     
    3131#endif
    3232
    33 #if ! defined(NDEBUG) && (defined(__CFA_DEBUG__) || defined(__CFA_VERIFY__))
     33#if !defined(NDEBUG) && (defined(__CFA_DEBUG__) || defined(__CFA_VERIFY__))
    3434        #define __CFA_WITH_VERIFY__
    3535        #define verify(x) assert(x)
  • tests/.expect/alloc.txt

    r4f102fa ra55472cc  
    3535CFA realloc array alloc, fill
    36360xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
    37 CFA realloc array alloc, 5
    38 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5
    39 CFA realloc array alloc, 5
    40 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    41 CFA realloc array alloc, 5
    42 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5 0x5
    4337
    4438C   memalign 42 42.5
  • tests/alloc.cfa

    r4f102fa ra55472cc  
    1010// Created On       : Wed Feb  3 07:56:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 29 10:57:02 2022
    13 // Update Count     : 436
     12// Last Modified On : Mon Apr 18 17:13:52 2022
     13// Update Count     : 433
    1414//
    1515
     
    154154        printf( "\n" );
    155155        // do not free
    156 
     156#if 0 // FIX ME
    157157        ip = alloc( 5 * dim, ip`realloc, 5`fill );                      // CFA realloc array alloc, 5
    158158        printf( "CFA realloc array alloc, 5\n" );
     
    171171        for ( i; 5 * dim ) { printf( "%#x ", ip[i] ); }
    172172        printf( "\n" );
    173 
     173#endif // 0
    174174        free( ip );
    175175
  • tests/alloc2.cfa

    r4f102fa ra55472cc  
    1 #include <fstream.hfa>                                                                  // sout
    21#include <malloc.h>                                                                             // malloc_usable_size
    32#include <stdint.h>                                                                             // uintptr_t
     
    54#include <string.h>                                                                             // memcmp
    65
     6int last_failed;
    77int tests_total;
    88int tests_failed;
     
    1313void test_base( void * ip, size_t size, size_t align ) {
    1414        tests_total += 1;
    15         // sout | "DEBUG: starting test" | tests_total;
     15//      printf( "DEBUG: starting test %d\n", tests_total);
    1616        bool passed = (malloc_size( ip ) == size) && (malloc_usable_size( ip ) >= size) && (malloc_alignment( ip ) == align) && ((uintptr_t)ip % align  == 0);
    1717        if ( ! passed ) {
    18                 sout | "base failed test" | tests_total | "ip" | ip | "size" | size | "align" | align | "but got size" | malloc_size( ip ) | "usable" | malloc_usable_size( ip ) | "align" | malloc_alignment( ip );
     18                printf( "failed test %3d: %4zu %4zu but got %4zu ( %3zu ) %4zu\n", tests_total, size, align, malloc_size( ip ), malloc_usable_size( ip ), malloc_alignment( ip ) );
    1919                tests_failed += 1;
    2020        } // if
    21         // sout | "DEBUG: done test" | tests_total;
     21//      printf( "DEBUG: done test %d\n", tests_total);
    2222}
    2323
    2424void test_fill( void * ip_, size_t start, size_t end, char fill ) {
    2525        tests_total += 1;
    26         // sout | "DEBUG: starting test" | tests_total;
     26//      printf( "DEBUG: starting test %d\n", tests_total );
    2727        bool passed = true;
    2828        char * ip = (char *) ip_;
    2929        for ( i; start ~ end ) passed = passed && (ip[i] == fill);
    3030        if ( ! passed ) {
    31                 sout | "fill1 failed test" | tests_total | "fill C";
     31                printf( "failed test %3d: fill C\n", tests_total );
    3232                tests_failed += 1;
    3333        } // if
    34         // sout | "DEBUG: done test" | tests_total;
     34//      printf( "DEBUG: done test %d\n", tests_total );
    3535}
    3636
    3737void test_fill( void * ip_, size_t start, size_t end, int fill ) {
    3838        tests_total += 1;
    39         // sout | "DEBUG: starting test" tests_total;
     39//      printf( "DEBUG: starting test %d\n", tests_total );
    4040        bool passed = true;
    4141        int * ip = (int *)ip_;
    42         for ( i; start ~ end ) passed = passed && (ip[i] == fill);
     42        for (i; start ~ end ) passed = passed && (ip[i] == fill);
    4343        if ( ! passed ) {
    44                 sout | "fill2 failed test" | tests_total | "fill int";
     44                printf( "failed test %3d: fill int\n", tests_total );
    4545                tests_failed += 1;
    4646        } // if
    47         // sout | "DEBUG: done test" | tests_total;
     47//      printf( "DEBUG: done test %d\n", tests_total );
    4848}
    4949
    5050void test_fill( void * ip_, size_t start, size_t end, int * fill ) {
    5151        tests_total += 1;
    52         // sout | "DEBUG: starting test" | tests_total;
     52//      printf( "DEBUG: starting test %d\n", tests_total );
    5353        bool passed = memcmp((void*)((uintptr_t )ip_ + start ), (void*)fill, end ) == 0;
    5454        if ( ! passed ) {
    55                 sout | "fill3 failed test" | tests_total | "fill int A";
     55                printf( "failed test %3d: fill int A\n", tests_total );
    5656                tests_failed += 1;
    5757        } // if
    58         // sout | "DEBUG: done test" | tests_total;
     58//      printf( "DEBUG: done test %d\n", tests_total );
    5959}
    6060
    6161void test_fill( void * ip_, size_t start, size_t end, T1 fill ) {
    6262        tests_total += 1;
    63         // sout | "DEBUG: starting test" | tests_total;
     63//      printf( "DEBUG: starting test %d\n", tests_total );
    6464        bool passed = true;
    6565        T1 * ip = (T1 *) ip_;
    6666        for ( i; start ~ end ) passed = passed && (ip[i].data == fill.data );
    6767        if ( ! passed ) {
    68                 sout | "fill4 failed test" | tests_total | "fill T1";
     68                printf( "failed test %3d: fill T1\n", tests_total );
    6969                tests_failed += 1;
    7070        } // if
    71         // sout | "DEBUG: done test" | tests_total;
     71//      printf( "DEBUG: done test %d\n", tests_total );
    7272}
    7373
    7474void test_fill( void * ip_, size_t start, size_t end, T1 * fill ) {
    7575        tests_total += 1;
    76         // sout | "DEBUG: starting test" | tests_total;
     76//      printf( "DEBUG: starting test %d\n", tests_total );
    7777        bool passed = memcmp( (void*)((uintptr_t )ip_ + start ), (void*)fill, end ) == 0;
    7878        if ( ! passed ) {
    79                 sout | "fill5 failed test" | tests_total | "fill T1 A";
     79                printf( "failed test %3d: fill T1 A\n", tests_total );
    8080                tests_failed += 1;
    8181        } // if
    82         // sout | "DEBUG: done test" | tests_total;
     82//      printf( "DEBUG: done test %d\n", tests_total );
    8383}
    8484
    8585void test_use( int * ip, size_t dim ) {
    8686        tests_total += 1;
    87         // sout | "DEBUG: starting test" | tests_total;
     87//      printf( "DEBUG: starting test %d\n", tests_total );
    8888        bool passed = true;
    8989        for ( i; 0 ~ dim ) ip[i] = 0xdeadbeef;
    9090        for ( i; 0 ~ dim ) passed = passed &&  (ip[i] == 0xdeadbeef);
    9191        if ( ! passed ) {
    92                 sout | "use1 failed test" | tests_total | "use int";
     92                printf( "failed test %3d: use int\n", tests_total );
    9393                tests_failed += 1;
    9494        } // if
    95         // sout | "DEBUG: done test" | tests_total;
     95//      printf( "DEBUG: done test %d\n", tests_total );
    9696}
    9797
    9898void test_use( T1 * ip, size_t dim ) {
    9999        tests_total += 1;
    100         // sout | "DEBUG: starting test" | tests_total;
     100//      printf( "DEBUG: starting test %d\n", tests_total );
    101101        bool passed = true;
    102102        for ( i; 0 ~ dim ) ip[i].data = 0xdeadbeef;
    103103        for ( i; 0 ~ dim ) passed = passed &&  (ip[i].data == 0xdeadbeef);
    104104        if ( ! passed ) {
    105                 sout | "use2 failed test" | tests_total | "use T1";
     105                printf( "failed test %3d: use T1\n", tests_total );
    106106                tests_failed += 1;
    107107        } // if
    108         // sout | "DEBUG: done test" | tests_total;
     108//      printf( "DEBUG: done test %d\n", tests_total );
    109109}
    110110
     
    117117        char FillC = 'a';
    118118        int * FillA = calloc( dim / 4 );
    119 
    120119        T1 FillT1 = { FillT };
    121120        T1 * FillT1A = (T1 *)(void *) malloc( (dim / 4) * sizeof(T1) );
     
    130129        // testing alloc
    131130
     131        last_failed = -1;
    132132        tests_total = 0;
    133133        tests_failed = 0;
     
    153153        free( ip );
    154154
    155         ip = alloc( 0p`resize );
     155        ip = alloc( ((double *)0p)`resize );
    156156        test_base( ip, elemSize, libAlign );
    157157        test_use( ip, elemSize / elemSize );
     
    495495        free( ip );
    496496
    497         if ( tests_failed == 0 ) sout | "PASSED alloc tests" | nl | nl;
    498         else sout | "failed alloc tests :" | tests_failed | tests_total | nl | nl;
    499 
    500         // testing alloc (aligned struct)
     497        if ( tests_failed == 0 ) printf( "PASSED alloc tests\n\n" );
     498        else printf( "failed alloc tests : %d/%d\n\n", tests_failed, tests_total );
     499
     500        // testing alloc ( aligned struct )
    501501
    502502        elemSize = sizeof(T1);
    503503        size = dim * elemSize;
     504        last_failed = -1;
    504505        tests_total = 0;
    505506        tests_failed = 0;
     
    867868        free( t1p );
    868869
    869         if ( tests_failed == 0) sout | "PASSED alloc tests (aligned struct)" | nl | nl;
    870         else sout | "failed alloc tests ( aligned struct ) :" | tests_failed | tests_total | nl;
    871 
    872         sout | "(if applicable) alignment error below indicates memory trashing caused by test_use." | nl | nl;
     870        if ( tests_failed == 0) printf( "PASSED alloc tests (aligned struct)\n\n");
     871        else printf( "failed alloc tests ( aligned struct ) : %d/%d\n\n", tests_failed, tests_total );
     872
     873        printf( "(if applicable) alignment error below indicates memory trashing caused by test_use.\n\n");
    873874        free( FillA );
    874875        free( FillT1A );
  • tests/malloc.cfa

    r4f102fa ra55472cc  
    1 #include <fstream.hfa>                                                                  // sout
     1#include <assert.h>
    22#include <malloc.h>                                                                             // malloc_usable_size
    33#include <stdint.h>                                                                             // uintptr_t
     4#include <stdlib.h>                                                                             // posix_memalign
     5#include <fstream.hfa>
    46#include <stdlib.hfa>                                                                   // access C malloc, realloc
    57#include <unistd.h>                                                                             // getpagesize
     
    810int tests_failed;
    911size_t tAlign = 32;
    10 struct S1 { int data; } __attribute__(( aligned(32)));
     12struct S1 { int d1; } __attribute__((aligned(32)));
    1113typedef struct S1 T1;
    1214
    13 void test_base( void * ip, size_t size, size_t align ) {
     15void test_base( void * ip, size_t size, size_t align) {
    1416        tests_total += 1;
    15         bool passed = (malloc_size( ip ) == size) && (malloc_usable_size( ip ) >= size) && (malloc_alignment( ip ) == align) && ((uintptr_t)ip % align  == 0);
    16         if ( ! passed ) {
    17                 sout | "base failed test" | tests_total | "ip" | ip | "size" | size | "align" | align | "but got size" | malloc_size( ip ) | "usable" | malloc_usable_size( ip ) | "align" | malloc_alignment( ip );
     17        bool passed = (malloc_size(ip) == size) && (malloc_usable_size(ip) >= size) && (malloc_alignment(ip) == align) && ((uintptr_t)ip % align  == 0);
     18        if (!passed) {
     19                printf("failed test %2d: %4lu %4lu but got %4lu ( %3lu ) %4lu\n", tests_total, size, align, malloc_size(ip), malloc_usable_size(ip), malloc_alignment(ip));
    1820                tests_failed += 1;
    19         } // if
     21        }
    2022}
    2123
    22 void test_fill( void * ip_, size_t start, size_t end, char fill ) {
     24void test_fill( void * ip_, size_t start, size_t end, char fill) {
    2325        tests_total += 1;
    2426        bool passed = true;
    2527        char * ip = (char *) ip_;
    26         for ( i; start ~ end ) passed = passed && (ip[i] == fill);
    27         if ( ! passed ) {
    28                 sout | "fill1 failed test" | tests_total | "fill C";
     28        for (i; start ~ end) passed = passed && (ip[i] == fill);
     29        if (!passed) {
     30                printf("failed test %2d: fill\n", tests_total);
    2931                tests_failed += 1;
    30         } // if
     32        }
    3133}
    3234
    33 void test_use( void * ip_ ) {
     35void test_use( void * ip_) {
    3436        tests_total += 1;
    3537        bool passed = true;
    3638        int * ip = (int *) ip_;
    37         size_t size = malloc_size( ip );
    38         for ( i; 0 ~ size ~ sizeof(int)) ip[i/sizeof(int)] = 0xdeadbeef;
    39         for ( i; 0 ~ size ~ sizeof(int)) passed = passed && (ip[i / sizeof(int)] == 0xdeadbeef);
    40         size_t usize = malloc_usable_size( ip );
    41         for ( i; size ~ usize ~ sizeof(int)) ip[i / sizeof(int)] = -1;
    42         for ( i; size ~ usize ~ sizeof(int)) passed = passed &&  (ip[i / sizeof(int)] == -1);
    43         if ( ! passed ) {
    44                 sout | "failed test" | tests_total | "use";
     39        size_t size = malloc_size(ip);
     40        for (i; 0 ~ size ~ sizeof(int)) ip[i/sizeof(int)] = 0xdeadbeef;
     41        for (i; 0 ~ size ~ sizeof(int)) passed = passed &&  (ip[i/sizeof(int)] == 0xdeadbeef);
     42        size_t usize = malloc_usable_size(ip);
     43        for (i; size ~ usize ~ sizeof(int)) ip[i/sizeof(int)] = -1;
     44        for (i; size ~ usize ~ sizeof(int)) passed = passed &&  (ip[i/sizeof(int)] == -1);
     45        if (!passed) {
     46                printf("failed test %2d: use\n", tests_total);
    4547                tests_failed += 1;
    4648        }
     
    4850
    4951int main( void ) {
    50         enum { dim = 8, align = 64, libAlign = libAlign() };
    5152        size_t elemSize = sizeof(int);
     53        size_t dim = 8;
    5254        size_t size = dim * elemSize;
     55        size_t align = 64;
     56        const size_t libAlign = libAlign();
    5357        char fill = '\xde';
    5458        int * ip;
    5559        T1 * tp;
    5660
    57         // testing C malloc
     61        // testing C   malloc
    5862
    5963        tests_total = 0;
    6064        tests_failed = 0;
    6165
    62         ip = (int *)malloc( size );
    63         test_base( ip, size, libAlign );
    64         test_use( ip );
    65         free( ip );
    66 
    67         ip = (int *)malloc( 0 );
    68         test_base( ip, 0, libAlign );
    69         test_use( ip );
    70         free( ip );
    71 
    72         ip = (int *)aalloc( dim, elemSize );
    73         test_base( ip, size, libAlign );
    74         test_use( ip );
    75         free( ip );
    76 
    77         ip = (int *)aalloc( 0, elemSize );
    78         test_base( ip, 0, libAlign );
    79         test_use( ip );
    80         free( ip );
    81 
    82         ip = (int *)aalloc( dim, 0 );
    83         test_base( ip, 0, libAlign );
    84         test_use( ip );
    85         free( ip );
    86 
    87         ip = (int *)aalloc( 0, 0 );
    88         test_base( ip, 0, libAlign );
    89         test_use( ip );
    90         free( ip );
    91 
    92         ip = (int *)calloc( dim, elemSize );
    93         test_base( ip, size, libAlign );
    94         test_fill( ip, 0, size, '\0' );
    95         test_use( ip );
    96         free( ip );
    97 
    98         ip = (int *)calloc( 0, elemSize );
    99         test_base( ip, 0, libAlign );
    100         test_fill( ip, 0, 0, '\0' );
    101         test_use( ip );
    102         free( ip );
    103 
    104         ip = (int *)calloc( dim, 0 );
    105         test_base( ip, 0, libAlign );
    106         test_fill( ip, 0, 0, '\0' );
    107         test_use( ip );
    108         free( ip );
    109 
    110         ip = (int *)malloc( size );
    111         ip = (int *)resize( ip, size / 4 );
    112         test_base( ip, size / 4, libAlign );
    113         test_use( ip );
    114         free( ip );
    115 
    116         ip = (int *)malloc( size );
    117         ip = (int *)resize( ip, size * 4 );
    118         test_base( ip, size * 4, libAlign );
    119         test_use( ip );
    120         free( ip );
    121 
    122         ip = (int *)malloc( size );
    123         ip = (int *)resize( ip, 0 );
    124         test_base( ip, 0, libAlign );
    125         test_use( ip );
    126         free( ip );
    127 
    128         ip = (int *)resize( NULL, size );
    129         test_base( ip, size, libAlign );
    130         test_use( ip );
    131         free( ip );
    132 
    133         ip = (int *)resize( 0p, size );
    134         test_base( ip, size, libAlign );
    135         test_use( ip );
    136         free( ip );
    137 
    138         ip = (int *)calloc( dim, elemSize );
    139         ip = (int *)realloc( ip, size / 4 );
    140         test_base( ip, size / 4, libAlign );
    141         test_fill( ip, 0, size / 4, '\0' );
    142         test_use( ip );
    143         free( ip );
    144 
    145         ip = (int *)calloc( dim, elemSize );
    146         ip = (int *)realloc( ip, size * 4 );
    147         test_base( ip, size * 4, libAlign );
    148         test_fill( ip, 0, size * 4, '\0' );
    149         test_use( ip );
    150         free( ip );
    151 
    152         ip = (int *)calloc( dim, elemSize );
    153         ip = (int *)realloc( ip, 0 );
    154         test_base( ip, 0, libAlign );
    155         test_use( ip );
    156         free( ip );
    157 
    158         ip = (int *)realloc( NULL, size  );
    159         test_base( ip, size , libAlign );
    160         test_use( ip );
    161         free( ip );
    162 
    163         ip = (int *)realloc( 0p, size );
    164         test_base( ip, size, libAlign );
    165         test_use( ip );
    166         free( ip );
    167 
    168         ip = (int *)memalign( align, size );
    169         test_base( ip, size, align );
    170         test_use( ip );
    171         free( ip );
    172 
    173         ip = (int *)memalign( align, 0 );
    174         test_base( ip, 0, libAlign );
    175         test_use( ip );
    176         free( ip );
    177 
    178         ip = (int *)amemalign( align, dim, elemSize );
    179         test_base( ip, size, align );
    180         test_use( ip );
    181         free( ip );
    182 
    183         ip = (int *)amemalign( align, 0, elemSize );
    184         test_base( ip, 0, libAlign );
    185         test_use( ip );
    186         free( ip );
    187 
    188         ip = (int *)amemalign( align, dim, 0 );
    189         test_base( ip, 0, libAlign );
    190         test_use( ip );
    191         free( ip );
    192 
    193         ip = (int *)cmemalign( align, dim, elemSize );
    194         test_base( ip, size, align );
    195         test_fill( ip, 0, size, '\0' );
    196         test_use( ip );
    197         free( ip );
    198 
    199         ip = (int *)cmemalign( align, 0, elemSize );
    200         test_base( ip, 0, libAlign );
    201         test_use( ip );
    202         free( ip );
    203 
    204         ip = (int *)cmemalign( align, dim, 0 );
    205         test_base( ip, 0, libAlign );
    206         test_use( ip );
    207         free( ip );
    208 
    209         ip = (int *)aligned_alloc( align, size );
    210         test_base( ip, size, align );
    211         test_use( ip );
    212         free( ip );
    213 
    214         ip = (int *)aligned_alloc( align, 0 );
    215         test_base( ip, 0, libAlign );
    216         test_use( ip );
    217         free( ip );
    218 
    219         posix_memalign( (void **) &ip, align, size );
    220         test_base( ip, size, align );
    221         test_use( ip );
    222         free( ip );
    223 
    224         posix_memalign( (void **) &ip, align, 0 );
    225         test_base( ip, 0, libAlign );
    226         test_use( ip );
    227         free( ip );
    228 
    229         ip = (int *)valloc( size );
    230         test_base( ip, size, getpagesize() );
    231         test_use( ip );
    232         free( ip );
    233 
    234         ip = (int *)valloc( 0 );
    235         test_base( ip, 0, libAlign );
    236         test_use( ip );
    237         free( ip );
    238 
    239         ip = (int *)pvalloc( getpagesize() * 3 / 2 );
    240         test_base( ip, getpagesize() * 2, getpagesize() );
    241         test_use( ip );
    242         free( ip );
    243 
    244         ip = (int *)pvalloc( 0 );
    245         test_base( ip, 0, libAlign );
    246         test_use( ip );
    247         free( ip );
    248 
    249         ip = (int *)malloc( size );
    250         ip = (int *)resize( ip, libAlign, size / 2 );
    251         test_base( ip, size / 2, libAlign );
    252         test_use( ip );
    253         free( ip );
    254 
    255         ip = (int *)aligned_alloc( align, size );
    256         ip = (int *)resize( ip, align, size / 2 );
    257         test_base( ip, size / 2, align );
    258         test_use( ip );
    259         free( ip );
    260 
    261         ip = (int *)malloc( size );
    262         ip = (int *)resize( ip, align, size / 4 );
    263         test_base( ip, size / 4, align );
    264         test_use( ip );
    265         free( ip );
    266 
    267         ip = (int *)malloc( size );
    268         ip = (int *)resize( ip, align, 0 );
    269         test_base( ip, 0, libAlign );
    270         test_use( ip );
    271         free( ip );
    272 
    273         ip = (int *)resize( NULL, align, size );
    274         test_base( ip, size, align );
    275         test_use( ip );
    276         free( ip );
    277 
    278         ip = (int *)resize( 0p, align, size );
    279         test_base( ip, size, align );
    280         test_use( ip );
    281         free( ip );
    282 
    283         ip = (int *)calloc( dim, elemSize );
    284         ip = (int *)realloc( ip, libAlign, size / 2 );
    285         test_base( ip, size / 2, libAlign );
    286         test_fill( ip, 0, size / 2, '\0' );
    287         test_use( ip );
    288         free( ip );
    289 
    290         ip = (int *)cmemalign( align, dim, elemSize );
    291         ip = (int *)realloc( ip, align, size / 2 );
    292         test_base( ip, size / 2, align );
    293         test_fill( ip, 0, size / 2, '\0' );
    294         test_use( ip );
    295         free( ip );
    296 
    297         ip = (int *)calloc( dim, elemSize );
    298         ip = (int *)realloc( ip, align, size / 4 );
    299         test_base( ip, size / 4, align );
    300         test_fill( ip, 0, size / 4, '\0' );
    301         test_use( ip );
    302         free( ip );
    303 
    304         ip = (int *)calloc( dim, elemSize );
    305         ip = (int *)realloc( ip, libAlign, size * 4 );
    306         test_base( ip, size * 4, libAlign );
    307         test_fill( ip, 0, size * 4, '\0' );
    308         test_use( ip );
    309         free( ip );
    310 
    311         ip = (int *)calloc( dim, elemSize );
    312         ip = (int *)realloc( ip, align, 0 );
    313         test_base( ip, 0, libAlign );
    314         test_use( ip );
    315         free( ip );
    316 
    317         free( 0p );                                                                                     // sanity check
    318         free( NULL );                                                                           // sanity check
    319 
    320         if (tests_failed == 0) sout | "PASSED C malloc tests" | nl | nl;
    321         else sout | "failed C malloc tests" | tests_failed | tests_total | nl | nl;
     66        ip = (int *) (void *) malloc( size );
     67        test_base(ip, size, libAlign);
     68        test_use(ip);
     69        free(ip);
     70
     71        ip = (int *) (void *) malloc( 0 );
     72        test_base(ip, 0, libAlign);
     73        test_use(ip);
     74        free(ip);
     75
     76        ip = (int *) (void *) aalloc( dim, elemSize );
     77        test_base(ip, size, libAlign);
     78        test_use(ip);
     79        free(ip);
     80
     81        ip = (int *) (void *) aalloc( 0, elemSize );
     82        test_base(ip, 0, libAlign);
     83        test_use(ip);
     84        free(ip);
     85
     86        ip = (int *) (void *) aalloc( dim, 0 );
     87        test_base(ip, 0, libAlign);
     88        test_use(ip);
     89        free(ip);
     90
     91        ip = (int *) (void *) aalloc( 0, 0 );
     92        test_base(ip, 0, libAlign);
     93        test_use(ip);
     94        free(ip);
     95
     96        ip = (int *) (void *) calloc( dim, elemSize );
     97        test_base(ip, size, libAlign);
     98        test_fill(ip, 0, size, '\0');
     99        test_use(ip);
     100        free(ip);
     101
     102        ip = (int *) (void *) calloc( 0, elemSize );
     103        test_base(ip, 0, libAlign);
     104        test_fill(ip, 0, 0, '\0');
     105        test_use(ip);
     106        free(ip);
     107
     108        ip = (int *) (void *) calloc( dim, 0 );
     109        test_base(ip, 0, libAlign);
     110        test_fill(ip, 0, 0, '\0');
     111        test_use(ip);
     112        free(ip);
     113
     114        ip = (int *) (void *) malloc( size );
     115        ip = (int *) (void *) resize( (void *) ip, size / 4 );
     116        test_base(ip, size / 4, libAlign);
     117        test_use(ip);
     118        free(ip);
     119
     120        ip = (int *) (void *) malloc( size );
     121        ip = (int *) (void *) resize( (void *) ip, size * 4 );
     122        test_base(ip, size * 4, libAlign);
     123        test_use(ip);
     124        free(ip);
     125
     126        ip = (int *) (void *) malloc( size );
     127        ip = (int *) (void *) resize( (void *) ip, 0 );
     128        test_base(ip, 0, libAlign);
     129        test_use(ip);
     130        free(ip);
     131
     132        ip = (int *) (void *) resize( NULL, size );
     133        test_base(ip, size, libAlign);
     134        test_use(ip);
     135        free(ip);
     136
     137        ip = (int *) (void *) resize( 0p, size );
     138        test_base(ip, size, libAlign);
     139        test_use(ip);
     140        free(ip);
     141
     142        ip = (int *) (void *) calloc( dim, elemSize );
     143        ip = (int *) (void *) realloc( (void *) ip, size / 4 );
     144        test_base(ip, size / 4, libAlign);
     145        test_fill(ip, 0, size / 4, '\0');
     146        test_use(ip);
     147        free(ip);
     148
     149        ip = (int *) (void *) calloc( dim, elemSize );
     150        ip = (int *) (void *) realloc( (void *) ip, size * 4 );
     151        test_base(ip, size * 4, libAlign);
     152        test_fill(ip, 0, size * 4, '\0');
     153        test_use(ip);
     154        free(ip);
     155
     156        ip = (int *) (void *) calloc( dim, elemSize );
     157        ip = (int *) (void *) realloc( (void *) ip, 0 );
     158        test_base(ip, 0, libAlign);
     159        test_use(ip);
     160        free(ip);
     161
     162        ip = (int *) (void *) realloc( NULL, size  );
     163        test_base(ip, size , libAlign);
     164        test_use(ip);
     165        free(ip);
     166
     167        ip = (int *) (void *) realloc( 0p, size );
     168        test_base(ip, size, libAlign);
     169        test_use(ip);
     170        free(ip);
     171
     172        ip = (int *) (void *) memalign( align, size );
     173        test_base(ip, size, align);
     174        test_use(ip);
     175        free(ip);
     176
     177        ip = (int *) (void *) memalign( align, 0 );
     178        test_base(ip, 0, libAlign);
     179        test_use(ip);
     180        free(ip);
     181
     182        ip = (int *) (void *) amemalign( align, dim, elemSize );
     183        test_base(ip, size, align);
     184        test_use(ip);
     185        free(ip);
     186
     187        ip = (int *) (void *) amemalign( align, 0, elemSize );
     188        test_base(ip, 0, libAlign);
     189        test_use(ip);
     190        free(ip);
     191
     192        ip = (int *) (void *) amemalign( align, dim, 0 );
     193        test_base(ip, 0, libAlign);
     194        test_use(ip);
     195        free(ip);
     196
     197        ip = (int *) (void *) cmemalign( align, dim, elemSize );
     198        test_base(ip, size, align);
     199        test_fill(ip, 0, size, '\0');
     200        test_use(ip);
     201        free(ip);
     202
     203        ip = (int *) (void *) cmemalign( align, 0, elemSize );
     204        test_base(ip, 0, libAlign);
     205        test_use(ip);
     206        free(ip);
     207
     208        ip = (int *) (void *) cmemalign( align, dim, 0 );
     209        test_base(ip, 0, libAlign);
     210        test_use(ip);
     211        free(ip);
     212
     213        ip = (int *) (void *) aligned_alloc( align, size );
     214        test_base(ip, size, align);
     215        test_use(ip);
     216        free(ip);
     217
     218        ip = (int *) (void *) aligned_alloc( align, 0 );
     219        test_base(ip, 0, libAlign);
     220        test_use(ip);
     221        free(ip);
     222
     223        (int) posix_memalign( (void **) &ip, align, size );
     224        test_base(ip, size, align);
     225        test_use(ip);
     226        free(ip);
     227
     228        (int) posix_memalign( (void **) &ip, align, 0 );
     229        test_base(ip, 0, libAlign);
     230        test_use(ip);
     231        free(ip);
     232
     233        ip = (int *) (void *) valloc( size );
     234        test_base(ip, size, getpagesize());
     235        test_use(ip);
     236        free(ip);
     237
     238        ip = (int *) (void *) valloc( 0 );
     239        test_base(ip, 0, libAlign);
     240        test_use(ip);
     241        free(ip);
     242
     243        ip = (int *) (void *) pvalloc( getpagesize() * 3 / 2 );
     244        test_base(ip, getpagesize() * 2, getpagesize());
     245        test_use(ip);
     246        free(ip);
     247
     248        ip = (int *) (void *) pvalloc( 0 );
     249        test_base(ip, 0, libAlign);
     250        test_use(ip);
     251        free(ip);
     252
     253        ip = (int *) (void *) malloc( size );
     254        ip = (int *) (void *) resize( (void *) ip, libAlign, size / 2 );
     255        test_base(ip, size / 2, libAlign);
     256        test_use(ip);
     257        free(ip);
     258
     259        ip = (int *) (void *) aligned_alloc( align, size );
     260        ip = (int *) (void *) resize( (void *) ip, align, size / 2 );
     261        test_base(ip, size / 2, align);
     262        test_use(ip);
     263        free(ip);
     264
     265        ip = (int *) (void *) malloc( size );
     266        ip = (int *) (void *) resize( (void *) ip, align, size / 4 );
     267        test_base(ip, size / 4, align);
     268        test_use(ip);
     269        free(ip);
     270
     271        ip = (int *) (void *) malloc( size );
     272        ip = (int *) (void *) resize( (void *) ip, align, 0 );
     273        test_base(ip, 0, libAlign);
     274        test_use(ip);
     275        free(ip);
     276
     277        ip = (int *) (void *) resize( NULL, align, size );
     278        test_base(ip, size, align);
     279        test_use(ip);
     280        free(ip);
     281
     282        ip = (int *) (void *) resize( 0p, align, size );
     283        test_base(ip, size, align);
     284        test_use(ip);
     285        free(ip);
     286
     287        ip = (int *) (void *) calloc( dim, elemSize );
     288        ip = (int *) (void *) realloc( (void *) ip, libAlign, size / 2 );
     289        test_base(ip, size / 2, libAlign);
     290        test_fill(ip, 0, size / 2, '\0');
     291        test_use(ip);
     292        free(ip);
     293
     294        ip = (int *) (void *) cmemalign( align, dim, elemSize );
     295        ip = (int *) (void *) realloc( (void *) ip, align, size / 2 );
     296        test_base(ip, size / 2, align);
     297        test_fill(ip, 0, size / 2, '\0');
     298        test_use(ip);
     299        free(ip);
     300
     301        ip = (int *) (void *) calloc( dim, elemSize );
     302        ip = (int *) (void *) realloc( (void *) ip, align, size / 4 );
     303        test_base(ip, size / 4, align);
     304        test_fill(ip, 0, size / 4, '\0');
     305        test_use(ip);
     306        free(ip);
     307
     308        ip = (int *) (void *) calloc( dim, elemSize );
     309        ip = (int *) (void *) realloc( (void *) ip, 0, size * 4 );
     310        test_base(ip, size * 4, libAlign);
     311        test_fill(ip, 0, size * 4, '\0');
     312        test_use(ip);
     313        free(ip);
     314
     315        ip = (int *) (void *) calloc( dim, elemSize );
     316        ip = (int *) (void *) realloc( (void *) ip, align, 0 );
     317        test_base(ip, 0, libAlign);
     318        test_use(ip);
     319        free(ip);
     320
     321        free( 0p ); // sanity check
     322        free( NULL ); // sanity check
     323
     324        if (tests_failed == 0) printf("PASSED C malloc tests\n\n");
     325        else printf("failed C malloc tests : %d/%d\n\n", tests_failed, tests_total);
    322326
    323327        // testing CFA malloc
     
    327331
    328332        ip = malloc();
    329         test_base( ip, elemSize, libAlign );
    330         test_use( ip );
    331         free( ip );
     333        test_base(ip, elemSize, libAlign);
     334        test_use(ip);
     335        free(ip);
    332336
    333337        ip = aalloc( dim );
    334         test_base( ip, size, libAlign );
    335         test_use( ip );
    336         free( ip );
     338        test_base(ip, size, libAlign);
     339        test_use(ip);
     340        free(ip);
    337341
    338342        ip = aalloc( 0 );
    339         test_base( ip, 0, libAlign );
    340         test_use( ip );
    341         free( ip );
     343        test_base(ip, 0, libAlign);
     344        test_use(ip);
     345        free(ip);
    342346
    343347        ip = calloc( dim );
    344         test_base( ip, size, libAlign );
    345         test_fill( ip, 0, size, '\0' );
    346         test_use( ip );
    347         free( ip );
     348        test_base(ip, size, libAlign);
     349        test_fill(ip, 0, size, '\0');
     350        test_use(ip);
     351        free(ip);
    348352
    349353        ip = calloc( 0 );
    350         test_base( ip, 0, libAlign );
    351         test_use( ip );
    352         free( ip );
     354        test_base(ip, 0, libAlign);
     355        test_use(ip);
     356        free(ip);
    353357
    354358        ip = aalloc( dim );
    355359        ip = resize( ip, size / 4 );
    356         test_base( ip, size / 4, libAlign );
    357         test_use( ip );
    358         free( ip );
     360        test_base(ip, size / 4, libAlign);
     361        test_use(ip);
     362        free(ip);
    359363
    360364        ip = aalloc( dim );
    361365        ip = resize( ip, size * 4 );
    362         test_base( ip, size * 4, libAlign );
    363         test_use( ip );
    364         free( ip );
     366        test_base(ip, size * 4, libAlign);
     367        test_use(ip);
     368        free(ip);
    365369
    366370        ip = aalloc( dim );
    367371        ip = resize( ip, 0 );
    368         test_base( ip, 0, libAlign );
    369         test_use( ip );
    370         free( ip );
    371 
    372         ip = resize( 0p, size );
    373         test_base( ip, size, libAlign );
    374         test_use( ip );
    375         free( ip );
    376 
    377         ip = resize( 0p, size );
    378         test_base( ip, size, libAlign );
    379         test_use( ip );
    380         free( ip );
     372        test_base(ip, 0, libAlign);
     373        test_use(ip);
     374        free(ip);
     375
     376        ip = resize( (int*)0p, size );
     377        test_base(ip, size, libAlign);
     378        test_use(ip);
     379        free(ip);
     380
     381        ip = resize( (int*)0p, size );
     382        test_base(ip, size, libAlign);
     383        test_use(ip);
     384        free(ip);
    381385
    382386        ip = calloc( dim );
    383387        ip = realloc( ip, size / 4 );
    384         test_base( ip, size / 4, libAlign );
    385         test_fill( ip, 0, size / 4, '\0' );
    386         test_use( ip );
    387         free( ip );
     388        test_base(ip, size / 4, libAlign);
     389        test_fill(ip, 0, size / 4, '\0');
     390        test_use(ip);
     391        free(ip);
    388392
    389393        ip = calloc( dim );
    390394        ip = realloc( ip, size * 4 );
    391         test_base( ip, size * 4, libAlign );
    392         test_fill( ip, 0, size, '\0' );
    393         test_use( ip );
    394         free( ip );
     395        test_base(ip, size * 4, libAlign);
     396        test_fill(ip, 0, size, '\0');
     397        test_use(ip);
     398        free(ip);
    395399
    396400        ip = calloc( dim );
    397401        ip = realloc( ip, 0 );
    398         test_base( ip, 0, libAlign );
    399         test_use( ip );
    400         free( ip );
    401 
    402         ip = realloc( 0p, size );
    403         test_base( ip, size , libAlign );
    404         test_use( ip );
    405         free( ip );
    406 
    407         ip = realloc( 0p, size );
    408         test_base( ip, size, libAlign );
    409         test_use( ip );
    410         free( ip );
     402        test_base(ip, 0, libAlign);
     403        test_use(ip);
     404        free(ip);
     405
     406        ip = realloc( (int*)0p, size );
     407        test_base(ip, size , libAlign);
     408        test_use(ip);
     409        free(ip);
     410
     411        ip = realloc( (int*)0p, size );
     412        test_base(ip, size, libAlign);
     413        test_use(ip);
     414        free(ip);
    411415
    412416        ip = memalign( align );
    413         test_base( ip, elemSize, align );
    414         test_use( ip );
    415         free( ip );
     417        test_base(ip, elemSize, align);
     418        test_use(ip);
     419        free(ip);
    416420
    417421        ip = amemalign( align, dim );
    418         test_base( ip, size, align );
    419         test_use( ip );
    420         free( ip );
     422        test_base(ip, size, align);
     423        test_use(ip);
     424        free(ip);
    421425
    422426        ip = amemalign( align, 0 );
    423         test_base( ip, 0, libAlign );
    424         test_use( ip );
    425         free( ip );
     427        test_base(ip, 0, libAlign);
     428        test_use(ip);
     429        free(ip);
    426430
    427431        ip = cmemalign( align, dim );
    428         test_base( ip, size, align );
    429         test_fill( ip, 0, size, '\0' );
    430         test_use( ip );
    431         free( ip );
     432        test_base(ip, size, align);
     433        test_fill(ip, 0, size, '\0');
     434        test_use(ip);
     435        free(ip);
    432436
    433437        ip = cmemalign( align, 0 );
    434         test_base( ip, 0, libAlign );
    435         test_use( ip );
    436         free( ip );
     438        test_base(ip, 0, libAlign);
     439        test_use(ip);
     440        free(ip);
    437441
    438442        ip = aligned_alloc( align );
    439         test_base( ip, elemSize, align );
    440         test_use( ip );
    441         free( ip );
    442 
    443         posix_memalign( (int **) &ip, align );
    444         test_base( ip, elemSize, align );
    445         test_use( ip );
    446         free( ip );
     443        test_base(ip, elemSize, align);
     444        test_use(ip);
     445        free(ip);
     446
     447        (int) posix_memalign( (int **) &ip, align );
     448        test_base(ip, elemSize, align);
     449        test_use(ip);
     450        free(ip);
    447451
    448452        ip = valloc();
    449         test_base( ip, elemSize, getpagesize() );
    450         test_use( ip );
    451         free( ip );
     453        test_base(ip, elemSize, getpagesize());
     454        test_use(ip);
     455        free(ip);
    452456
    453457        ip = pvalloc();
    454         test_base( ip, getpagesize(), getpagesize() );
    455         test_use( ip );
    456         free( ip );
    457 
    458         if (tests_failed == 0) sout | "PASSED CFA malloc tests" | nl | nl;
    459         else sout | "failed CFA malloc tests" | tests_failed | tests_total | nl | nl;
     458        test_base(ip, getpagesize(), getpagesize());
     459        test_use(ip);
     460        free(ip);
     461
     462        if (tests_failed == 0) printf("PASSED CFA malloc tests\n\n");
     463        else printf("failed CFA malloc tests : %d/%d\n\n", tests_failed, tests_total);
    460464
    461465        // testing CFA malloc with aligned struct
     
    467471
    468472        tp = malloc();
    469         test_base( tp, elemSize, tAlign );
    470         test_use( tp );
    471         free( tp );
     473        test_base(tp, elemSize, tAlign );
     474        test_use(tp);
     475        free(tp);
    472476
    473477        tp = aalloc( dim );
    474         test_base( tp, size, tAlign );
    475         test_use( tp );
    476         free( tp );
     478        test_base(tp, size, tAlign );
     479        test_use(tp);
     480        free(tp);
    477481
    478482        tp = aalloc( 0 );
    479         test_base( tp, 0, libAlign );
    480         test_use( tp );
    481         free( tp );
     483        test_base(tp, 0, libAlign);
     484        test_use(tp);
     485        free(tp);
    482486
    483487        tp = calloc( dim );
    484         test_base( tp, size, tAlign );
    485         test_fill( tp, 0, size, '\0' );
    486         test_use( tp );
    487         free( tp );
     488        test_base(tp, size, tAlign );
     489        test_fill(tp, 0, size, '\0');
     490        test_use(tp);
     491        free(tp);
    488492
    489493        tp = calloc( 0 );
    490         test_base( tp, 0, libAlign );
    491         test_use( tp );
    492         free( tp );
     494        test_base(tp, 0, libAlign);
     495        test_use(tp);
     496        free(tp);
    493497
    494498        tp = aalloc( dim );
    495499        tp = resize( tp, size / 4 );
    496         test_base( tp, size / 4, tAlign );
    497         test_use( tp );
    498         free( tp );
     500        test_base(tp, size / 4, tAlign );
     501        test_use(tp);
     502        free(tp);
    499503
    500504        tp = malloc();
    501505        tp = resize( tp, size * 4 );
    502         test_base( tp, size * 4, tAlign );
    503         test_use( tp );
    504         free( tp );
     506        test_base(tp, size * 4, tAlign );
     507        test_use(tp);
     508        free(tp);
    505509
    506510        tp = aalloc( dim );
    507511        tp = resize( tp, 0 );
    508         test_base( tp, 0, libAlign );
    509         test_use( tp );
    510         free( tp );
     512        test_base(tp, 0, libAlign);
     513        test_use(tp);
     514        free(tp);
    511515
    512516        tp = resize( (T1*)0p, size );
    513         test_base( tp, size, tAlign );
    514         test_use( tp );
    515         free( tp );
     517        test_base(tp, size, tAlign );
     518        test_use(tp);
     519        free(tp);
    516520
    517521        tp = resize( (T1*)0p, size );
    518         test_base( tp, size, tAlign );
    519         test_use( tp );
    520         free( tp );
     522        test_base(tp, size, tAlign );
     523        test_use(tp);
     524        free(tp);
    521525
    522526        tp = calloc( dim );
    523527        tp = realloc( tp, size / 4 );
    524         test_base( tp, size / 4, tAlign );
    525         test_fill( tp, 0, size / 4, '\0' );
    526         test_use( tp );
    527         free( tp );
     528        test_base(tp, size / 4, tAlign );
     529        test_fill(tp, 0, size / 4, '\0');
     530        test_use(tp);
     531        free(tp);
    528532
    529533        tp = calloc( dim );
    530534        tp = realloc( tp, size * 4 );
    531         test_base( tp, size * 4, tAlign );
    532         test_fill( tp, 0, size, '\0' );
    533         test_use( tp );
    534         free( tp );
     535        test_base(tp, size * 4, tAlign );
     536        test_fill(tp, 0, size, '\0');
     537        test_use(tp);
     538        free(tp);
    535539
    536540        tp = calloc( dim );
    537541        tp = realloc( tp, 0 );
    538         test_base( tp, 0, libAlign );
    539         test_use( tp );
    540         free( tp );
     542        test_base(tp, 0, libAlign);
     543        test_use(tp);
     544        free(tp);
    541545
    542546        tp = realloc( (T1*)0p, size  );
    543         test_base( tp, size , tAlign );
    544         test_use( tp );
    545         free( tp );
     547        test_base(tp, size , tAlign );
     548        test_use(tp);
     549        free(tp);
    546550
    547551        tp = realloc( (T1*)0p, size );
    548         test_base( tp, size, tAlign );
    549         test_use( tp );
    550         free( tp );
     552        test_base(tp, size, tAlign );
     553        test_use(tp);
     554        free(tp);
    551555
    552556        tp = memalign( align );
    553         test_base( tp, elemSize, align );
    554         test_use( tp );
    555         free( tp );
     557        test_base(tp, elemSize, align);
     558        test_use(tp);
     559        free(tp);
    556560
    557561        tp = amemalign( align, dim );
    558         test_base( tp, size, align );
    559         test_use( tp );
    560         free( tp );
     562        test_base(tp, size, align);
     563        test_use(tp);
     564        free(tp);
    561565
    562566        tp = amemalign( align, 0 );
    563         test_base( tp, 0, libAlign );
    564         test_use( tp );
    565         free( tp );
     567        test_base(tp, 0, libAlign);
     568        test_use(tp);
     569        free(tp);
    566570
    567571        tp = cmemalign( align, dim );
    568         test_base( tp, size, align );
    569         test_fill( tp, 0, size, '\0' );
    570         test_use( tp );
    571         free( tp );
     572        test_base(tp, size, align);
     573        test_fill(tp, 0, size, '\0');
     574        test_use(tp);
     575        free(tp);
    572576
    573577        tp = cmemalign( align, 0 );
    574         test_base( tp, 0, libAlign );
    575         test_use( tp );
    576         free( tp );
     578        test_base(tp, 0, libAlign);
     579        test_use(tp);
     580        free(tp);
    577581
    578582        tp = aligned_alloc( align );
    579         test_base( tp, elemSize, align );
    580         test_use( tp );
    581         free( tp );
    582 
    583         posix_memalign( (T1 **)&tp, align );
    584         test_base( tp, elemSize, align );
    585         test_use( tp );
    586         free( tp );
     583        test_base(tp, elemSize, align);
     584        test_use(tp);
     585        free(tp);
     586
     587        (int) posix_memalign( (T1 **) &tp, align );
     588        test_base(tp, elemSize, align);
     589        test_use(tp);
     590        free(tp);
    587591
    588592        tp = valloc();
    589         test_base( tp, elemSize, getpagesize() );
    590         test_use( tp );
    591         free( tp );
     593        test_base(tp, elemSize, getpagesize());
     594        test_use(tp);
     595        free(tp);
    592596
    593597        tp = pvalloc();
    594         test_base( tp, getpagesize(), getpagesize() );
    595         test_use( tp );
    596         free( tp );
    597 
    598         if ( tests_failed == 0 ) sout | "PASSED CFA malloc tests (aligned struct)" | nl | nl;
    599         else sout | "failed CFA malloc tests (aligned struct)" | tests_failed | tests_total | nl | nl;
     598        test_base(tp, getpagesize(), getpagesize());
     599        test_use(tp);
     600        free(tp);
     601
     602        if (tests_failed == 0) printf("PASSED CFA malloc tests (aligned struct)\n\n");
     603        else printf("failed CFA malloc tests (aligned struct) : %d/%d\n\n", tests_failed, tests_total);
     604
     605        return 0;
    600606}
    601607
Note: See TracChangeset for help on using the changeset viewer.