Changeset 175f9f4 for libcfa


Ignore:
Timestamp:
Jan 18, 2022, 1:16:23 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
Children:
1e8b4b49, adfd125
Parents:
21a5bfb7 (diff), 91a72ef (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
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/Makefile.am

    r21a5bfb7 r175f9f4  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Feb  3 21:27:18 2020
    14 ## Update Count     : 208
     13## Last Modified On : Thu Jan 13 17:06:27 2022
     14## Update Count     : 215
    1515###############################################################################
    1616
     
    3737# create extra forward types/declarations to reduce inclusion of library files
    3838extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c
    39         ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx > extras.cf
    40         ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> extras.cf
     39        @echo '# 2 "${@}"  // needed for error messages from this file' > ${@}
     40        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx >> ${@}
     41        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> ${@}
    4142
    4243# create forward declarations for gcc builtins
    4344gcc-builtins.cf : gcc-builtins.c ${srcdir}/prototypes.sed
    44         ${AM_V_GEN}gcc -I${srcdir} -E -P $< | sed -r -f ${srcdir}/prototypes.sed > $@
     45        @echo '# 2 "${@}"  // needed for error messages from this file' > ${@}
     46        ${AM_V_GEN}gcc -I${srcdir} -E -P $< | sed -r -f ${srcdir}/prototypes.sed >> ${@}
    4547
    4648gcc-builtins.c : ${srcdir}/builtins.def ${srcdir}/prototypes.awk ${srcdir}/sync-builtins.cf ${srcdir}/prototypes.c
    47         ${AM_V_GEN}gcc -I${srcdir} -E ${srcdir}/prototypes.c | awk -f ${srcdir}/prototypes.awk > $@
     49        ${AM_V_GEN}gcc -I${srcdir} -E ${srcdir}/prototypes.c | awk -f ${srcdir}/prototypes.awk > ${@}
    4850
    4951prelude.cfa : prelude-gen.cc
    5052        ${AM_V_GEN}${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} ${AM_CFLAGS} ${<} -o prelude-gen -Wall -Wextra -O2 -g -std=c++14
    51         @./prelude-gen > $@
     53        @./prelude-gen > ${@}
    5254        @rm ./prelude-gen
    5355
     
    5860# create forward declarations for cfa builtins
    5961builtins.cf : builtins.c @LOCAL_CFACC@
    60         ${AM_V_GEN}gcc ${AM_CFLAGS} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
     62        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
    6163        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
    6264
     
    6466
    6567bootloader.c : ${srcdir}/bootloader.cf prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACPP@
    66         ${AM_V_GEN}@CFACPP@ --prelude-dir=${builddir} -tpm ${srcdir}/bootloader.cf $@  # use src/cfa-cpp as not in lib until after install
     68        ${AM_V_GEN}@CFACPP@ --prelude-dir=${builddir} -tpm ${srcdir}/bootloader.cf ${@}  # use src/cfa-cpp as not in lib until after install
    6769
    6870maintainer-clean-local :
  • libcfa/src/bits/locks.hfa

    r21a5bfb7 r175f9f4  
    3131                // previous thread to acquire the lock
    3232                void* prev_thrd;
     33                // keep track of number of times we had to spin, just in case the number is unexpectedly huge
     34                size_t spin_count;
    3335        #endif
    3436};
     
    4850        static inline void ?{}( __spinlock_t & this ) {
    4951                this.lock = 0;
     52                #ifdef __CFA_DEBUG__
     53                        this.spin_count = 0;
     54                #endif
    5055        }
    5156
     
    7277                for ( unsigned int i = 1;; i += 1 ) {
    7378                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
     79                        #ifdef __CFA_DEBUG__
     80                                this.spin_count++;
     81                        #endif
    7482                        #ifndef NOEXPBACK
    7583                                // exponential spin
  • libcfa/src/bits/random.hfa

    r21a5bfb7 r175f9f4  
    33#include <stdint.h>
    44
     5// Pipelined to allow out-of-order overlap with reduced dependencies. Critically, return the current value, and compute
     6// and store the next value.
     7
    58//--------------------------------------------------
    69#if defined(__SIZEOF_INT128__)
    7         typedef __uint128_t __lehmer64_state_t;
    8         static inline uint64_t __lehmer64( __lehmer64_state_t & state ) {
     10        static inline uint64_t lehmer64( __uint128_t & state ) {
     11                __uint128_t ret = state;
    912                state *= 0xda942042e4dd58b5;
    10                 return state >> 64;
     13                return ret >> 64;
    1114        }
    1215
    1316//--------------------------------------------------
    14         typedef uint64_t __wyhash64_state_t;
    15         static inline uint64_t __wyhash64( __wyhash64_state_t & state ) {
     17        static inline uint64_t wyhash64( uint64_t & state ) {
    1618                state += 0x60bee2bee120fc15;
    1719                __uint128_t tmp;
     
    2527
    2628//--------------------------------------------------
    27 typedef uint64_t __xorshift64_state_t;
    28 static inline uint64_t __xorshift64( __xorshift64_state_t & state ) {
    29         uint64_t x = state;
    30         x ^= x << 13;
    31         x ^= x >> 7;
    32         x ^= x << 17;
    33         return state = x;
     29static inline uint64_t xorshift_13_7_17( uint64_t & state ) {
     30        uint64_t ret = state;
     31        state ^= state << 13;
     32        state ^= state >> 7;
     33        state ^= state << 17;
     34        return ret;
    3435}
     36
     37//--------------------------------------------------
     38static inline uint32_t xorshift_6_21_7( uint32_t & state ) {
     39        uint32_t ret = state;
     40        state ^= state << 6;
     41        state ^= state >> 21;
     42        state ^= state << 7;
     43        return ret;
     44} // xorshift_6_21_7
    3545
    3646//--------------------------------------------------
     
    3848  uint32_t a, b, c, d;
    3949  uint32_t counter;
    40 } __xorwow__state_t;
     50} xorwow__state_t;
    4151
    4252/* The state array must be initialized to not be all zero in the first four words */
    43 static inline uint32_t __xorwow( __xorwow__state_t & state ) {
     53static inline uint32_t xorwow( xorwow__state_t & state ) {
    4454        /* Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs" */
     55        uint32_t ret = state.a + state.counter;
    4556        uint32_t t = state.d;
    4657
     
    5667
    5768        state.counter += 362437;
    58         return t + state.counter;
     69        return ret;
    5970}
     71
     72//--------------------------------------------------
     73static inline uint32_t LCG( uint32_t & state ) {                // linear congruential generator
     74        uint32_t ret = state;
     75        state = 36969 * (state & 65535) + (state >> 16);        // 36969 is NOT prime! No not change it!
     76        return ret;
     77} // LCG
     78
     79//--------------------------------------------------
     80#define M  (1_l64u << 48_l64u)
     81#define A  (25214903917_l64u)
     82#define AI (18446708753438544741_l64u)
     83#define C  (11_l64u)
     84#define D  (16_l64u)
     85
     86static inline uint32_t LCGBI_fwd( uint64_t & state ) {
     87        state = (A * state + C) & (M - 1);
     88        return state >> D;
     89}
     90
     91static inline uint32_t LCGBI_bck( uint64_t & state ) {
     92        unsigned int r = state >> D;
     93        state = AI * (state - C) & (M - 1);
     94        return r;
     95}
     96
     97#undef M
     98#undef A
     99#undef AI
     100#undef C
     101#undef D
  • libcfa/src/common.hfa

    r21a5bfb7 r175f9f4  
    1 // 
     1//
    22// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // common --
    8 // 
     6//
     7// common.hfa --
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Wed Jul 11 17:54:36 2018
     
    1212// Last Modified On : Wed May  5 14:02:04 2021
    1313// Update Count     : 18
    14 // 
     14//
    1515
    1616#pragma once
  • libcfa/src/concurrency/clib/cfathread.cfa

    r21a5bfb7 r175f9f4  
    2222#include "thread.hfa"
    2323#include "time.hfa"
     24#include "stdlib.hfa"
    2425
    2526#include "cfathread.h"
     
    195196                                eevent.data.u64 = (uint64_t)active_thread();
    196197
    197                                 int id = thread_rand() % poller_cnt;
     198                                int id = prng() % poller_cnt;
    198199                                if(0 != epoll_ctl(poller_fds[id], EPOLL_CTL_ADD, fd, &eevent))
    199200                                {
  • libcfa/src/concurrency/invoke.h

    r21a5bfb7 r175f9f4  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan  6 16:37:40 2022
    13 // Update Count     : 47
     12// Last Modified On : Sun Jan  9 19:06:45 2022
     13// Update Count     : 48
    1414//
    1515
     
    211211                struct processor * last_proc;
    212212
     213                uint32_t random_state;                                                  // fast random numbers
     214
    213215                #if defined( __CFA_WITH_VERIFY__ )
    214216                        void * canary;
  • libcfa/src/concurrency/io.cfa

    r21a5bfb7 r175f9f4  
    552552                        /* paranoid */ verify( proc == __cfaabi_tls.this_processor );
    553553                        /* paranoid */ verify( ! __preemption_enabled() );
     554
     555                        return true;
    554556                }
    555557        #endif
  • libcfa/src/concurrency/kernel.cfa

    r21a5bfb7 r175f9f4  
    554554        /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd->canary );
    555555
    556         const bool local = thrd->state != Start;
    557556        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    558557
  • libcfa/src/concurrency/kernel.hfa

    r21a5bfb7 r175f9f4  
    6767                unsigned target;
    6868                unsigned last;
    69                 unsigned cnt;
    70                 unsigned long long int cutoff;
     69                signed   cpu;
    7170        } rdq;
    7271
     
    152151        volatile unsigned long long tv;
    153152        volatile unsigned long long ma;
     153};
     154
     155struct __attribute__((aligned(16))) __cache_id_t {
     156        volatile unsigned id;
    154157};
    155158
     
    164167static inline void ^?{}(__timestamp_t & this) {}
    165168
     169struct __attribute__((aligned(128))) __ready_queue_caches_t;
     170void  ?{}(__ready_queue_caches_t & this);
     171void ^?{}(__ready_queue_caches_t & this);
     172
    166173//TODO adjust cache size to ARCHITECTURE
    167 // Structure holding the relaxed ready queue
     174// Structure holding the ready queue
    168175struct __ready_queue_t {
    169176        // Data tracking the actual lanes
     
    177184                // Array of times
    178185                __timestamp_t * volatile tscs;
     186
     187                __cache_id_t * volatile caches;
    179188
    180189                // Array of stats
  • libcfa/src/concurrency/kernel/fwd.hfa

    r21a5bfb7 r175f9f4  
    7777
    7878                static inline uint64_t __tls_rand() {
     79                        return
    7980                        #if defined(__SIZEOF_INT128__)
    80                                 return __lehmer64( kernelTLS().rand_seed );
     81                                lehmer64( kernelTLS().rand_seed );
    8182                        #else
    82                                 return __xorshift64( kernelTLS().rand_seed );
     83                                xorshift_13_7_17( kernelTLS().rand_seed );
    8384                        #endif
    8485                }
    8586
    86                 #define M  (1_l64u << 48_l64u)
    87                 #define A  (25214903917_l64u)
    88                 #define AI (18446708753438544741_l64u)
    89                 #define C  (11_l64u)
    90                 #define D  (16_l64u)
    91 
    9287                static inline unsigned __tls_rand_fwd() {
    93 
    94                         kernelTLS().ready_rng.fwd_seed = (A * kernelTLS().ready_rng.fwd_seed + C) & (M - 1);
    95                         return kernelTLS().ready_rng.fwd_seed >> D;
     88                        return LCGBI_fwd( kernelTLS().ready_rng.fwd_seed );
    9689                }
    9790
    9891                static inline unsigned __tls_rand_bck() {
    99                         unsigned int r = kernelTLS().ready_rng.bck_seed >> D;
    100                         kernelTLS().ready_rng.bck_seed = AI * (kernelTLS().ready_rng.bck_seed - C) & (M - 1);
    101                         return r;
    102                 }
    103 
    104                 #undef M
    105                 #undef A
    106                 #undef AI
    107                 #undef C
    108                 #undef D
     92                        return LCGBI_bck( kernelTLS().ready_rng.bck_seed );
     93                }
    10994
    11095                static inline void __tls_rand_advance_bck(void) {
     
    11297                }
    11398        }
    114 
    115 
    11699
    117100        extern void disable_interrupts();
     
    142125                        }
    143126                }
    144 
    145                 extern uint64_t thread_rand();
    146127
    147128                // Semaphore which only supports a single thread
  • libcfa/src/concurrency/kernel/startup.cfa

    r21a5bfb7 r175f9f4  
    3434#include "kernel_private.hfa"
    3535#include "startup.hfa"          // STARTUP_PRIORITY_XXX
     36#include "limits.hfa"
    3637#include "math.hfa"
    3738
     
    101102extern void __wake_proc(processor *);
    102103extern int cfa_main_returned;                                                   // from interpose.cfa
     104extern uint32_t __global_random_seed;
    103105
    104106//-----------------------------------------------------------------------------
     
    174176        this.context = &storage_mainThreadCtx;
    175177}
    176 
    177178
    178179
     
    489490        preferred = ready_queue_new_preferred();
    490491        last_proc = 0p;
     492        random_state = __global_random_seed;
    491493        #if defined( __CFA_WITH_VERIFY__ )
    492494                canary = 0x0D15EA5E0D15EA5Ep;
     
    513515        this.rdq.its = 0;
    514516        this.rdq.itr = 0;
    515         this.rdq.id  = -1u;
    516         this.rdq.target = -1u;
    517         this.rdq.last = -1u;
    518         this.rdq.cutoff = 0ull;
     517        this.rdq.id  = MAX;
     518        this.rdq.target = MAX;
     519        this.rdq.last = MAX;
     520        this.rdq.cpu = 0;
     521        // this.rdq.cutoff = 0ull;
    519522        do_terminate = false;
    520523        preemption_alarm = 0p;
     
    684687        uint_fast32_t last_size;
    685688        [this->unique_id, last_size] = ready_mutate_register();
     689
     690                this->rdq.cpu = __kernel_getcpu();
    686691
    687692                this->cltr->procs.total += 1u;
  • libcfa/src/concurrency/locks.hfa

    r21a5bfb7 r175f9f4  
    2929#include "time_t.hfa"
    3030#include "time.hfa"
    31 
    32 //-----------------------------------------------------------------------------
    33 // Semaphores
    34 
    35 // '0-nary' semaphore
    36 // Similar to a counting semaphore except the value of one is never reached
    37 // as a consequence, a V() that would bring the value to 1 *spins* until
    38 // a P consumes it
    39 struct Semaphore0nary {
    40         __spinlock_t lock; // needed to protect
    41         mpsc_queue(thread$) queue;
    42 };
    43 
    44 static inline bool P(Semaphore0nary & this, thread$ * thrd) {
    45         /* paranoid */ verify(!thrd`next);
    46         /* paranoid */ verify(!(&(*thrd)`next));
    47 
    48         push(this.queue, thrd);
    49         return true;
    50 }
    51 
    52 static inline bool P(Semaphore0nary & this) {
    53     thread$ * thrd = active_thread();
    54     P(this, thrd);
    55     park();
    56     return true;
    57 }
    58 
    59 static inline thread$ * V(Semaphore0nary & this, bool doUnpark = true) {
    60         thread$ * next;
    61         lock(this.lock __cfaabi_dbg_ctx2);
    62                 for (;;) {
    63                         next = pop(this.queue);
    64                         if (next) break;
    65                         Pause();
    66                 }
    67         unlock(this.lock);
    68 
    69         if (doUnpark) unpark(next);
    70         return next;
    71 }
    72 
    73 // Wrapper used on top of any sempahore to avoid potential locking
    74 struct BinaryBenaphore {
    75         volatile ssize_t counter;
    76 };
    77 
    78 static inline {
    79         void ?{}(BinaryBenaphore & this) { this.counter = 0; }
    80         void ?{}(BinaryBenaphore & this, zero_t) { this.counter = 0; }
    81         void ?{}(BinaryBenaphore & this, one_t ) { this.counter = 1; }
    82 
    83         // returns true if no blocking needed
    84         bool P(BinaryBenaphore & this) {
    85                 return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0;
    86         }
    87 
    88         bool tryP(BinaryBenaphore & this) {
    89                 ssize_t c = this.counter;
    90                 /* paranoid */ verify( c > MIN );
    91                 return (c >= 1) && __atomic_compare_exchange_n(&this.counter, &c, c-1, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
    92         }
    93 
    94         // returns true if notify needed
    95         bool V(BinaryBenaphore & this) {
    96                 ssize_t c = 0;
    97                 for () {
    98                         /* paranoid */ verify( this.counter < MAX );
    99                         if (__atomic_compare_exchange_n(&this.counter, &c, c+1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    100                                 if (c == 0) return true;
    101                                 /* paranoid */ verify(c < 0);
    102                                 return false;
    103                         } else {
    104                                 if (c == 1) return true;
    105                                 /* paranoid */ verify(c < 1);
    106                                 Pause();
    107                         }
    108                 }
    109         }
    110 }
    111 
    112 // Binary Semaphore based on the BinaryBenaphore on top of the 0-nary Semaphore
    113 struct ThreadBenaphore {
    114         BinaryBenaphore ben;
    115         Semaphore0nary  sem;
    116 };
    117 
    118 static inline void ?{}(ThreadBenaphore & this) {}
    119 static inline void ?{}(ThreadBenaphore & this, zero_t) { (this.ben){ 0 }; }
    120 static inline void ?{}(ThreadBenaphore & this, one_t ) { (this.ben){ 1 }; }
    121 
    122 static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
    123 static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
    124 static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
    125 
    126 static inline thread$ * V(ThreadBenaphore & this, bool doUnpark = true) {
    127         if (V(this.ben)) return 0p;
    128         return V(this.sem, doUnpark);
    129 }
    13031
    13132//-----------------------------------------------------------------------------
     
    17172static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    17273static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    173 
    174 struct fast_lock {
    175         thread$ * volatile owner;
    176         ThreadBenaphore sem;
    177 };
    178 
    179 static inline void ?{}(fast_lock & this) __attribute__((deprecated("use linear_backoff_then_block_lock instead")));
    180 static inline void ?{}(fast_lock & this) { this.owner = 0p; }
    181 
    182 static inline bool $try_lock(fast_lock & this, thread$ * thrd) {
    183     thread$ * exp = 0p;
    184     return __atomic_compare_exchange_n(&this.owner, &exp, thrd, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
    185 }
    186 
    187 static inline void lock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
    188 static inline void lock( fast_lock & this ) {
    189         thread$ * thrd = active_thread();
    190         /* paranoid */verify(thrd != this.owner);
    191 
    192         for (;;) {
    193                 if ($try_lock(this, thrd)) return;
    194                 P(this.sem);
    195         }
    196 }
    197 
    198 static inline bool try_lock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
    199 static inline bool try_lock ( fast_lock & this ) {
    200         thread$ * thrd = active_thread();
    201         /* paranoid */ verify(thrd != this.owner);
    202         return $try_lock(this, thrd);
    203 }
    204 
    205 static inline thread$ * unlock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
    206 static inline thread$ * unlock( fast_lock & this ) {
    207         /* paranoid */ verify(active_thread() == this.owner);
    208 
    209         // open 'owner' before unlocking anyone
    210         // so new and unlocked threads don't park incorrectly.
    211         // This may require additional fencing on ARM.
    212         this.owner = 0p;
    213 
    214         return V(this.sem);
    215 }
    216 
    217 static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
    218 static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
    219 static inline void on_notify( fast_lock &, struct thread$ * t ) { unpark(t); }
    22074
    22175struct mcs_node {
  • libcfa/src/concurrency/ready_queue.cfa

    r21a5bfb7 r175f9f4  
    2020
    2121
    22 #define USE_RELAXED_FIFO
     22// #define USE_RELAXED_FIFO
    2323// #define USE_WORK_STEALING
    2424// #define USE_CPU_WORK_STEALING
     25#define USE_AWARE_STEALING
    2526
    2627#include "bits/defs.hfa"
     
    2930
    3031#include "stdlib.hfa"
     32#include "limits.hfa"
    3133#include "math.hfa"
    3234
     
    5456#endif
    5557
    56 #if   defined(USE_CPU_WORK_STEALING)
     58#if   defined(USE_AWARE_STEALING)
     59        #define READYQ_SHARD_FACTOR 2
     60        #define SEQUENTIAL_SHARD 2
     61#elif defined(USE_CPU_WORK_STEALING)
    5762        #define READYQ_SHARD_FACTOR 2
    5863#elif defined(USE_RELAXED_FIFO)
     
    138143        __kernel_rseq_register();
    139144
    140         __cfadbg_print_safe(ready_queue, "Kernel : Registering proc %p for RW-Lock\n", proc);
    141145        bool * handle = (bool *)&kernelTLS().sched_lock;
    142146
     
    174178        }
    175179
    176         __cfadbg_print_safe(ready_queue, "Kernel : Registering proc %p done, id %lu\n", proc, n);
    177 
    178180        // Return new spot.
    179181        /* paranoid */ verify(n < ready);
     
    190192
    191193        __atomic_store_n(cell, 0p, __ATOMIC_RELEASE);
    192 
    193         __cfadbg_print_safe(ready_queue, "Kernel : Unregister proc %p\n", proc);
    194194
    195195        __kernel_rseq_unregister();
     
    244244
    245245//=======================================================================
     246// caches handling
     247
     248struct __attribute__((aligned(128))) __ready_queue_caches_t {
     249        // Count States:
     250        // - 0  : No one is looking after this cache
     251        // - 1  : No one is looking after this cache, BUT it's not empty
     252        // - 2+ : At least one processor is looking after this cache
     253        volatile unsigned count;
     254};
     255
     256void  ?{}(__ready_queue_caches_t & this) { this.count = 0; }
     257void ^?{}(__ready_queue_caches_t & this) {}
     258
     259static inline void depart(__ready_queue_caches_t & cache) {
     260        /* paranoid */ verify( cache.count > 1);
     261        __atomic_fetch_add(&cache.count, -1, __ATOMIC_SEQ_CST);
     262        /* paranoid */ verify( cache.count != 0);
     263        /* paranoid */ verify( cache.count < 65536 ); // This verify assumes no cluster will have more than 65000 kernel threads mapped to a single cache, which could be correct but is super weird.
     264}
     265
     266static inline void arrive(__ready_queue_caches_t & cache) {
     267        // for() {
     268        //      unsigned expected = cache.count;
     269        //      unsigned desired  = 0 == expected ? 2 : expected + 1;
     270        // }
     271}
     272
     273//=======================================================================
    246274// Cforall Ready Queue used for scheduling
    247275//=======================================================================
    248 unsigned long long moving_average(unsigned long long nval, unsigned long long oval) {
    249         const unsigned long long tw = 16;
    250         const unsigned long long nw = 4;
    251         const unsigned long long ow = tw - nw;
    252         return ((nw * nval) + (ow * oval)) / tw;
     276unsigned long long moving_average(unsigned long long currtsc, unsigned long long instsc, unsigned long long old_avg) {
     277        /* paranoid */ verifyf( currtsc < 45000000000000000, "Suspiciously large current time: %'llu (%llx)\n", currtsc, currtsc );
     278        /* paranoid */ verifyf( instsc  < 45000000000000000, "Suspiciously large insert time: %'llu (%llx)\n", instsc, instsc );
     279        /* paranoid */ verifyf( old_avg < 15000000000000, "Suspiciously large previous average: %'llu (%llx)\n", old_avg, old_avg );
     280
     281        const unsigned long long new_val = currtsc > instsc ? currtsc - instsc : 0;
     282        const unsigned long long total_weight = 16;
     283        const unsigned long long new_weight   = 4;
     284        const unsigned long long old_weight = total_weight - new_weight;
     285        const unsigned long long ret = ((new_weight * new_val) + (old_weight * old_avg)) / total_weight;
     286        return ret;
    253287}
    254288
     
    271305                }
    272306        #else
    273                 lanes.data  = 0p;
    274                 lanes.tscs  = 0p;
    275                 lanes.help  = 0p;
    276                 lanes.count = 0;
     307                lanes.data   = 0p;
     308                lanes.tscs   = 0p;
     309                lanes.caches = 0p;
     310                lanes.help   = 0p;
     311                lanes.count  = 0;
    277312        #endif
    278313}
     
    285320        free(lanes.data);
    286321        free(lanes.tscs);
     322        free(lanes.caches);
    287323        free(lanes.help);
    288324}
    289325
    290326//-----------------------------------------------------------------------
     327#if defined(USE_AWARE_STEALING)
     328        __attribute__((hot)) void push(struct cluster * cltr, struct thread$ * thrd, unpark_hint hint) with (cltr->ready_queue) {
     329                processor * const proc = kernelTLS().this_processor;
     330                const bool external = (!proc) || (cltr != proc->cltr);
     331                const bool remote   = hint == UNPARK_REMOTE;
     332
     333                unsigned i;
     334                if( external || remote ) {
     335                        // Figure out where thread was last time and make sure it's valid
     336                        /* paranoid */ verify(thrd->preferred >= 0);
     337                        if(thrd->preferred * READYQ_SHARD_FACTOR < lanes.count) {
     338                                /* paranoid */ verify(thrd->preferred * READYQ_SHARD_FACTOR < lanes.count);
     339                                unsigned start = thrd->preferred * READYQ_SHARD_FACTOR;
     340                                do {
     341                                        unsigned r = __tls_rand();
     342                                        i = start + (r % READYQ_SHARD_FACTOR);
     343                                        /* paranoid */ verify( i < lanes.count );
     344                                        // If we can't lock it retry
     345                                } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
     346                        } else {
     347                                do {
     348                                        i = __tls_rand() % lanes.count;
     349                                } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
     350                        }
     351                } else {
     352                        do {
     353                                unsigned r = proc->rdq.its++;
     354                                i = proc->rdq.id + (r % READYQ_SHARD_FACTOR);
     355                                /* paranoid */ verify( i < lanes.count );
     356                                // If we can't lock it retry
     357                        } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
     358                }
     359
     360                // Actually push it
     361                push(lanes.data[i], thrd);
     362
     363                // Unlock and return
     364                __atomic_unlock( &lanes.data[i].lock );
     365
     366                #if !defined(__CFA_NO_STATISTICS__)
     367                        if(unlikely(external || remote)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.success, 1, __ATOMIC_RELAXED);
     368                        else __tls_stats()->ready.push.local.success++;
     369                #endif
     370        }
     371
     372        static inline unsigned long long calc_cutoff(const unsigned long long ctsc, const processor * proc, __ready_queue_t & rdq) {
     373                unsigned start = proc->rdq.id;
     374                unsigned long long max = 0;
     375                for(i; READYQ_SHARD_FACTOR) {
     376                        unsigned long long ptsc = ts(rdq.lanes.data[start + i]);
     377                        if(ptsc != -1ull) {
     378                                /* paranoid */ verify( start + i < rdq.lanes.count );
     379                                unsigned long long tsc = moving_average(ctsc, ptsc, rdq.lanes.tscs[start + i].ma);
     380                                if(tsc > max) max = tsc;
     381                        }
     382                }
     383                return (max + 2 * max) / 2;
     384        }
     385
     386        __attribute__((hot)) struct thread$ * pop_fast(struct cluster * cltr) with (cltr->ready_queue) {
     387                /* paranoid */ verify( lanes.count > 0 );
     388                /* paranoid */ verify( kernelTLS().this_processor );
     389                /* paranoid */ verify( kernelTLS().this_processor->rdq.id < lanes.count );
     390
     391                processor * const proc = kernelTLS().this_processor;
     392                unsigned this = proc->rdq.id;
     393                /* paranoid */ verify( this < lanes.count );
     394                __cfadbg_print_safe(ready_queue, "Kernel : pop from %u\n", this);
     395
     396                // Figure out the current cpu and make sure it is valid
     397                const int cpu = __kernel_getcpu();
     398                /* paranoid */ verify(cpu >= 0);
     399                /* paranoid */ verify(cpu < cpu_info.hthrd_count);
     400                unsigned this_cache = cpu_info.llc_map[cpu].cache;
     401
     402                // Super important: don't write the same value over and over again
     403                // We want to maximise our chances that his particular values stays in cache
     404                if(lanes.caches[this / READYQ_SHARD_FACTOR].id != this_cache)
     405                        __atomic_store_n(&lanes.caches[this / READYQ_SHARD_FACTOR].id, this_cache, __ATOMIC_RELAXED);
     406
     407                const unsigned long long ctsc = rdtscl();
     408
     409                if(proc->rdq.target == MAX) {
     410                        uint64_t chaos = __tls_rand();
     411                        unsigned ext = chaos & 0xff;
     412                        unsigned other  = (chaos >> 8) % (lanes.count);
     413
     414                        if(ext < 3 || __atomic_load_n(&lanes.caches[other / READYQ_SHARD_FACTOR].id, __ATOMIC_RELAXED) == this_cache) {
     415                                proc->rdq.target = other;
     416                        }
     417                }
     418                else {
     419                        const unsigned target = proc->rdq.target;
     420                        __cfadbg_print_safe(ready_queue, "Kernel : %u considering helping %u, tcsc %llu\n", this, target, lanes.tscs[target].tv);
     421                        /* paranoid */ verify( lanes.tscs[target].tv != MAX );
     422                        if(target < lanes.count) {
     423                                const unsigned long long cutoff = calc_cutoff(ctsc, proc, cltr->ready_queue);
     424                                const unsigned long long age = moving_average(ctsc, lanes.tscs[target].tv, lanes.tscs[target].ma);
     425                                __cfadbg_print_safe(ready_queue, "Kernel : Help attempt on %u from %u, age %'llu vs cutoff %'llu, %s\n", target, this, age, cutoff, age > cutoff ? "yes" : "no");
     426                                if(age > cutoff) {
     427                                        thread$ * t = try_pop(cltr, target __STATS(, __tls_stats()->ready.pop.help));
     428                                        if(t) return t;
     429                                }
     430                        }
     431                        proc->rdq.target = MAX;
     432                }
     433
     434                for(READYQ_SHARD_FACTOR) {
     435                        unsigned i = this + (proc->rdq.itr++ % READYQ_SHARD_FACTOR);
     436                        if(thread$ * t = try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.local))) return t;
     437                }
     438
     439                // All lanes where empty return 0p
     440                return 0p;
     441
     442        }
     443        __attribute__((hot)) struct thread$ * pop_slow(struct cluster * cltr) with (cltr->ready_queue) {
     444                unsigned i = __tls_rand() % lanes.count;
     445                return try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.steal));
     446        }
     447        __attribute__((hot)) struct thread$ * pop_search(struct cluster * cltr) {
     448                return search(cltr);
     449        }
     450#endif
    291451#if defined(USE_CPU_WORK_STEALING)
    292452        __attribute__((hot)) void push(struct cluster * cltr, struct thread$ * thrd, unpark_hint hint) with (cltr->ready_queue) {
     
    350510                /* paranoid */ verify( kernelTLS().this_processor );
    351511
     512                processor * const proc = kernelTLS().this_processor;
    352513                const int cpu = __kernel_getcpu();
    353514                /* paranoid */ verify(cpu >= 0);
     
    360521                /* paranoid */ verifyf((map.start + map.count) * READYQ_SHARD_FACTOR <= lanes.count, "have %zu lanes but map can go up to %u", lanes.count, (map.start + map.count) * READYQ_SHARD_FACTOR);
    361522
    362                 processor * const proc = kernelTLS().this_processor;
    363523                const int start = map.self * READYQ_SHARD_FACTOR;
    364524                const unsigned long long ctsc = rdtscl();
    365525
    366526                // Did we already have a help target
    367                 if(proc->rdq.target == -1u) {
     527                if(proc->rdq.target == MAX) {
    368528                        unsigned long long max = 0;
    369529                        for(i; READYQ_SHARD_FACTOR) {
    370                                 unsigned long long tsc = moving_average(ctsc - ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
     530                                unsigned long long tsc = moving_average(ctsc, ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
    371531                                if(tsc > max) max = tsc;
    372532                        }
    373                         proc->rdq.cutoff = (max + 2 * max) / 2;
     533                        // proc->rdq.cutoff = (max + 2 * max) / 2;
    374534                        /* paranoid */ verify(lanes.count < 65536); // The following code assumes max 65536 cores.
    375535                        /* paranoid */ verify(map.count < 65536); // The following code assumes max 65536 cores.
     
    384544                        }
    385545
    386                         /* paranoid */ verify(proc->rdq.target != -1u);
     546                        /* paranoid */ verify(proc->rdq.target != MAX);
    387547                }
    388548                else {
    389549                        unsigned long long max = 0;
    390550                        for(i; READYQ_SHARD_FACTOR) {
    391                                 unsigned long long tsc = moving_average(ctsc - ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
     551                                unsigned long long tsc = moving_average(ctsc, ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
    392552                                if(tsc > max) max = tsc;
    393553                        }
     
    395555                        {
    396556                                unsigned target = proc->rdq.target;
    397                                 proc->rdq.target = -1u;
     557                                proc->rdq.target = MAX;
    398558                                lanes.help[target / READYQ_SHARD_FACTOR].tri++;
    399                                 if(moving_average(ctsc - lanes.tscs[target].tv, lanes.tscs[target].ma) > cutoff) {
     559                                if(moving_average(ctsc, lanes.tscs[target].tv, lanes.tscs[target].ma) > cutoff) {
    400560                                        thread$ * t = try_pop(cltr, target __STATS(, __tls_stats()->ready.pop.help));
    401561                                        proc->rdq.last = target;
    402562                                        if(t) return t;
    403                                         else proc->rdq.target = -1u;
    404563                                }
    405                                 else proc->rdq.target = -1u;
     564                                proc->rdq.target = MAX;
    406565                        }
    407566
    408567                        unsigned last = proc->rdq.last;
    409                         if(last != -1u && lanes.tscs[last].tv < cutoff && ts(lanes.data[last]) < cutoff) {
     568                        if(last != MAX && moving_average(ctsc, lanes.tscs[last].tv, lanes.tscs[last].ma) > cutoff) {
    410569                                thread$ * t = try_pop(cltr, last __STATS(, __tls_stats()->ready.pop.help));
    411570                                if(t) return t;
    412571                        }
    413572                        else {
    414                                 proc->rdq.last = -1u;
     573                                proc->rdq.last = MAX;
    415574                        }
    416575                }
     
    428587                processor * const proc = kernelTLS().this_processor;
    429588                unsigned last = proc->rdq.last;
    430                 if(last != -1u) {
     589                if(last != MAX) {
    431590                        struct thread$ * t = try_pop(cltr, last __STATS(, __tls_stats()->ready.pop.steal));
    432591                        if(t) return t;
    433                         proc->rdq.last = -1u;
     592                        proc->rdq.last = MAX;
    434593                }
    435594
     
    560719                #else
    561720                        unsigned preferred = thrd->preferred;
    562                         const bool external = (hint != UNPARK_LOCAL) || (!kernelTLS().this_processor) || preferred == -1u || thrd->curr_cluster != cltr;
     721                        const bool external = (hint != UNPARK_LOCAL) || (!kernelTLS().this_processor) || preferred == MAX || thrd->curr_cluster != cltr;
    563722                        /* paranoid */ verifyf(external || preferred < lanes.count, "Invalid preferred queue %u for %u lanes", preferred, lanes.count );
    564723
     
    612771                processor * proc = kernelTLS().this_processor;
    613772
    614                 if(proc->rdq.target == -1u) {
     773                if(proc->rdq.target == MAX) {
    615774                        unsigned long long min = ts(lanes.data[proc->rdq.id]);
    616775                        for(int i = 0; i < READYQ_SHARD_FACTOR; i++) {
     
    623782                else {
    624783                        unsigned target = proc->rdq.target;
    625                         proc->rdq.target = -1u;
     784                        proc->rdq.target = MAX;
    626785                        const unsigned long long bias = 0; //2_500_000_000;
    627786                        const unsigned long long cutoff = proc->rdq.cutoff > bias ? proc->rdq.cutoff - bias : proc->rdq.cutoff;
     
    658817// try to pop from a lane given by index w
    659818static inline struct thread$ * try_pop(struct cluster * cltr, unsigned w __STATS(, __stats_readyQ_pop_t & stats)) with (cltr->ready_queue) {
     819        /* paranoid */ verify( w < lanes.count );
    660820        __STATS( stats.attempt++; )
    661821
     
    681841        // Actually pop the list
    682842        struct thread$ * thrd;
    683         unsigned long long tsc_before = ts(lane);
     843        #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
     844                unsigned long long tsc_before = ts(lane);
     845        #endif
    684846        unsigned long long tsv;
    685847        [thrd, tsv] = pop(lane);
     
    695857        __STATS( stats.success++; )
    696858
    697         #if defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
    698                 unsigned long long now = rdtscl();
    699                 lanes.tscs[w].tv = tsv;
    700                 lanes.tscs[w].ma = moving_average(now > tsc_before ? now - tsc_before : 0, lanes.tscs[w].ma);
     859        #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
     860                if (tsv != MAX) {
     861                        unsigned long long now = rdtscl();
     862                        unsigned long long pma = __atomic_load_n(&lanes.tscs[w].ma, __ATOMIC_RELAXED);
     863                        __atomic_store_n(&lanes.tscs[w].tv, tsv, __ATOMIC_RELAXED);
     864                        __atomic_store_n(&lanes.tscs[w].ma, moving_average(now, tsc_before, pma), __ATOMIC_RELAXED);
     865                }
    701866        #endif
    702867
    703         #if defined(USE_CPU_WORK_STEALING)
     868        #if defined(USE_AWARE_STEALING) || defined(USE_CPU_WORK_STEALING)
    704869                thrd->preferred = w / READYQ_SHARD_FACTOR;
    705870        #else
     
    800965                /* paranoid */ verifyf( it, "Unexpected null iterator, at index %u of %u\n", i, count);
    801966                it->rdq.id = value;
    802                 it->rdq.target = -1u;
     967                it->rdq.target = MAX;
    803968                value += READYQ_SHARD_FACTOR;
    804969                it = &(*it)`next;
     
    813978
    814979static void fix_times( struct cluster * cltr ) with( cltr->ready_queue ) {
    815         #if defined(USE_WORK_STEALING)
     980        #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING)
    816981                lanes.tscs = alloc(lanes.count, lanes.tscs`realloc);
    817982                for(i; lanes.count) {
    818                         unsigned long long tsc1 = ts(lanes.data[i]);
    819                         unsigned long long tsc2 = rdtscl();
    820                         lanes.tscs[i].tv = min(tsc1, tsc2);
     983                        lanes.tscs[i].tv = rdtscl();
     984                        lanes.tscs[i].ma = 0;
    821985                }
    822986        #endif
     
    8641028                        // Update original
    8651029                        lanes.count = ncount;
     1030
     1031                        lanes.caches = alloc( target, lanes.caches`realloc );
    8661032                }
    8671033
     
    9401106                                fix(lanes.data[idx]);
    9411107                        }
     1108
     1109                        lanes.caches = alloc( target, lanes.caches`realloc );
    9421110                }
    9431111
    9441112                fix_times(cltr);
     1113
    9451114
    9461115                reassign_cltr_id(cltr);
  • libcfa/src/concurrency/thread.cfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec  4 09:17:49 2019
    13 // Update Count     : 9
     12// Last Modified On : Thu Jan 13 20:11:55 2022
     13// Update Count     : 42
    1414//
    1515
     
    2525#include "invoke.h"
    2626
    27 uint64_t thread_rand();
     27extern uint32_t __global_random_seed;
    2828
    2929//-----------------------------------------------------------------------------
    3030// Thread ctors and dtors
    31 void ?{}(thread$ & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
     31void ?{}( thread$ & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
    3232        context{ 0p, 0p };
    3333        self_cor{ name, storage, storageSize };
     
    4545        preferred = ready_queue_new_preferred();
    4646        last_proc = 0p;
     47        random_state = __global_random_seed;
    4748        #if defined( __CFA_WITH_VERIFY__ )
    4849                canary = 0x0D15EA5E0D15EA5Ep;
     
    171172}
    172173
    173 uint64_t thread_rand() {
    174         disable_interrupts();
    175         uint64_t ret = __tls_rand();
    176         enable_interrupts();
    177         return ret;
    178 }
     174//-----------------------------------------------------------------------------
     175#define GENERATOR LCG
     176
     177void set_seed( uint32_t seed ) {
     178        active_thread()->random_state = __global_random_seed = seed;
     179        GENERATOR( active_thread()->random_state );
     180} // set_seed
     181uint32_t prng( void ) { return GENERATOR( active_thread()->random_state ); } // [0,UINT_MAX]
    179182
    180183// Local Variables: //
  • libcfa/src/device/cpu.cfa

    r21a5bfb7 r175f9f4  
    427427                        unsigned c = pairings[i].cpu;
    428428                        unsigned llc_id = pairings[i].id;
    429                         unsigned width = maps[llc_id].raw->width;
    430429                        unsigned start = maps[llc_id].start;
    431                         unsigned self  = start + (maps[llc_id].count++);
    432                         entries[c].count = width;
     430                        entries[c].count = maps[llc_id].raw->width;
    433431                        entries[c].start = start;
    434                         entries[c].self  = self;
     432                        entries[c].self  = start + (maps[llc_id].count++);
     433                        entries[c].cache = llc_id;
    435434                }
    436435
  • libcfa/src/device/cpu.hfa

    r21a5bfb7 r175f9f4  
    1616#include <stddef.h>
    1717
     18// Map from cpu entry to a structure detailling cpus with common topologies
     19// Note that the cpu-groups are contiguous so the indexing is different from
     20// the cpu indexing
    1821struct cpu_map_entry_t {
     22        // Where this particular cpu is in the group
    1923        unsigned self;
     24
     25        // Starting index of the cpus with the same topology
    2026        unsigned start;
     27
     28        // Number of cpus with the same topology
    2129        unsigned count;
     30
     31        // Index of the cache this entry describes
     32        unsigned cache;
    2233};
    2334
  • libcfa/src/fstream.cfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 11:23:05 2021
    13 // Update Count     : 512
     12// Last Modified On : Mon Jan 10 08:45:05 2022
     13// Update Count     : 513
    1414//
    1515
     
    5252inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
    5353
    54 inline void lock( ofstream & os ) with( os ) {  lock( os.lock$ ); }
     54inline void lock( ofstream & os ) with( os ) { lock( os.lock$ ); }
    5555inline void unlock( ofstream & os ) { unlock( os.lock$ ); }
    5656
  • libcfa/src/iostream.cfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 09:28:17 2021
    13 // Update Count     : 1345
     12// Last Modified On : Mon Jan 17 16:38:32 2022
     13// Update Count     : 1349
    1414//
    1515
     
    5757        ostype & ?|?( ostype & os, signed char sc ) {
    5858                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    59                 fmt( os, "%hhd", sc );
     59                fmt( os, "%'hhd", sc );
    6060                return os;
    6161        } // ?|?
     
    6666        ostype & ?|?( ostype & os, unsigned char usc ) {
    6767                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    68                 fmt( os, "%hhu", usc );
     68                fmt( os, "%'hhu", usc );
    6969                return os;
    7070        } // ?|?
     
    7575        ostype & ?|?( ostype & os, short int si ) {
    7676                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    77                 fmt( os, "%hd", si );
     77                fmt( os, "%'hd", si );
    7878                return os;
    7979        } // ?|?
     
    8484        ostype & ?|?( ostype & os, unsigned short int usi ) {
    8585                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    86                 fmt( os, "%hu", usi );
     86                fmt( os, "%'hu", usi );
    8787                return os;
    8888        } // ?|?
     
    9393        ostype & ?|?( ostype & os, int i ) {
    9494                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    95                 fmt( os, "%d", i );
     95                fmt( os, "%'d", i );
    9696                return os;
    9797        } // ?|?
     
    102102        ostype & ?|?( ostype & os, unsigned int ui ) {
    103103                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    104                 fmt( os, "%u", ui );
     104                fmt( os, "%'u", ui );
    105105                return os;
    106106        } // ?|?
     
    111111        ostype & ?|?( ostype & os, long int li ) {
    112112                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    113                 fmt( os, "%ld", li );
     113                fmt( os, "%'ld", li );
    114114                return os;
    115115        } // ?|?
     
    120120        ostype & ?|?( ostype & os, unsigned long int uli ) {
    121121                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    122                 fmt( os, "%lu", uli );
     122                fmt( os, "%'lu", uli );
    123123                return os;
    124124        } // ?|?
     
    129129        ostype & ?|?( ostype & os, long long int lli ) {
    130130                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    131                 fmt( os, "%lld", lli );
     131                fmt( os, "%'lld", lli );
    132132                return os;
    133133        } // ?|?
     
    138138        ostype & ?|?( ostype & os, unsigned long long int ulli ) {
    139139                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    140                 fmt( os, "%llu", ulli );
     140                fmt( os, "%'llu", ulli );
    141141                return os;
    142142        } // ?|?
     
    496496                if ( ! f.flags.pc ) memcpy( &fmtstr, IFMTNP, sizeof(IFMTNP) ); \
    497497                else memcpy( &fmtstr, IFMTP, sizeof(IFMTP) ); \
    498                 int star = 4;                                                                   /* position before first '*' */ \
     498                int star = 5;                                                                   /* position before first '*' */ \
    499499\
    500500                /* Insert flags into spaces before '*', from right to left. */ \
     
    503503                if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \
    504504                if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \
     505                fmtstr[star] = '\''; star -= 1;                                 /* locale */ \
    505506                fmtstr[star] = '%'; \
    506507\
     
    521522} // distribution
    522523
    523 IntegralFMTImpl( signed char, "     *hh ", "     *.*hh " )
    524 IntegralFMTImpl( unsigned char, "     *hh ", "     *.*hh " )
    525 IntegralFMTImpl( signed short int, "     *h ", "     *.*h " )
    526 IntegralFMTImpl( unsigned short int, "     *h ", "     *.*h " )
    527 IntegralFMTImpl( signed int, "     * ", "     *.* " )
    528 IntegralFMTImpl( unsigned int, "     * ", "     *.* " )
    529 IntegralFMTImpl( signed long int, "     *l ", "     *.*l " )
    530 IntegralFMTImpl( unsigned long int, "     *l ", "     *.*l " )
    531 IntegralFMTImpl( signed long long int, "     *ll ", "     *.*ll " )
    532 IntegralFMTImpl( unsigned long long int, "     *ll ", "     *.*ll " )
     524IntegralFMTImpl( signed char,            "      *hh ", "      *.*hh " )
     525IntegralFMTImpl( unsigned char,          "      *hh ", "      *.*hh " )
     526IntegralFMTImpl( signed short int,       "      *h ",  "      *.*h " )
     527IntegralFMTImpl( unsigned short int,     "      *h ",  "      *.*h " )
     528IntegralFMTImpl( signed int,             "      * ",   "      *.* " )
     529IntegralFMTImpl( unsigned int,           "      * ",   "      *.* " )
     530IntegralFMTImpl( signed long int,        "      *l ",  "      *.*l " )
     531IntegralFMTImpl( unsigned long int,      "      *l ",  "      *.*l " )
     532IntegralFMTImpl( signed long long int,   "      *ll ", "      *.*ll " )
     533IntegralFMTImpl( unsigned long long int, "      *ll ", "      *.*ll " )
    533534
    534535
  • libcfa/src/parseconfig.cfa

    r21a5bfb7 r175f9f4  
     1
     2
     3#pragma GCC diagnostic push
     4//#pragma GCC diagnostic ignored "-Wunused-parameter"
     5//#pragma GCC diagnostic ignored "-Wunused-function"
     6//#pragma GCC diagnostic ignored "-Wuninitialized"
     7//#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     8
    19#include <fstream.hfa>
    210#include <parseargs.hfa>
     
    1927// TODO: use string interface when it's ready (and implement exception msg protocol)
    2028[ void ] msg( * Missing_Config_Entries ex ) {
    21         serr | nlOff;
    22         serr | "The config file is missing " | ex->num_missing;
    23         serr | nlOn;
    24         if ( ex->num_missing == 1 ) {
    25                 serr | " entry.";
    26         } else {
    27                 serr | " entries.";
    28         }
     29        serr | "The config file is missing " | ex->num_missing | "entr" | sepOff | (ex->num_missing == 1 ? "y." : "ies.");
    2930} // msg
    3031
     
    223224        return value < zero_val;
    224225}
     226#pragma GCC diagnostic pop
    225227
    226228
  • libcfa/src/startup.cfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jan  9 23:18:23 2021
    13 // Update Count     : 34
     12// Last Modified On : Mon Jan 17 16:41:54 2022
     13// Update Count     : 55
    1414//
    1515
     
    1717#include <locale.h>                                                                             // setlocale
    1818#include <stdlib.h>                                                                             // getenv
     19#include "bits/defs.hfa"                                                                // rdtscl
    1920#include "startup.hfa"
     21
     22extern uint32_t __global_random_seed;                                   // sequential/concurrent
     23extern uint32_t __global_random_state;                                  // sequential
    2024
    2125extern "C" {
     
    2327        void __cfaabi_appready_startup( void ) {
    2428                tzset();                                                                                // initialize time global variables
    25                 setlocale( LC_NUMERIC, getenv("LANG") );
    2629                #ifdef __CFA_DEBUG__
    2730                extern void heapAppStart();
     
    4851        void __cfaabi_core_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
    4952        void __cfaabi_core_startup( void ) {
     53                __global_random_state = __global_random_seed = rdtscl();
    5054                __cfaabi_interpose_startup();
    5155                __cfaabi_device_startup();
  • libcfa/src/stdlib.cfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  3 09:36:27 2022
    13 // Update Count     : 519
     12// Last Modified On : Thu Jan 13 21:38:30 2022
     13// Update Count     : 593
    1414//
    1515
    1616#include "stdlib.hfa"
     17#include "bits/random.hfa"
     18#include "concurrency/invoke.h"                                                 // random_state
    1719
    1820//---------------------------------------
     
    221223//---------------------------------------
    222224
    223 static uint32_t seed = 0;                                                               // current seed
    224 static thread_local uint32_t state;                                             // random state
    225 
    226 void set_seed( uint32_t seed_ ) { state = seed = seed_; }
    227 uint32_t get_seed() { return seed; }
    228 
    229225#define GENERATOR LCG
    230226
    231 inline uint32_t MarsagliaXor( uint32_t & state ) {
    232         if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
    233         else if ( unlikely( state == 0 ) ) state = seed;
    234         state ^= state << 6;
    235         state ^= state >> 21;
    236         state ^= state << 7;
    237         return state;
    238 } // MarsagliaXor
    239 
    240 inline uint32_t LCG( uint32_t & state ) {                               // linear congruential generator
    241         if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
    242         else if ( unlikely( state == 0 ) ) state = seed;
    243         return state = 36969 * (state & 65535) + (state >> 16); // 36969 is NOT prime!
    244 } // LCG
    245 
     227uint32_t __global_random_seed;                                                  // sequential/concurrent
     228uint32_t __global_random_state;                                         // sequential only
     229
     230void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; GENERATOR( state ); } // set seed
    246231uint32_t prng( PRNG & prng ) with( prng ) { callcnt += 1; return GENERATOR( state ); }
    247232
    248 uint32_t prng( void ) { return GENERATOR( state ); }
     233void set_seed( uint32_t seed ) { __global_random_seed = seed; GENERATOR( __global_random_state ); }
     234uint32_t get_seed() { return __global_random_seed; }
     235uint32_t prng( void ) { return GENERATOR( __global_random_state ); } // [0,UINT_MAX]
    249236
    250237//---------------------------------------
  • libcfa/src/stdlib.hfa

    r21a5bfb7 r175f9f4  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan  2 22:53:57 2022
    13 // Update Count     : 594
     12// Last Modified On : Thu Jan 13 21:34:46 2022
     13// Update Count     : 636
    1414//
    1515
     
    2121#include <stdlib.h>                                                                             // *alloc, strto*, ato*
    2222#include <heap.hfa>
     23
    2324
    2425// Reduce includes by explicitly defining these routines.
     
    207208
    208209        forall( TT... | { T * alloc_internal$( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
    209 
    210210                T * alloc_internal$( void *       , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
    211211                return alloc_internal$( Resize, (T*)0p, Align, Dim, Fill, rest);
     
    231231                return alloc_internal$( (void*)0p, (T*)0p, (_Alignof(T) > libAlign() ? _Alignof(T) : libAlign()), dim, (S_fill(T)){'0'}, all);
    232232            }
    233 
    234233        } // distribution TT
    235234} // distribution T
     
    385384//---------------------------------------
    386385
     386// Sequential Pseudo Random-Number Generator : generate repeatable sequence of values that appear random.
     387//
     388// Declaration :
     389//   PRNG sprng = { 1009 } - set starting seed versus random seed
     390//   
     391// Interface :
     392//   set_seed( sprng, 1009 ) - set starting seed for ALL kernel threads versus random seed
     393//   get_seed( sprng ) - read seed
     394//   prng( sprng ) - generate random value in range [0,UINT_MAX]
     395//   prng( sprng, u ) - generate random value in range [0,u)
     396//   prng( sprng, l, u ) - generate random value in range [l,u]
     397//   calls( sprng ) - number of generated random value so far
     398//
     399// Examples : generate random number between 5-21
     400//   prng( sprng ) % 17 + 5;    values 0-16 + 5 = 5-21
     401//   prng( sprng, 16 + 1 ) + 5;
     402//   prng( sprng, 5, 21 );
     403//   calls( sprng );
     404
    387405struct PRNG {
    388406        uint32_t callcnt;                                                                       // call count
     
    391409}; // PRNG
    392410
    393 extern uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
     411void set_seed( PRNG & prng, uint32_t seed_ );
     412uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
    394413static inline {
    395         void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; } // set seed
    396414        void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); } // random seed
    397415        void ?{}( PRNG & prng, uint32_t seed ) { set_seed( prng, seed ); } // fixed seed
     
    402420} // distribution
    403421
    404 extern void set_seed( uint32_t seed );                                  // set per thread seed
    405 extern uint32_t get_seed();                                                             // get seed
    406 extern uint32_t prng( void ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
     422// Concurrent Pseudo Random-Number Generator : generate repeatable sequence of values that appear random.
     423//
     424// Interface :
     425//   set_seed( 1009 ) - fixed seed for all kernel threads versus random seed
     426//   get_seed() - read seed
     427//   prng() - generate random value in range [0,UINT_MAX]
     428//   prng( u ) - generate random value in range [0,u)
     429//   prng( l, u ) - generate random value in range [l,u]
     430//
     431// Examples : generate random number between 5-21
     432//   prng() % 17 + 5;   values 0-16 + 5 = 5-21
     433//   prng( 16 + 1 ) + 5;
     434//   prng( 5, 21 );
     435
     436void set_seed( uint32_t seed_ ) OPTIONAL_THREAD;
     437uint32_t get_seed() __attribute__(( warn_unused_result ));
     438uint32_t prng( void ) __attribute__(( warn_unused_result )) OPTIONAL_THREAD; // [0,UINT_MAX]
    407439static inline {
    408         uint32_t prng( uint32_t u ) __attribute__(( warn_unused_result ));
    409         uint32_t prng( uint32_t u ) { return prng() % u; }      // [0,u)
    410         uint32_t prng( uint32_t l, uint32_t u ) __attribute__(( warn_unused_result ));
    411         uint32_t prng( uint32_t l, uint32_t u ) { return prng( u - l + 1 ) + l; } // [l,u]
     440        uint32_t prng( uint32_t u ) __attribute__(( warn_unused_result )) { return prng() % u; } // [0,u)
     441        uint32_t prng( uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( u - l + 1 ) + l; } // [l,u]
    412442} // distribution
    413443
Note: See TracChangeset for help on using the changeset viewer.