Changeset d99a716 for libcfa/src


Ignore:
Timestamp:
Jan 4, 2023, 1:44:19 PM (16 months ago)
Author:
caparsons <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
339e30a, a14926b
Parents:
0348fd8 (diff), 66a89e7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
libcfa/src
Files:
2 edited

Legend:

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

    r0348fd8 rd99a716  
    1010// Created On       : Fri Jan 14 07:18:11 2022
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 11 18:43:58 2022
    13 // Update Count     : 171
     12// Last Modified On : Thu Dec 22 20:54:22 2022
     13// Update Count     : 178
    1414//
    1515
    1616#pragma once
    1717
    18 #include <stdint.h>
     18#include <stdint.h>                                                                             // uintXX_t
    1919
    2020#define GLUE2( x, y ) x##y
     
    2424#ifdef __x86_64__                                                                               // 64-bit architecture
    2525        // 64-bit generators
    26         #define LEHMER64
     26        //#define LEHMER64
    2727        //#define XORSHIFT_12_25_27
    28         //#define XOSHIRO256PP
     28        #define XOSHIRO256PP
    2929        //#define KISS_64
    3030
    3131        // 32-bit generators
    32         #define XORSHIFT_6_21_7
    33         //#define XOSHIRO128PP
     32        //#define XORSHIFT_6_21_7
     33        #define XOSHIRO128PP
    3434#else                                                                                                   // 32-bit architecture
    3535        // 64-bit generators
    36         #define XORSHIFT_13_7_17
     36        //#define XORSHIFT_13_7_17
     37        #define XOSHIRO256PP
    3738
    3839        // 32-bit generators
    39         #define XORSHIFT_6_21_7
     40        //#define XORSHIFT_6_21_7
     41        #define XOSHIRO128PP
    4042#endif // __x86_64__
    4143
     
    4749#define PRNG_NAME_64 xoshiro256pp
    4850#define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t)
    49 typedef struct PRNG_STATE_64_T { uint64_t s[4]; } PRNG_STATE_64_T;
     51typedef struct PRNG_STATE_64_T { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;
    5052#endif // XOSHIRO256PP
    5153
     
    5355#define PRNG_NAME_32 xoshiro128pp
    5456#define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t)
    55 typedef struct PRNG_STATE_32_T { uint32_t s[4]; } PRNG_STATE_32_T;
     57typedef struct PRNG_STATE_32_T { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;
    5658#endif // XOSHIRO128PP
    5759
     
    110112
    111113// ALL PRNG ALGORITHMS ARE OPTIMIZED SO THAT THE PRNG LOGIC CAN HAPPEN IN PARALLEL WITH THE USE OF THE RESULT.
    112 // Therefore, the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the
    113 // first random value.
     114// Specifically, the current random state is copied for returning, before computing the next value.  As a consequence,
     115// the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the first random
     116// value.
     117
    114118
    115119#ifdef __cforall                                                                                // don't include in C code (invoke.h)
     
    126130
    127131#ifndef XOSHIRO256PP
    128 typedef struct xoshiro256pp_t { uint64_t s[4]; } xoshiro256pp_t;
     132typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
    129133#endif // ! XOSHIRO256PP
    130134
    131135static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) {
    132         inline uint64_t rotl(const uint64_t x, int k) {
     136        inline uint64_t rotl( const uint64_t x, int k ) {
    133137                return (x << k) | (x >> (64 - k));
    134138        } // rotl
    135139
    136         const uint64_t result = rotl( s[0] + s[3], 23 ) + s[0];
    137         const uint64_t t = s[1] << 17;
    138 
    139         s[2] ^= s[0];
    140         s[3] ^= s[1];
    141         s[1] ^= s[2];
    142         s[0] ^= s[3];
    143         s[2] ^= t;
    144         s[3] = rotl( s[3], 45 );
     140        const uint64_t result = rotl( s0 + s3, 23 ) + s0;
     141        const uint64_t t = s1 << 17;
     142
     143        s2 ^= s0;
     144        s3 ^= s1;
     145        s1 ^= s2;
     146        s0 ^= s3;
     147        s2 ^= t;
     148        s3 = rotl( s3, 45 );
    145149        return result;
    146150} // xoshiro256pp
    147151
    148 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state,  uint64_t seed ) {
    149         state = (xoshiro256pp_t){ {seed, seed, seed, seed} };
     152static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) {
     153        state = (xoshiro256pp_t){ seed, seed, seed, seed };
    150154        xoshiro256pp( state );
    151155} // xoshiro256pp_set_seed
     
    161165
    162166#ifndef XOSHIRO128PP
    163 typedef struct xoshiro128pp_t { uint32_t s[4]; } xoshiro128pp_t;
     167typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
    164168#endif // ! XOSHIRO128PP
    165169
     
    169173        } // rotl
    170174
    171         const uint32_t result = rotl( s[0] + s[3], 7 ) + s[0];
    172         const uint32_t t = s[1] << 9;
    173 
    174         s[2] ^= s[0];
    175         s[3] ^= s[1];
    176         s[1] ^= s[2];
    177         s[0] ^= s[3];
    178         s[2] ^= t;
    179         s[3] = rotl( s[3], 11 );
     175        const uint32_t result = rotl( s0 + s3, 7 ) + s0;
     176        const uint32_t t = s1 << 9;
     177
     178        s2 ^= s0;
     179        s3 ^= s1;
     180        s1 ^= s2;
     181        s0 ^= s3;
     182        s2 ^= t;
     183        s3 = rotl( s3, 11 );
    180184        return result;
    181185} // xoshiro128pp
    182186
    183187static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
    184         state = (xoshiro128pp_t){ {seed, seed, seed, seed} };
     188        state = (xoshiro128pp_t){ seed, seed, seed, seed };
    185189        xoshiro128pp( state );                                                          // prime
    186190} // xoshiro128pp_set_seed
    187191
    188192#ifdef __SIZEOF_INT128__
    189         // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is
    190         // returned (copied), and then compute and store the next random value.
    191193        //--------------------------------------------------
    192194        static inline uint64_t lehmer64( __uint128_t & state ) {
    193195                __uint128_t ret = state;
    194                 state *= 0xda942042e4dd58b5;
     196                state *= 0x_da94_2042_e4dd_58b5;
    195197                return ret >> 64;
    196198        } // lehmer64
    197199
    198200        static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) {
     201                // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed.
    199202                state = seed;
    200                 lehmer64( state );
     203                lehmer64( state );                                                              // prime
    201204        } // lehmer64_set_seed
    202205
     
    272275#endif // ! KISS_64
    273276
    274 static inline uint64_t kiss_64( kiss_64_t & state ) with(state) {
    275         kiss_64_t ret = state;
     277static inline uint64_t kiss_64( kiss_64_t & rs ) with(rs) {
     278        kiss_64_t ret = rs;
    276279        z = 36969 * (z & 65535) + (z >> 16);
    277280        w = 18000 * (w & 65535) + (w >> 16);
    278         jsr ^= (jsr << 17);
    279281        jsr ^= (jsr << 13);
     282        jsr ^= (jsr >> 17);
    280283        jsr ^= (jsr << 5);
    281284        jcong = 69069 * jcong + 1234567;
     
    283286} // kiss_64
    284287
    285 static inline void kiss_64_set_seed( kiss_64_t & state, uint64_t seed ) with(state) {
     288static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) {
    286289        z = 1; w = 1; jsr = 4; jcong = seed;
    287         kiss_64( state );                                                                       // prime
     290        kiss_64( rs );                                                                          // prime
    288291} // kiss_64_set_seed
    289292
     
    294297#endif // ! XORWOW
    295298
    296 static inline uint32_t xorwow( xorwow_t & state ) with(state) {
     299static inline uint32_t xorwow( xorwow_t & rs ) with(rs) {
    297300        // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs".
    298301        uint32_t ret = a + counter;
     
    312315} // xorwow
    313316
    314 static inline void xorwow_set_seed( xorwow_t & state, uint32_t seed ) {
    315         state = (xorwow_t){ seed, seed, seed, seed, 0 };
    316         xorwow( state );                                                                        // prime
     317static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) {
     318        rs = (xorwow_t){ seed, seed, seed, seed, 0 };
     319        xorwow( rs );                                                                           // prime
    317320} // xorwow_set_seed
    318321
     
    326329
    327330// Bi-directional LCG random-number generator
    328 static inline uint32_t LCGBI_fwd( uint64_t & state ) {
    329         state = (A * state + C) & (M - 1);
    330         return state >> D;
     331static inline uint32_t LCGBI_fwd( uint64_t & rs ) {
     332        rs = (A * rs + C) & (M - 1);
     333        return rs >> D;
    331334} // LCGBI_fwd
    332335
    333 static inline uint32_t LCGBI_bck( uint64_t & state ) {
    334         unsigned int r = state >> D;
    335         state = AI * (state - C) & (M - 1);
     336static inline uint32_t LCGBI_bck( uint64_t & rs ) {
     337        unsigned int r = rs >> D;
     338        rs = AI * (rs - C) & (M - 1);
    336339        return r;
    337340} // LCGBI_bck
  • libcfa/src/heap.cfa

    r0348fd8 rd99a716  
    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.