Ignore:
Timestamp:
Dec 28, 2022, 12:49:41 PM (16 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master
Children:
d9585291
Parents:
ea2ed3a
Message:

change spinlock atomics to ATOMIC_ACQUIRE/RELEASE, increase alignment of FreeHeader? elements, change counter types from int64_t to ptrdiff_t/size_t, fix bug allocating heapManager arrays, move return push counters

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    rea2ed3a r8ee54963  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 30 20:56:20 2022
    13 // Update Count     : 1584
     12// Last Modified On : Wed Dec 28 12:37:38 2022
     13// Update Count     : 1597
    1414//
    1515
     
    1717#include <string.h>                                                                             // memset, memcpy
    1818#include <limits.h>                                                                             // ULONG_MAX
    19 #include <stdlib.h>                                                                             // EXIT_FAILURE
    2019#include <errno.h>                                                                              // errno, ENOMEM, EINVAL
    21 #include <unistd.h>                                                                             // STDERR_FILENO, sbrk, sysconf
    22 #include <malloc.h>                                                                             // memalign, malloc_usable_size
     20#include <unistd.h>                                                                             // STDERR_FILENO, sbrk, sysconf, write
    2321#include <sys/mman.h>                                                                   // mmap, munmap
    2422extern "C" {
     
    2624} // extern "C"
    2725
     26#include "heap.hfa"
    2827#include "bits/align.hfa"                                                               // libAlign
    2928#include "bits/defs.hfa"                                                                // likely, unlikely
     
    140139#endif
    141140
    142 typedef volatile uintptr_t SpinLock_t CALIGN;                   // aligned addressable word-size
     141typedef volatile uintptr_t SpinLock_t;
    143142
    144143static inline __attribute__((always_inline)) void lock( volatile SpinLock_t & slock ) {
     
    147146
    148147        for ( unsigned int i = 1;; i += 1 ) {
    149           if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_SEQ_CST ) == 0 ) break; // Fence
     148          if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_ACQUIRE ) == 0 ) break; // Fence
    150149                for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause(); // exponential spin
    151150                spin += spin;                                                                   // powers of 2
     
    156155
    157156static inline __attribute__((always_inline)) void unlock( volatile SpinLock_t & slock ) {
    158         __atomic_clear( &slock, __ATOMIC_SEQ_CST );                     // Fence
     157        __atomic_clear( &slock, __ATOMIC_RELEASE );                     // Fence
    159158} // spin_unlock
    160159
     
    261260        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    262261
    263         struct __attribute__(( aligned (8) )) FreeHeader {
    264                 size_t blockSize __attribute__(( aligned(8) )); // size of allocations on this list
     262        struct CALIGN FreeHeader {
     263                size_t blockSize CALIGN;                                                // size of allocations on this list
    265264                #ifdef OWNERSHIP
    266265                #ifdef RETURNSPIN
     
    284283
    285284        #ifdef __CFA_DEBUG__
    286         int64_t allocUnfreed;                                                           // running total of allocations minus frees; can be negative
     285        ptrdiff_t allocUnfreed;                                                         // running total of allocations minus frees; can be negative
    287286        #endif // __CFA_DEBUG__
    288287
     
    369368// Thread-local storage is allocated lazily when the storage is accessed.
    370369static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing
    371 static __thread Heap * volatile heapManager CALIGN TLSMODEL;
     370static __thread Heap * heapManager CALIGN TLSMODEL;
    372371static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing
    373372
     
    443442                // 12K ~= 120K byte superblock.  Where 128-heap superblock handles a medium sized multi-processor server.
    444443                size_t remaining = heapManagersStorageEnd - heapManagersStorage; // remaining free heaps in superblock
    445                 if ( ! heapManagersStorage || remaining != 0 ) {
     444                if ( ! heapManagersStorage || remaining == 0 ) {
    446445                        // Each block of heaps is a multiple of the number of cores on the computer.
    447446                        int HeapDim = get_nprocs();                                     // get_nprocs_conf does not work
     
    562561                // allocUnfreed is set to 0 when a heap is created and it accumulates any unfreed storage during its multiple thread
    563562                // usages.  At the end, add up each heap allocUnfreed value across all heaps to get the total unfreed storage.
    564                 int64_t allocUnfreed = 0;
     563                ptrdiff_t allocUnfreed = 0;
    565564                for ( Heap * heap = heapMaster.heapManagersList; heap; heap = heap->nextHeapManager ) {
    566565                        allocUnfreed += heap->allocUnfreed;
     
    572571                        char helpText[512];
    573572                        __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    574                                                                                 "CFA warning (UNIX pid:%ld) : program terminating with %ju(0x%jx) bytes of storage allocated but not freed.\n"
     573                                                                                "CFA warning (UNIX pid:%ld) : program terminating with %td(%#tx) bytes of storage allocated but not freed.\n"
    575574                                                                                "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    576575                                                                                (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
     
    950949                block = freeHead->freeList;                                             // remove node from stack
    951950                if ( unlikely( block == 0p ) ) {                                // no free block ?
    952                         // Freelist for this size is empty, so check return list (OWNERSHIP), carve it out of the heap, if there
     951                        // Freelist for this size is empty, so check return list (OWNERSHIP), or carve it out of the heap if there
    953952                        // is enough left, or get some more heap storage and carve it off.
    954953                        #ifdef OWNERSHIP
     
    11151114                        while ( ! __atomic_compare_exchange_n( &freeHead->returnList, &header->kind.real.next, (Heap.Storage *)header,
    11161115                                                                                                   false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) );
     1116
     1117                        #ifdef __STATISTICS__
     1118                        stats.return_pushes += 1;
     1119                        stats.return_storage_request += rsize;
     1120                        stats.return_storage_alloc += size;
     1121                        #endif // __STATISTICS__
    11171122                        #endif // RETURNSPIN
    11181123                } // if
     
    11251130                freeHead->freeList = (Heap.Storage *)header;
    11261131                #endif // ! OWNERSHIP
    1127 
    1128                 #ifdef __U_STATISTICS__
    1129                 stats.return_pushes += 1;
    1130                 stats.return_storage_request += rsize;
    1131                 stats.return_storage_alloc += size;
    1132                 #endif // __U_STATISTICS__
    11331132
    11341133                // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
     
    11801179
    11811180#ifdef __STATISTICS__
    1182 static void incCalls( intptr_t statName ) libcfa_nopreempt {
     1181static void incCalls( size_t statName ) libcfa_nopreempt {
    11831182        heapManager->stats.counters[statName].calls += 1;
    11841183} // incCalls
    11851184
    1186 static void incZeroCalls( intptr_t statName ) libcfa_nopreempt {
     1185static void incZeroCalls( size_t statName ) libcfa_nopreempt {
    11871186        heapManager->stats.counters[statName].calls_0 += 1;
    11881187} // incZeroCalls
     
    14561455        // 0p, no operation is performed.
    14571456        void free( void * addr ) libcfa_public {
    1458 //              verify( heapManager );
    1459 
    14601457          if ( unlikely( addr == 0p ) ) {                                       // special case
    14611458                        #ifdef __STATISTICS__
Note: See TracChangeset for help on using the changeset viewer.