Changes in / [97fed44:f57f6ea0]


Ignore:
Files:
5 added
39 edited

Legend:

Unmodified
Added
Removed
  • benchmark/io/http/Makefile.am

    r97fed44 rf57f6ea0  
    2121include $(top_srcdir)/tools/build/cfa.make
    2222
    23 AM_CFLAGS = -O3 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror
     23AM_CFLAGS = -O2 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror
    2424AM_CFAFLAGS = -quiet -nodebug
    2525AM_LDFLAGS = -quiet -nodebug
  • benchmark/io/http/main.cfa

    r97fed44 rf57f6ea0  
    1 #define _GNU_SOURCE
     1#define __USE_GNU
    22
    33#include <errno.h>
     
    66#include <unistd.h>
    77extern "C" {
    8         #include <sched.h>
    98        #include <signal.h>
    109        #include <sys/socket.h>
     
    6867        (this.self){ "Server Cluster", options.clopts.params };
    6968
    70         cpu_set_t fullset;
    71         CPU_ZERO(&fullset);
    72         int ret = sched_getaffinity(getpid(), sizeof(fullset), &fullset);
    73         if( ret != 0 ) abort | "sched_getaffinity failed with" | errno | strerror( errno );
    74         int cnt = CPU_COUNT(&fullset);
    75 
    7669        this.procs = alloc(options.clopts.nprocs);
    7770        for(i; options.clopts.nprocs) {
    7871                (this.procs[i]){ "Benchmark Processor", this.self };
    79 
    80                 int c = 0;
    81                 int n = 1 + (i % cnt);
    82                 for(int j = 0; j < CPU_SETSIZE; j++) {
    83                         if(CPU_ISSET(j, &fullset)) n--;
    84                         if(n == 0) {
    85                                 c = j;
    86                                 break;
    87                         }
    88                 }
    89                 cpu_set_t localset;
    90                 CPU_ZERO(&localset);
    91                 CPU_SET(c, &localset);
    92                 ret = pthread_setaffinity_np(this.procs[i].kernel_thread, sizeof(localset), &localset);
    93                 if( ret != 0 ) abort | "sched_getaffinity failed with" | ret | strerror( ret );
    9472
    9573                #if !defined(__CFA_NO_STATISTICS__)
     
    168146        int waited = 0;
    169147        for() {
    170                 int sockfd = server_fd;
    171                 __CONST_SOCKADDR_ARG addr;
    172                 addr.__sockaddr__ = (struct sockaddr *)&address;
    173                 socklen_t addrlen = sizeof(address);
    174                 ret = bind( sockfd, addr, addrlen );
     148                ret = bind( server_fd, (struct sockaddr *)&address, sizeof(address) );
    175149                if(ret < 0) {
    176150                        if(errno == EADDRINUSE) {
  • benchmark/readyQ/churn.cfa

    r97fed44 rf57f6ea0  
    2121        wait( sem );
    2222        for() {
    23                 uint32_t r = prng();
     23                uint64_t r = thread_rand();
    2424                bench_sem * next = __atomic_exchange_n(&spots[r % spot_cnt], &sem, __ATOMIC_SEQ_CST);
    2525                if(next) post( *next );
  • benchmark/readyQ/locality.cfa

    r97fed44 rf57f6ea0  
    128128__attribute__((noinline)) void work(MyData & data, size_t cnt_, uint64_t & state) {
    129129        for (cnt_) {
    130                 access(data, xorshift_13_7_17(state));
     130                access(data, __xorshift64(state));
    131131        }
    132132}
    133133
    134134void main(MyThread & this) {
    135         uint64_t state = prng();
     135        uint64_t state = thread_rand();
    136136
    137137        // Wait for start
     
    144144
    145145                // Wait on a random spot
    146                 uint64_t idx = xorshift_13_7_17(state) % this.spots.len;
     146                uint64_t idx = __xorshift64(state) % this.spots.len;
    147147                bool closed = put(*this.spots.ptr[idx], this, this.data, this.share);
    148148
  • benchmark/readyQ/transfer.cfa

    r97fed44 rf57f6ea0  
    11#include "rq_bench.hfa"
    22#include <fstream.hfa>
    3 #include <locale.h>
    43
    54Duration default_preemption() {
     
    98#define PRINT(...)
    109
    11 __uint128_t lead_seed;
     10__lehmer64_state_t lead_seed;
    1211volatile unsigned leader;
    1312volatile size_t lead_idx;
     
    6968        waitgroup();
    7069
    71         unsigned nleader = lehmer64( lead_seed ) % nthreads;
     70        unsigned nleader = __lehmer64( lead_seed ) % nthreads;
    7271        __atomic_store_n( &leader, nleader, __ATOMIC_SEQ_CST );
    7372
     
    106105// ==================================================
    107106int main(int argc, char * argv[]) {
    108         uint64_t lead_seed = getpid();
    109         for(10) lehmer64( lead_seed );
     107        __lehmer64_state_t lead_seed = getpid();
     108        for(10) __lehmer64( lead_seed );
    110109        unsigned nprocs = 2;
    111110
     
    127126
    128127        lead_idx = 0;
    129         leader = lehmer64( lead_seed ) % nthreads;
     128        leader = __lehmer64( lead_seed ) % nthreads;
    130129
    131130        size_t rechecks = 0;
     
    168167        }
    169168
    170         setlocale( LC_NUMERIC, getenv( "LANG" ) );
    171169        sout | "Duration (ms)           : " | ws(3, 3, unit(eng((end - start)`dms)));
    172170        sout | "Number of processors    : " | nprocs;
  • libcfa/prelude/Makefile.am

    r97fed44 rf57f6ea0  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Thu Jan 13 17:06:27 2022
    14 ## Update Count     : 215
     13## Last Modified On : Mon Feb  3 21:27:18 2020
     14## Update Count     : 208
    1515###############################################################################
    1616
     
    3737# create extra forward types/declarations to reduce inclusion of library files
    3838extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c
    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' >> ${@}
     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
    4241
    4342# create forward declarations for gcc builtins
    4443gcc-builtins.cf : gcc-builtins.c ${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 >> ${@}
     44        ${AM_V_GEN}gcc -I${srcdir} -E -P $< | sed -r -f ${srcdir}/prototypes.sed > $@
    4745
    4846gcc-builtins.c : ${srcdir}/builtins.def ${srcdir}/prototypes.awk ${srcdir}/sync-builtins.cf ${srcdir}/prototypes.c
    49         ${AM_V_GEN}gcc -I${srcdir} -E ${srcdir}/prototypes.c | awk -f ${srcdir}/prototypes.awk > ${@}
     47        ${AM_V_GEN}gcc -I${srcdir} -E ${srcdir}/prototypes.c | awk -f ${srcdir}/prototypes.awk > $@
    5048
    5149prelude.cfa : prelude-gen.cc
    5250        ${AM_V_GEN}${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} ${AM_CFLAGS} ${<} -o prelude-gen -Wall -Wextra -O2 -g -std=c++14
    53         @./prelude-gen > ${@}
     51        @./prelude-gen > $@
    5452        @rm ./prelude-gen
    5553
     
    6058# create forward declarations for cfa builtins
    6159builtins.cf : builtins.c @LOCAL_CFACC@
    62         ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
     60        ${AM_V_GEN}gcc ${AM_CFLAGS} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
    6361        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
    6462
     
    6664
    6765bootloader.c : ${srcdir}/bootloader.cf prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACPP@
    68         ${AM_V_GEN}@CFACPP@ --prelude-dir=${builddir} -tpm ${srcdir}/bootloader.cf ${@}  # use src/cfa-cpp as not in lib until after install
     66        ${AM_V_GEN}@CFACPP@ --prelude-dir=${builddir} -tpm ${srcdir}/bootloader.cf $@  # use src/cfa-cpp as not in lib until after install
    6967
    7068maintainer-clean-local :
  • libcfa/src/bits/random.hfa

    r97fed44 rf57f6ea0  
    1 //
    2 // Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
    3 //
    4 // The contents of this file are covered under the licence agreement in the
    5 // file "LICENCE" distributed with Cforall.
    6 //
    7 // random.hfa --
    8 //
    9 // Author           : Peter A. Buhr
    10 // Created On       : Fri Jan 14 07:18:11 2022
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 07:18:58 2022
    13 // Update Count     : 1
    14 //
    15 
    161#pragma once
    172
    183#include <stdint.h>
    194
    20 // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is returned
    21 // (copied), and then compute and store the next random value.
    22 
     5//--------------------------------------------------
    236#if defined(__SIZEOF_INT128__)
    24 //--------------------------------------------------
    25         static inline uint64_t lehmer64( __uint128_t & state ) {
    26                 __uint128_t ret = state;
     7        typedef __uint128_t __lehmer64_state_t;
     8        static inline uint64_t __lehmer64( __lehmer64_state_t & state ) {
    279                state *= 0xda942042e4dd58b5;
    28                 return ret >> 64;
     10                return state >> 64;
    2911        }
    3012
    3113//--------------------------------------------------
    32         static inline uint64_t wyhash64( uint64_t & state ) {
     14        typedef uint64_t __wyhash64_state_t;
     15        static inline uint64_t __wyhash64( __wyhash64_state_t & state ) {
    3316                state += 0x60bee2bee120fc15;
    3417                __uint128_t tmp;
     
    4225
    4326//--------------------------------------------------
    44 static inline uint64_t xorshift_13_7_17( uint64_t & state ) {
    45         uint64_t ret = state;
    46         state ^= state << 13;
    47         state ^= state >> 7;
    48         state ^= state << 17;
    49         return ret;
     27typedef uint64_t __xorshift64_state_t;
     28static 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;
    5034}
    51 
    52 //--------------------------------------------------
    53 static inline uint32_t xorshift_6_21_7( uint32_t & state ) {
    54         uint32_t ret = state;
    55         state ^= state << 6;
    56         state ^= state >> 21;
    57         state ^= state << 7;
    58         return ret;
    59 } // xorshift_6_21_7
    6035
    6136//--------------------------------------------------
     
    6338  uint32_t a, b, c, d;
    6439  uint32_t counter;
    65 } xorwow__state_t;
     40} __xorwow__state_t;
    6641
    67 // The state array must be initialized to not be all zero in the first four words.
    68 static inline uint32_t xorwow( xorwow__state_t & state ) {
    69         // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs".
    70         uint32_t ret = state.a + state.counter;
     42/* The state array must be initialized to not be all zero in the first four words */
     43static inline uint32_t __xorwow( __xorwow__state_t & state ) {
     44        /* Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs" */
    7145        uint32_t t = state.d;
    7246
     
    8256
    8357        state.counter += 362437;
    84         return ret;
     58        return t + state.counter;
    8559}
    86 
    87 //--------------------------------------------------
    88 static inline uint32_t LCG( uint32_t & state ) {                // linear congruential generator
    89         uint32_t ret = state;
    90         state = 36969 * (state & 65535) + (state >> 16);        // 36969 is NOT prime! No not change it!
    91         return ret;
    92 } // LCG
    93 
    94 //--------------------------------------------------
    95 #define M  (1_l64u << 48_l64u)
    96 #define A  (25214903917_l64u)
    97 #define AI (18446708753438544741_l64u)
    98 #define C  (11_l64u)
    99 #define D  (16_l64u)
    100 
    101 // Bi-directional LCG random-number generator
    102 static inline uint32_t LCGBI_fwd( uint64_t & state ) {
    103         state = (A * state + C) & (M - 1);
    104         return state >> D;
    105 }
    106 
    107 static inline uint32_t LCGBI_bck( uint64_t & state ) {
    108         unsigned int r = state >> D;
    109         state = AI * (state - C) & (M - 1);
    110         return r;
    111 }
    112 
    113 #undef M
    114 #undef A
    115 #undef AI
    116 #undef C
    117 #undef D
  • libcfa/src/common.hfa

    r97fed44 rf57f6ea0  
    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.hfa --
    8 //
     6// 
     7// common --
     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

    r97fed44 rf57f6ea0  
    2222#include "thread.hfa"
    2323#include "time.hfa"
    24 #include "stdlib.hfa"
    2524
    2625#include "cfathread.h"
     
    196195                                eevent.data.u64 = (uint64_t)active_thread();
    197196
    198                                 int id = prng() % poller_cnt;
     197                                int id = thread_rand() % poller_cnt;
    199198                                if(0 != epoll_ctl(poller_fds[id], EPOLL_CTL_ADD, fd, &eevent))
    200199                                {
  • libcfa/src/concurrency/io.cfa

    r97fed44 rf57f6ea0  
    144144                __ioarbiter_flush( ctx );
    145145
    146                 if(ctx.sq.to_submit != 0 || min_comp > 0) {
    147 
    148                         __STATS__( true, io.calls.flush++; )
    149                         int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, min_comp, min_comp > 0 ? IORING_ENTER_GETEVENTS : 0, (sigset_t *)0p, _NSIG / 8);
    150                         if( ret < 0 ) {
    151                                 switch((int)errno) {
    152                                 case EAGAIN:
    153                                 case EINTR:
    154                                 case EBUSY:
    155                                         // Update statistics
    156                                         __STATS__( false, io.calls.errors.busy ++; )
    157                                         return false;
    158                                 default:
    159                                         abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) );
    160                                 }
     146                __STATS__( true, io.calls.flush++; )
     147                int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, min_comp, min_comp > 0 ? IORING_ENTER_GETEVENTS : 0, (sigset_t *)0p, _NSIG / 8);
     148                if( ret < 0 ) {
     149                        switch((int)errno) {
     150                        case EAGAIN:
     151                        case EINTR:
     152                        case EBUSY:
     153                                // Update statistics
     154                                __STATS__( false, io.calls.errors.busy ++; )
     155                                return false;
     156                        default:
     157                                abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) );
    161158                        }
    162 
    163                         __cfadbg_print_safe(io, "Kernel I/O : %u submitted to io_uring %d\n", ret, ctx.fd);
    164                         __STATS__( true, io.calls.submitted += ret; )
    165                         /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num );
    166                         /* paranoid */ verify( ctx.sq.to_submit >= ret );
    167 
    168                         ctx.sq.to_submit -= ret;
    169 
    170                         /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num );
    171 
    172                         // Release the consumed SQEs
    173                         __release_sqes( ctx );
    174 
    175                         /* paranoid */ verify( ! __preemption_enabled() );
    176 
    177                         ctx.proc->io.pending = false;
    178                 }
    179 
     159                }
     160
     161                __cfadbg_print_safe(io, "Kernel I/O : %u submitted to io_uring %d\n", ret, ctx.fd);
     162                __STATS__( true, io.calls.submitted += ret; )
     163                /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num );
     164                /* paranoid */ verify( ctx.sq.to_submit >= ret );
     165
     166                ctx.sq.to_submit -= ret;
     167
     168                /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num );
     169
     170                // Release the consumed SQEs
     171                __release_sqes( ctx );
     172
     173                /* paranoid */ verify( ! __preemption_enabled() );
     174
     175                ctx.proc->io.pending = false;
    180176                ready_schedule_lock();
    181177                bool ret = __cfa_io_drain( proc );
  • libcfa/src/concurrency/kernel.cfa

    r97fed44 rf57f6ea0  
    205205                                // Don't block if we are done
    206206                                if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
     207
     208                                #if !defined(__CFA_NO_STATISTICS__)
     209                                        __tls_stats()->ready.sleep.halts++;
     210                                #endif
    207211
    208212                                // Push self to idle stack
     
    728732// Wake a thread from the front if there are any
    729733static void __wake_one(cluster * this) {
     734        /* paranoid */ verify( ! __preemption_enabled() );
     735        /* paranoid */ verify( ready_schedule_islocked() );
     736
     737        // Check if there is a sleeping processor
     738        // int fd = __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST);
     739        int fd = 0;
     740        if( __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST) != 0 ) {
     741                fd = __atomic_exchange_n(&this->procs.fd, 0, __ATOMIC_RELAXED);
     742        }
     743
     744        // If no one is sleeping, we are done
     745        if( fd == 0 ) return;
     746
     747        // We found a processor, wake it up
    730748        eventfd_t val;
    731 
    732         /* paranoid */ verify( ! __preemption_enabled() );
    733         /* paranoid */ verify( ready_schedule_islocked() );
    734 
    735         // Check if there is a sleeping processor
    736         struct __fd_waitctx * fdp = __atomic_load_n(&this->procs.fdw, __ATOMIC_SEQ_CST);
    737 
    738         // If no one is sleeping: we are done
    739         if( fdp == 0p ) return;
    740 
    741         int fd = 1;
    742         if( __atomic_load_n(&fdp->fd, __ATOMIC_SEQ_CST) != 1 ) {
    743                 fd = __atomic_exchange_n(&fdp->fd, 1, __ATOMIC_RELAXED);
    744         }
    745 
    746         switch(fd) {
    747         case 0:
    748                 // If the processor isn't ready to sleep then the exchange will already wake it up
    749                 #if !defined(__CFA_NO_STATISTICS__)
    750                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.early++;
    751                         } else { __atomic_fetch_add(&this->stats->ready.sleep.early, 1, __ATOMIC_RELAXED); }
    752                 #endif
    753                 break;
    754         case 1:
    755                 // If someone else already said they will wake them: we are done
    756                 #if !defined(__CFA_NO_STATISTICS__)
    757                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.seen++;
    758                         } else { __atomic_fetch_add(&this->stats->ready.sleep.seen, 1, __ATOMIC_RELAXED); }
    759                 #endif
    760                 break;
    761         default:
    762                 // If the processor was ready to sleep, we need to wake it up with an actual write
    763                 val = 1;
    764                 eventfd_write( fd, val );
    765 
    766                 #if !defined(__CFA_NO_STATISTICS__)
    767                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.wakes++;
    768                         } else { __atomic_fetch_add(&this->stats->ready.sleep.wakes, 1, __ATOMIC_RELAXED); }
    769                 #endif
    770                 break;
    771         }
     749        val = 1;
     750        eventfd_write( fd, val );
     751
     752        #if !defined(__CFA_NO_STATISTICS__)
     753                if( kernelTLS().this_stats ) {
     754                        __tls_stats()->ready.sleep.wakes++;
     755                }
     756                else {
     757                        __atomic_fetch_add(&this->stats->ready.sleep.wakes, 1, __ATOMIC_RELAXED);
     758                }
     759        #endif
    772760
    773761        /* paranoid */ verify( ready_schedule_islocked() );
     
    782770
    783771        __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
    784 
    785         this->idle_wctx.fd = 1;
    786772
    787773        eventfd_t val;
     
    793779
    794780static void idle_sleep(processor * this, io_future_t & future, iovec & iov) {
    795         // Tell everyone we are ready to go do sleep
    796         for() {
    797                 int expected = this->idle_wctx.fd;
    798 
    799                 // Someone already told us to wake-up! No time for a nap.
    800                 if(expected == 1) { return; }
    801 
    802                 // Try to mark that we are going to sleep
    803                 if(__atomic_compare_exchange_n(&this->idle_wctx.fd, &expected, this->idle_fd, false,  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
    804                         // Every one agreed, taking a nap
    805                         break;
    806                 }
    807         }
    808 
    809 
    810781        #if !defined(CFA_WITH_IO_URING_IDLE)
    811782                #if !defined(__CFA_NO_STATISTICS__)
     
    854825
    855826static bool mark_idle(__cluster_proc_list & this, processor & proc) {
    856         #if !defined(__CFA_NO_STATISTICS__)
    857                 __tls_stats()->ready.sleep.halts++;
    858         #endif
    859 
    860         proc.idle_wctx.fd = 0;
    861 
    862827        /* paranoid */ verify( ! __preemption_enabled() );
    863828        if(!try_lock( this )) return false;
     
    867832                insert_first(this.idles, proc);
    868833
    869                 __atomic_store_n(&this.fdw, &proc.idle_wctx, __ATOMIC_SEQ_CST);
     834                __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST);
    870835        unlock( this );
    871836        /* paranoid */ verify( ! __preemption_enabled() );
     
    883848
    884849                {
    885                         struct __fd_waitctx * wctx = 0;
    886                         if(!this.idles`isEmpty) wctx = &this.idles`first.idle_wctx;
    887                         __atomic_store_n(&this.fdw, wctx, __ATOMIC_SEQ_CST);
     850                        int fd = 0;
     851                        if(!this.idles`isEmpty) fd = this.idles`first.idle_fd;
     852                        __atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST);
    888853                }
    889854
  • libcfa/src/concurrency/kernel.hfa

    r97fed44 rf57f6ea0  
    5555};
    5656
    57 
    58 struct __fd_waitctx {
    59         volatile int fd;
    60 };
    61 
    6257// Wrapper around kernel threads
    6358struct __attribute__((aligned(128))) processor {
     
    7267                unsigned target;
    7368                unsigned last;
    74                 signed   cpu;
     69                unsigned cnt;
     70                unsigned long long int cutoff;
    7571        } rdq;
    7672
     
    106102        int idle_fd;
    107103
    108         // Idle waitctx
    109         struct __fd_waitctx idle_wctx;
    110 
    111104        // Termination synchronisation (user semaphore)
    112105        oneshot terminated;
     
    159152        volatile unsigned long long tv;
    160153        volatile unsigned long long ma;
    161 };
    162 
    163 struct __attribute__((aligned(16))) __cache_id_t {
    164         volatile unsigned id;
    165154};
    166155
     
    175164static inline void ^?{}(__timestamp_t & this) {}
    176165
    177 struct __attribute__((aligned(128))) __ready_queue_caches_t;
    178 void  ?{}(__ready_queue_caches_t & this);
    179 void ^?{}(__ready_queue_caches_t & this);
    180 
    181166//TODO adjust cache size to ARCHITECTURE
    182 // Structure holding the ready queue
     167// Structure holding the relaxed ready queue
    183168struct __ready_queue_t {
    184169        // Data tracking the actual lanes
     
    193178                __timestamp_t * volatile tscs;
    194179
    195                 __cache_id_t * volatile caches;
    196 
    197180                // Array of stats
    198181                __help_cnts_t * volatile help;
     
    215198
    216199        // FD to use to wake a processor
    217         struct __fd_waitctx * volatile fdw;
     200        volatile int fd;
    218201
    219202        // Total number of processors
  • libcfa/src/concurrency/kernel/fwd.hfa

    r97fed44 rf57f6ea0  
    7979                        return
    8080                        #if defined(__SIZEOF_INT128__)
    81                                 lehmer64( kernelTLS().rand_seed );
     81                                __lehmer64( kernelTLS().rand_seed );
    8282                        #else
    83                                 xorshift_13_7_17( kernelTLS().rand_seed );
     83                                __xorshift64( kernelTLS().rand_seed );
    8484                        #endif
    8585                }
    8686
     87                #define M  (1_l64u << 48_l64u)
     88                #define A  (25214903917_l64u)
     89                #define AI (18446708753438544741_l64u)
     90                #define C  (11_l64u)
     91                #define D  (16_l64u)
     92
    8793                static inline unsigned __tls_rand_fwd() {
    88                         return LCGBI_fwd( kernelTLS().ready_rng.fwd_seed );
     94                        kernelTLS().ready_rng.fwd_seed = (A * kernelTLS().ready_rng.fwd_seed + C) & (M - 1);
     95                        return kernelTLS().ready_rng.fwd_seed >> D;
    8996                }
    9097
    9198                static inline unsigned __tls_rand_bck() {
    92                         return LCGBI_bck( kernelTLS().ready_rng.bck_seed );
    93                 }
     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
    94109
    95110                static inline void __tls_rand_advance_bck(void) {
     
    125140                        }
    126141                }
     142
     143                extern uint64_t thread_rand();
    127144
    128145                // Semaphore which only supports a single thread
  • libcfa/src/concurrency/kernel/startup.cfa

    r97fed44 rf57f6ea0  
    3434#include "kernel_private.hfa"
    3535#include "startup.hfa"          // STARTUP_PRIORITY_XXX
    36 #include "limits.hfa"
    3736#include "math.hfa"
    3837
     
    178177
    179178
     179
    180180//=============================================================================================
    181181// Kernel Setup logic
     
    515515        this.rdq.its = 0;
    516516        this.rdq.itr = 0;
    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;
     517        this.rdq.id  = -1u;
     518        this.rdq.target = -1u;
     519        this.rdq.last = -1u;
     520        this.rdq.cutoff = 0ull;
    522521        do_terminate = false;
    523522        preemption_alarm = 0p;
     
    537536        }
    538537
    539         this.idle_wctx.fd = 0;
    540 
    541         // I'm assuming these two are reserved for standard input and output
    542         // so I'm using them as sentinels with idle_wctx.
    543         /* paranoid */ verify( this.idle_fd != 0 );
    544         /* paranoid */ verify( this.idle_fd != 1 );
    545 
    546538        #if !defined(__CFA_NO_STATISTICS__)
    547539                print_stats = 0;
     
    597589// Cluster
    598590static void ?{}(__cluster_proc_list & this) {
    599         this.fdw   = 0p;
     591        this.fd    = 0;
    600592        this.idle  = 0;
    601593        this.total = 0;
     
    694686        uint_fast32_t last_size;
    695687        [this->unique_id, last_size] = ready_mutate_register();
    696 
    697                 this->rdq.cpu = __kernel_getcpu();
    698688
    699689                this->cltr->procs.total += 1u;
  • libcfa/src/concurrency/locks.hfa

    r97fed44 rf57f6ea0  
    3131
    3232//-----------------------------------------------------------------------------
     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
     39struct Semaphore0nary {
     40        __spinlock_t lock; // needed to protect
     41        mpsc_queue(thread$) queue;
     42};
     43
     44static 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
     52static inline bool P(Semaphore0nary & this) {
     53    thread$ * thrd = active_thread();
     54    P(this, thrd);
     55    park();
     56    return true;
     57}
     58
     59static 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
     74struct BinaryBenaphore {
     75        volatile ssize_t counter;
     76};
     77
     78static 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
     113struct ThreadBenaphore {
     114        BinaryBenaphore ben;
     115        Semaphore0nary  sem;
     116};
     117
     118static inline void ?{}(ThreadBenaphore & this) {}
     119static inline void ?{}(ThreadBenaphore & this, zero_t) { (this.ben){ 0 }; }
     120static inline void ?{}(ThreadBenaphore & this, one_t ) { (this.ben){ 1 }; }
     121
     122static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
     123static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
     124static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
     125
     126static inline thread$ * V(ThreadBenaphore & this, bool doUnpark = true) {
     127        if (V(this.ben)) return 0p;
     128        return V(this.sem, doUnpark);
     129}
     130
     131//-----------------------------------------------------------------------------
    33132// Semaphore
    34133struct semaphore {
     
    72171static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    73172static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
     173
     174struct fast_lock {
     175        thread$ * volatile owner;
     176        ThreadBenaphore sem;
     177};
     178
     179static inline void ?{}(fast_lock & this) __attribute__((deprecated("use linear_backoff_then_block_lock instead")));
     180static inline void ?{}(fast_lock & this) { this.owner = 0p; }
     181
     182static 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
     187static inline void lock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
     188static 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
     198static inline bool try_lock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
     199static 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
     205static inline thread$ * unlock( fast_lock & this ) __attribute__((deprecated("use linear_backoff_then_block_lock instead"), artificial));
     206static 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
     217static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
     218static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
     219static inline void on_notify( fast_lock &, struct thread$ * t ) { unpark(t); }
    74220
    75221struct mcs_node {
  • libcfa/src/concurrency/ready_queue.cfa

    r97fed44 rf57f6ea0  
    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
    2625
    2726#include "bits/defs.hfa"
     
    3029
    3130#include "stdlib.hfa"
    32 #include "limits.hfa"
    3331#include "math.hfa"
    3432
     
    5654#endif
    5755
    58 #if   defined(USE_AWARE_STEALING)
    59         #define READYQ_SHARD_FACTOR 2
    60         #define SEQUENTIAL_SHARD 2
    61 #elif defined(USE_CPU_WORK_STEALING)
     56#if   defined(USE_CPU_WORK_STEALING)
    6257        #define READYQ_SHARD_FACTOR 2
    6358#elif defined(USE_RELAXED_FIFO)
     
    143138        __kernel_rseq_register();
    144139
     140        __cfadbg_print_safe(ready_queue, "Kernel : Registering proc %p for RW-Lock\n", proc);
    145141        bool * handle = (bool *)&kernelTLS().sched_lock;
    146142
     
    178174        }
    179175
     176        __cfadbg_print_safe(ready_queue, "Kernel : Registering proc %p done, id %lu\n", proc, n);
     177
    180178        // Return new spot.
    181179        /* paranoid */ verify(n < ready);
     
    192190
    193191        __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();
     
    201201uint_fast32_t ready_mutate_lock( void ) with(*__scheduler_lock) {
    202202        /* paranoid */ verify( ! __preemption_enabled() );
     203        /* paranoid */ verify( ! kernelTLS().sched_lock );
    203204
    204205        // Step 1 : lock global lock
     
    206207        //   to simply lock their own lock and enter.
    207208        __atomic_acquire( &write_lock );
    208 
    209         // Make sure we won't deadlock ourself
    210         // Checking before acquiring the writer lock isn't safe
    211         // because someone else could have locked us.
    212         /* paranoid */ verify( ! kernelTLS().sched_lock );
    213209
    214210        // Step 2 : lock per-proc lock
     
    248244
    249245//=======================================================================
    250 // caches handling
    251 
    252 struct __attribute__((aligned(128))) __ready_queue_caches_t {
    253         // Count States:
    254         // - 0  : No one is looking after this cache
    255         // - 1  : No one is looking after this cache, BUT it's not empty
    256         // - 2+ : At least one processor is looking after this cache
    257         volatile unsigned count;
    258 };
    259 
    260 void  ?{}(__ready_queue_caches_t & this) { this.count = 0; }
    261 void ^?{}(__ready_queue_caches_t & this) {}
    262 
    263 static inline void depart(__ready_queue_caches_t & cache) {
    264         /* paranoid */ verify( cache.count > 1);
    265         __atomic_fetch_add(&cache.count, -1, __ATOMIC_SEQ_CST);
    266         /* paranoid */ verify( cache.count != 0);
    267         /* 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.
    268 }
    269 
    270 static inline void arrive(__ready_queue_caches_t & cache) {
    271         // for() {
    272         //      unsigned expected = cache.count;
    273         //      unsigned desired  = 0 == expected ? 2 : expected + 1;
    274         // }
    275 }
    276 
    277 //=======================================================================
    278246// Cforall Ready Queue used for scheduling
    279247//=======================================================================
    280 unsigned long long moving_average(unsigned long long currtsc, unsigned long long instsc, unsigned long long old_avg) {
    281         /* paranoid */ verifyf( currtsc < 45000000000000000, "Suspiciously large current time: %'llu (%llx)\n", currtsc, currtsc );
    282         /* paranoid */ verifyf( instsc  < 45000000000000000, "Suspiciously large insert time: %'llu (%llx)\n", instsc, instsc );
    283         /* paranoid */ verifyf( old_avg < 15000000000000, "Suspiciously large previous average: %'llu (%llx)\n", old_avg, old_avg );
    284 
    285         const unsigned long long new_val = currtsc > instsc ? currtsc - instsc : 0;
    286         const unsigned long long total_weight = 16;
    287         const unsigned long long new_weight   = 4;
    288         const unsigned long long old_weight = total_weight - new_weight;
    289         const unsigned long long ret = ((new_weight * new_val) + (old_weight * old_avg)) / total_weight;
    290         return ret;
     248unsigned 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;
    291253}
    292254
     
    309271                }
    310272        #else
    311                 lanes.data   = 0p;
    312                 lanes.tscs   = 0p;
    313                 lanes.caches = 0p;
    314                 lanes.help   = 0p;
    315                 lanes.count  = 0;
     273                lanes.data  = 0p;
     274                lanes.tscs  = 0p;
     275                lanes.help  = 0p;
     276                lanes.count = 0;
    316277        #endif
    317278}
     
    324285        free(lanes.data);
    325286        free(lanes.tscs);
    326         free(lanes.caches);
    327287        free(lanes.help);
    328288}
    329289
    330290//-----------------------------------------------------------------------
    331 #if defined(USE_AWARE_STEALING)
    332         __attribute__((hot)) void push(struct cluster * cltr, struct thread$ * thrd, unpark_hint hint) with (cltr->ready_queue) {
    333                 processor * const proc = kernelTLS().this_processor;
    334                 const bool external = (!proc) || (cltr != proc->cltr);
    335                 const bool remote   = hint == UNPARK_REMOTE;
    336 
    337                 unsigned i;
    338                 if( external || remote ) {
    339                         // Figure out where thread was last time and make sure it's valid
    340                         /* paranoid */ verify(thrd->preferred >= 0);
    341                         if(thrd->preferred * READYQ_SHARD_FACTOR < lanes.count) {
    342                                 /* paranoid */ verify(thrd->preferred * READYQ_SHARD_FACTOR < lanes.count);
    343                                 unsigned start = thrd->preferred * READYQ_SHARD_FACTOR;
    344                                 do {
    345                                         unsigned r = __tls_rand();
    346                                         i = start + (r % READYQ_SHARD_FACTOR);
    347                                         /* paranoid */ verify( i < lanes.count );
    348                                         // If we can't lock it retry
    349                                 } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
    350                         } else {
    351                                 do {
    352                                         i = __tls_rand() % lanes.count;
    353                                 } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
    354                         }
    355                 } else {
    356                         do {
    357                                 unsigned r = proc->rdq.its++;
    358                                 i = proc->rdq.id + (r % READYQ_SHARD_FACTOR);
    359                                 /* paranoid */ verify( i < lanes.count );
    360                                 // If we can't lock it retry
    361                         } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
    362                 }
    363 
    364                 // Actually push it
    365                 push(lanes.data[i], thrd);
    366 
    367                 // Unlock and return
    368                 __atomic_unlock( &lanes.data[i].lock );
    369 
    370                 #if !defined(__CFA_NO_STATISTICS__)
    371                         if(unlikely(external || remote)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.success, 1, __ATOMIC_RELAXED);
    372                         else __tls_stats()->ready.push.local.success++;
    373                 #endif
    374         }
    375 
    376         static inline unsigned long long calc_cutoff(const unsigned long long ctsc, const processor * proc, __ready_queue_t & rdq) {
    377                 unsigned start = proc->rdq.id;
    378                 unsigned long long max = 0;
    379                 for(i; READYQ_SHARD_FACTOR) {
    380                         unsigned long long ptsc = ts(rdq.lanes.data[start + i]);
    381                         if(ptsc != -1ull) {
    382                                 /* paranoid */ verify( start + i < rdq.lanes.count );
    383                                 unsigned long long tsc = moving_average(ctsc, ptsc, rdq.lanes.tscs[start + i].ma);
    384                                 if(tsc > max) max = tsc;
    385                         }
    386                 }
    387                 return (max + 2 * max) / 2;
    388         }
    389 
    390         __attribute__((hot)) struct thread$ * pop_fast(struct cluster * cltr) with (cltr->ready_queue) {
    391                 /* paranoid */ verify( lanes.count > 0 );
    392                 /* paranoid */ verify( kernelTLS().this_processor );
    393                 /* paranoid */ verify( kernelTLS().this_processor->rdq.id < lanes.count );
    394 
    395                 processor * const proc = kernelTLS().this_processor;
    396                 unsigned this = proc->rdq.id;
    397                 /* paranoid */ verify( this < lanes.count );
    398                 __cfadbg_print_safe(ready_queue, "Kernel : pop from %u\n", this);
    399 
    400                 // Figure out the current cpu and make sure it is valid
    401                 const int cpu = __kernel_getcpu();
    402                 /* paranoid */ verify(cpu >= 0);
    403                 /* paranoid */ verify(cpu < cpu_info.hthrd_count);
    404                 unsigned this_cache = cpu_info.llc_map[cpu].cache;
    405 
    406                 // Super important: don't write the same value over and over again
    407                 // We want to maximise our chances that his particular values stays in cache
    408                 if(lanes.caches[this / READYQ_SHARD_FACTOR].id != this_cache)
    409                         __atomic_store_n(&lanes.caches[this / READYQ_SHARD_FACTOR].id, this_cache, __ATOMIC_RELAXED);
    410 
    411                 const unsigned long long ctsc = rdtscl();
    412 
    413                 if(proc->rdq.target == MAX) {
    414                         uint64_t chaos = __tls_rand();
    415                         unsigned ext = chaos & 0xff;
    416                         unsigned other  = (chaos >> 8) % (lanes.count);
    417 
    418                         if(ext < 3 || __atomic_load_n(&lanes.caches[other / READYQ_SHARD_FACTOR].id, __ATOMIC_RELAXED) == this_cache) {
    419                                 proc->rdq.target = other;
    420                         }
    421                 }
    422                 else {
    423                         const unsigned target = proc->rdq.target;
    424                         __cfadbg_print_safe(ready_queue, "Kernel : %u considering helping %u, tcsc %llu\n", this, target, lanes.tscs[target].tv);
    425                         /* paranoid */ verify( lanes.tscs[target].tv != MAX );
    426                         if(target < lanes.count) {
    427                                 const unsigned long long cutoff = calc_cutoff(ctsc, proc, cltr->ready_queue);
    428                                 const unsigned long long age = moving_average(ctsc, lanes.tscs[target].tv, lanes.tscs[target].ma);
    429                                 __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");
    430                                 if(age > cutoff) {
    431                                         thread$ * t = try_pop(cltr, target __STATS(, __tls_stats()->ready.pop.help));
    432                                         if(t) return t;
    433                                 }
    434                         }
    435                         proc->rdq.target = MAX;
    436                 }
    437 
    438                 for(READYQ_SHARD_FACTOR) {
    439                         unsigned i = this + (proc->rdq.itr++ % READYQ_SHARD_FACTOR);
    440                         if(thread$ * t = try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.local))) return t;
    441                 }
    442 
    443                 // All lanes where empty return 0p
    444                 return 0p;
    445 
    446         }
    447         __attribute__((hot)) struct thread$ * pop_slow(struct cluster * cltr) with (cltr->ready_queue) {
    448                 unsigned i = __tls_rand() % lanes.count;
    449                 return try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.steal));
    450         }
    451         __attribute__((hot)) struct thread$ * pop_search(struct cluster * cltr) {
    452                 return search(cltr);
    453         }
    454 #endif
    455291#if defined(USE_CPU_WORK_STEALING)
    456292        __attribute__((hot)) void push(struct cluster * cltr, struct thread$ * thrd, unpark_hint hint) with (cltr->ready_queue) {
     
    514350                /* paranoid */ verify( kernelTLS().this_processor );
    515351
    516                 processor * const proc = kernelTLS().this_processor;
    517352                const int cpu = __kernel_getcpu();
    518353                /* paranoid */ verify(cpu >= 0);
     
    525360                /* 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);
    526361
     362                processor * const proc = kernelTLS().this_processor;
    527363                const int start = map.self * READYQ_SHARD_FACTOR;
    528364                const unsigned long long ctsc = rdtscl();
    529365
    530366                // Did we already have a help target
    531                 if(proc->rdq.target == MAX) {
     367                if(proc->rdq.target == -1u) {
    532368                        unsigned long long max = 0;
    533369                        for(i; READYQ_SHARD_FACTOR) {
    534                                 unsigned long long tsc = moving_average(ctsc, ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
     370                                unsigned long long tsc = moving_average(ctsc - ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
    535371                                if(tsc > max) max = tsc;
    536372                        }
    537                         // proc->rdq.cutoff = (max + 2 * max) / 2;
     373                        proc->rdq.cutoff = (max + 2 * max) / 2;
    538374                        /* paranoid */ verify(lanes.count < 65536); // The following code assumes max 65536 cores.
    539375                        /* paranoid */ verify(map.count < 65536); // The following code assumes max 65536 cores.
     
    548384                        }
    549385
    550                         /* paranoid */ verify(proc->rdq.target != MAX);
     386                        /* paranoid */ verify(proc->rdq.target != -1u);
    551387                }
    552388                else {
    553389                        unsigned long long max = 0;
    554390                        for(i; READYQ_SHARD_FACTOR) {
    555                                 unsigned long long tsc = moving_average(ctsc, ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
     391                                unsigned long long tsc = moving_average(ctsc - ts(lanes.data[start + i]), lanes.tscs[start + i].ma);
    556392                                if(tsc > max) max = tsc;
    557393                        }
     
    559395                        {
    560396                                unsigned target = proc->rdq.target;
    561                                 proc->rdq.target = MAX;
     397                                proc->rdq.target = -1u;
    562398                                lanes.help[target / READYQ_SHARD_FACTOR].tri++;
    563                                 if(moving_average(ctsc, lanes.tscs[target].tv, lanes.tscs[target].ma) > cutoff) {
     399                                if(moving_average(ctsc - lanes.tscs[target].tv, lanes.tscs[target].ma) > cutoff) {
    564400                                        thread$ * t = try_pop(cltr, target __STATS(, __tls_stats()->ready.pop.help));
    565401                                        proc->rdq.last = target;
    566402                                        if(t) return t;
     403                                        else proc->rdq.target = -1u;
    567404                                }
    568                                 proc->rdq.target = MAX;
     405                                else proc->rdq.target = -1u;
    569406                        }
    570407
    571408                        unsigned last = proc->rdq.last;
    572                         if(last != MAX && moving_average(ctsc, lanes.tscs[last].tv, lanes.tscs[last].ma) > cutoff) {
     409                        if(last != -1u && lanes.tscs[last].tv < cutoff && ts(lanes.data[last]) < cutoff) {
    573410                                thread$ * t = try_pop(cltr, last __STATS(, __tls_stats()->ready.pop.help));
    574411                                if(t) return t;
    575412                        }
    576413                        else {
    577                                 proc->rdq.last = MAX;
     414                                proc->rdq.last = -1u;
    578415                        }
    579416                }
     
    591428                processor * const proc = kernelTLS().this_processor;
    592429                unsigned last = proc->rdq.last;
    593                 if(last != MAX) {
     430                if(last != -1u) {
    594431                        struct thread$ * t = try_pop(cltr, last __STATS(, __tls_stats()->ready.pop.steal));
    595432                        if(t) return t;
    596                         proc->rdq.last = MAX;
     433                        proc->rdq.last = -1u;
    597434                }
    598435
     
    723560                #else
    724561                        unsigned preferred = thrd->preferred;
    725                         const bool external = (hint != UNPARK_LOCAL) || (!kernelTLS().this_processor) || preferred == MAX || thrd->curr_cluster != cltr;
     562                        const bool external = (hint != UNPARK_LOCAL) || (!kernelTLS().this_processor) || preferred == -1u || thrd->curr_cluster != cltr;
    726563                        /* paranoid */ verifyf(external || preferred < lanes.count, "Invalid preferred queue %u for %u lanes", preferred, lanes.count );
    727564
     
    775612                processor * proc = kernelTLS().this_processor;
    776613
    777                 if(proc->rdq.target == MAX) {
     614                if(proc->rdq.target == -1u) {
    778615                        unsigned long long min = ts(lanes.data[proc->rdq.id]);
    779616                        for(int i = 0; i < READYQ_SHARD_FACTOR; i++) {
     
    786623                else {
    787624                        unsigned target = proc->rdq.target;
    788                         proc->rdq.target = MAX;
     625                        proc->rdq.target = -1u;
    789626                        const unsigned long long bias = 0; //2_500_000_000;
    790627                        const unsigned long long cutoff = proc->rdq.cutoff > bias ? proc->rdq.cutoff - bias : proc->rdq.cutoff;
     
    821658// try to pop from a lane given by index w
    822659static inline struct thread$ * try_pop(struct cluster * cltr, unsigned w __STATS(, __stats_readyQ_pop_t & stats)) with (cltr->ready_queue) {
    823         /* paranoid */ verify( w < lanes.count );
    824660        __STATS( stats.attempt++; )
    825661
     
    845681        // Actually pop the list
    846682        struct thread$ * thrd;
    847         #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
     683        #if defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
    848684                unsigned long long tsc_before = ts(lane);
    849685        #endif
     
    861697        __STATS( stats.success++; )
    862698
    863         #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
    864                 if (tsv != MAX) {
    865                         unsigned long long now = rdtscl();
    866                         unsigned long long pma = __atomic_load_n(&lanes.tscs[w].ma, __ATOMIC_RELAXED);
    867                         __atomic_store_n(&lanes.tscs[w].tv, tsv, __ATOMIC_RELAXED);
    868                         __atomic_store_n(&lanes.tscs[w].ma, moving_average(now, tsc_before, pma), __ATOMIC_RELAXED);
    869                 }
     699        #if defined(USE_WORK_STEALING) || defined(USE_CPU_WORK_STEALING)
     700                unsigned long long now = rdtscl();
     701                lanes.tscs[w].tv = tsv;
     702                lanes.tscs[w].ma = moving_average(now > tsc_before ? now - tsc_before : 0, lanes.tscs[w].ma);
    870703        #endif
    871704
    872         #if defined(USE_AWARE_STEALING) || defined(USE_CPU_WORK_STEALING)
     705        #if defined(USE_CPU_WORK_STEALING)
    873706                thrd->preferred = w / READYQ_SHARD_FACTOR;
    874707        #else
     
    969802                /* paranoid */ verifyf( it, "Unexpected null iterator, at index %u of %u\n", i, count);
    970803                it->rdq.id = value;
    971                 it->rdq.target = MAX;
     804                it->rdq.target = -1u;
    972805                value += READYQ_SHARD_FACTOR;
    973806                it = &(*it)`next;
     
    982815
    983816static void fix_times( struct cluster * cltr ) with( cltr->ready_queue ) {
    984         #if defined(USE_AWARE_STEALING) || defined(USE_WORK_STEALING)
     817        #if defined(USE_WORK_STEALING)
    985818                lanes.tscs = alloc(lanes.count, lanes.tscs`realloc);
    986819                for(i; lanes.count) {
    987                         lanes.tscs[i].tv = rdtscl();
    988                         lanes.tscs[i].ma = 0;
     820                        unsigned long long tsc1 = ts(lanes.data[i]);
     821                        unsigned long long tsc2 = rdtscl();
     822                        lanes.tscs[i].tv = min(tsc1, tsc2);
    989823                }
    990824        #endif
     
    1032866                        // Update original
    1033867                        lanes.count = ncount;
    1034 
    1035                         lanes.caches = alloc( target, lanes.caches`realloc );
    1036868                }
    1037869
     
    1110942                                fix(lanes.data[idx]);
    1111943                        }
    1112 
    1113                         lanes.caches = alloc( target, lanes.caches`realloc );
    1114944                }
    1115945
    1116946                fix_times(cltr);
    1117 
    1118947
    1119948                reassign_cltr_id(cltr);
  • libcfa/src/concurrency/stats.cfa

    r97fed44 rf57f6ea0  
    3131                stats->ready.sleep.halts   = 0;
    3232                stats->ready.sleep.cancels = 0;
    33                 stats->ready.sleep.early   = 0;
    3433                stats->ready.sleep.wakes   = 0;
    35                 stats->ready.sleep.seen    = 0;
    3634                stats->ready.sleep.exits   = 0;
    3735
     
    9391                tally_one( &cltr->ready.sleep.halts       , &proc->ready.sleep.halts        );
    9492                tally_one( &cltr->ready.sleep.cancels     , &proc->ready.sleep.cancels      );
    95                 tally_one( &cltr->ready.sleep.early       , &proc->ready.sleep.early        );
    9693                tally_one( &cltr->ready.sleep.wakes       , &proc->ready.sleep.wakes        );
    97                 tally_one( &cltr->ready.sleep.seen        , &proc->ready.sleep.wakes        );
    9894                tally_one( &cltr->ready.sleep.exits       , &proc->ready.sleep.exits        );
    9995
     
    157153                             | " (" | eng3(ready.pop.search.attempt) | " try)";
    158154
    159                         sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel,"
    160                              | eng3(ready.sleep.wakes + ready.sleep.early) | '(' | eng3(ready.sleep.early) | ',' | eng3(ready.sleep.seen) | ')' | " wake(early, seen),"
    161                              | eng3(ready.sleep.exits) | "exit";
     155                        sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel," | eng3(ready.sleep.wakes) | "wake," | eng3(ready.sleep.exits) | "exit";
    162156                        sstr | nl;
    163157                }
  • libcfa/src/concurrency/stats.hfa

    r97fed44 rf57f6ea0  
    6969                        volatile uint64_t halts;
    7070                        volatile uint64_t cancels;
    71                         volatile uint64_t early;
    7271                        volatile uint64_t wakes;
    73                         volatile uint64_t seen;
    7472                        volatile uint64_t exits;
    7573                } sleep;
  • libcfa/src/concurrency/thread.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan 13 20:11:55 2022
    13 // Update Count     : 42
     12// Last Modified On : Wed Jan 12 18:46:48 2022
     13// Update Count     : 36
    1414//
    1515
     
    2424#define __CFA_INVOKE_PRIVATE__
    2525#include "invoke.h"
     26
     27uint64_t thread_rand();
    2628
    2729extern uint32_t __global_random_seed;
     
    172174}
    173175
    174 //-----------------------------------------------------------------------------
     176uint64_t thread_rand() {
     177        disable_interrupts();
     178        uint64_t ret = __tls_rand();
     179        enable_interrupts();
     180        return ret;
     181}
     182 
    175183#define GENERATOR LCG
     184
     185static inline uint32_t MarsagliaXor( uint32_t & state ) {
     186        uint32_t ret = state;
     187        state ^= state << 6;
     188        state ^= state >> 21;
     189        state ^= state << 7;
     190        return ret;
     191} // MarsagliaXor
     192
     193static inline uint32_t LCG( uint32_t & state ) {                // linear congruential generator
     194        uint32_t ret = state;
     195        state = 36969 * (state & 65535) + (state >> 16);        // 36969 is NOT prime! No not change it!
     196        return ret;
     197} // LCG
    176198
    177199void set_seed( uint32_t seed ) {
  • libcfa/src/iostream.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan 19 08:15:53 2022
    13 // Update Count     : 1352
     12// Last Modified On : Sun Oct 10 09:28:17 2021
     13// Update Count     : 1345
    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        } // ?|?
     
    205205        ostype & ?|?( ostype & os, float f ) {
    206206                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    207                 PrintWithDP( os, "%'g", f );
     207                PrintWithDP( os, "%g", f );
    208208                return os;
    209209        } // ?|?
     
    214214        ostype & ?|?( ostype & os, double d ) {
    215215                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    216                 PrintWithDP( os, "%'.*lg", d, DBL_DIG );
     216                PrintWithDP( os, "%.*lg", d, DBL_DIG );
    217217                return os;
    218218        } // ?|?
     
    223223        ostype & ?|?( ostype & os, long double ld ) {
    224224                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    225                 PrintWithDP( os, "%'.*Lg", ld, LDBL_DIG );
     225                PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
    226226                return os;
    227227        } // ?|?
     
    233233                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    234234//              os | crealf( fc ) | nonl;
    235                 PrintWithDP( os, "%'g", crealf( fc ) );
    236                 PrintWithDP( os, "%'+g", cimagf( fc ) );
     235                PrintWithDP( os, "%g", crealf( fc ) );
     236                PrintWithDP( os, "%+g", cimagf( fc ) );
    237237                fmt( os, "i" );
    238238                return os;
     
    245245                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    246246//              os | creal( dc ) | nonl;
    247                 PrintWithDP( os, "%'.*lg", creal( dc ), DBL_DIG );
    248                 PrintWithDP( os, "%'+.*lg", cimag( dc ), DBL_DIG );
     247                PrintWithDP( os, "%.*lg", creal( dc ), DBL_DIG );
     248                PrintWithDP( os, "%+.*lg", cimag( dc ), DBL_DIG );
    249249                fmt( os, "i" );
    250250                return os;
     
    257257                if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
    258258//              os | creall( ldc ) || nonl;
    259                 PrintWithDP( os, "%'.*Lg", creall( ldc ), LDBL_DIG );
    260                 PrintWithDP( os, "%'+.*Lg", cimagl( ldc ), LDBL_DIG );
     259                PrintWithDP( os, "%.*Lg", creall( ldc ), LDBL_DIG );
     260                PrintWithDP( os, "%+.*Lg", cimagl( ldc ), LDBL_DIG );
    261261                fmt( os, "i" );
    262262                return os;
     
    282282                }; // mask
    283283
    284           if ( s == 0p ) { fmt( os, "%s", "0p" ); return os; } // null pointer
    285284          if ( s[0] == '\0' ) { sepOff( os ); return os; } // null string => no separator
    286285
     
    497496                if ( ! f.flags.pc ) memcpy( &fmtstr, IFMTNP, sizeof(IFMTNP) ); \
    498497                else memcpy( &fmtstr, IFMTP, sizeof(IFMTP) ); \
    499                 int star = 5;                                                                   /* position before first '*' */ \
     498                int star = 4;                                                                   /* position before first '*' */ \
    500499\
    501500                /* Insert flags into spaces before '*', from right to left. */ \
     
    504503                if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \
    505504                if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \
    506                 fmtstr[star] = '\''; star -= 1;                                 /* locale */ \
    507505                fmtstr[star] = '%'; \
    508506\
     
    523521} // distribution
    524522
    525 IntegralFMTImpl( signed char,            "      *hh ", "      *.*hh " )
    526 IntegralFMTImpl( unsigned char,          "      *hh ", "      *.*hh " )
    527 IntegralFMTImpl( signed short int,       "      *h ",  "      *.*h " )
    528 IntegralFMTImpl( unsigned short int,     "      *h ",  "      *.*h " )
    529 IntegralFMTImpl( signed int,             "      * ",   "      *.* " )
    530 IntegralFMTImpl( unsigned int,           "      * ",   "      *.* " )
    531 IntegralFMTImpl( signed long int,        "      *l ",  "      *.*l " )
    532 IntegralFMTImpl( unsigned long int,      "      *l ",  "      *.*l " )
    533 IntegralFMTImpl( signed long long int,   "      *ll ", "      *.*ll " )
    534 IntegralFMTImpl( unsigned long long int, "      *ll ", "      *.*ll " )
     523IntegralFMTImpl( signed char, "     *hh ", "     *.*hh " )
     524IntegralFMTImpl( unsigned char, "     *hh ", "     *.*hh " )
     525IntegralFMTImpl( signed short int, "     *h ", "     *.*h " )
     526IntegralFMTImpl( unsigned short int, "     *h ", "     *.*h " )
     527IntegralFMTImpl( signed int, "     * ", "     *.* " )
     528IntegralFMTImpl( unsigned int, "     * ", "     *.* " )
     529IntegralFMTImpl( signed long int, "     *l ", "     *.*l " )
     530IntegralFMTImpl( unsigned long int, "     *l ", "     *.*l " )
     531IntegralFMTImpl( signed long long int, "     *ll ", "     *.*ll " )
     532IntegralFMTImpl( unsigned long long int, "     *ll ", "     *.*ll " )
    535533
    536534
     
    694692                if ( ! f.flags.pc ) memcpy( &fmtstr, DFMTNP, sizeof(DFMTNP) ); \
    695693                else memcpy( &fmtstr, DFMTP, sizeof(DFMTP) ); \
    696                 int star = 5;                                                                   /* position before first '*' */ \
     694                int star = 4;                                                                   /* position before first '*' */ \
    697695\
    698696                /* Insert flags into spaces before '*', from right to left. */ \
     
    700698                if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \
    701699                if ( f.flags.pad0 ) { fmtstr[star] = '0'; star -= 1; } \
    702                 fmtstr[star] = '\''; star -= 1;                                 /* locale */ \
    703700                fmtstr[star] = '%'; \
    704701\
     
    718715} // distribution
    719716
    720 FloatingPointFMTImpl( double,      "      * ",  "      *.* " )
    721 FloatingPointFMTImpl( long double, "      *L ", "      *.*L " )
     717FloatingPointFMTImpl( double, "     * ", "     *.* " )
     718FloatingPointFMTImpl( long double, "     *L ", "     *.*L " )
    722719
    723720// *********************************** character ***********************************
  • libcfa/src/parseconfig.cfa

    r97fed44 rf57f6ea0  
    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 
    91#include <fstream.hfa>
    102#include <parseargs.hfa>
     
    2719// TODO: use string interface when it's ready (and implement exception msg protocol)
    2820[ void ] msg( * Missing_Config_Entries ex ) {
    29         serr | "The config file is missing " | ex->num_missing | "entr" | sepOff | (ex->num_missing == 1 ? "y." : "ies.");
     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        }
    3029} // msg
    3130
     
    224223        return value < zero_val;
    225224}
    226 #pragma GCC diagnostic pop
    227225
    228226
  • libcfa/src/startup.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 17 16:41:54 2022
    13 // Update Count     : 55
     12// Last Modified On : Wed Jan 12 18:51:24 2022
     13// Update Count     : 51
    1414//
    1515
     
    1717#include <locale.h>                                                                             // setlocale
    1818#include <stdlib.h>                                                                             // getenv
    19 #include "bits/defs.hfa"                                                                // rdtscl
    2019#include "startup.hfa"
     20#include "bits/defs.hfa"
    2121
    22 extern uint32_t __global_random_seed;                                   // sequential/concurrent
    23 extern uint32_t __global_random_state;                                  // sequential
     22extern uint32_t __global_random_seed, __global_random_state;
    2423
    2524extern "C" {
     
    2726        void __cfaabi_appready_startup( void ) {
    2827                tzset();                                                                                // initialize time global variables
     28                setlocale( LC_NUMERIC, getenv("LANG") );
    2929                #ifdef __CFA_DEBUG__
    3030                extern void heapAppStart();
  • libcfa/src/stdlib.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan 13 21:38:30 2022
    13 // Update Count     : 593
     12// Last Modified On : Wed Jan 12 18:52:41 2022
     13// Update Count     : 582
    1414//
    1515
    1616#include "stdlib.hfa"
    17 #include "bits/random.hfa"
     17//#include "concurrency/kernel/fwd.hfa"
    1818#include "concurrency/invoke.h"                                                 // random_state
    1919
     
    223223//---------------------------------------
    224224
     225// Pipelined to allow OoO overlap with reduced dependencies. Critically, return the current value, and compute and store
     226// the next value.
     227
    225228#define GENERATOR LCG
    226229
     230static inline uint32_t MarsagliaXor( uint32_t & state ) {
     231        uint32_t ret = state;
     232        state ^= state << 6;
     233        state ^= state >> 21;
     234        state ^= state << 7;
     235        return ret;
     236} // MarsagliaXor
     237
     238static inline uint32_t LCG( uint32_t & state ) {                // linear congruential generator
     239        uint32_t ret = state;
     240        state = 36969 * (state & 65535) + (state >> 16);        // 36969 is NOT prime! No not change it!
     241        return ret;
     242} // LCG
     243
    227244uint32_t __global_random_seed;                                                  // sequential/concurrent
    228 uint32_t __global_random_state;                                         // sequential only
     245uint32_t __global_random_state;                                                 // sequential only
    229246
    230247void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; GENERATOR( state ); } // set seed
  • libcfa/src/stdlib.hfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan 13 21:34:46 2022
    13 // Update Count     : 636
     12// Last Modified On : Wed Jan 12 18:56:13 2022
     13// Update Count     : 621
    1414//
    1515
     
    208208
    209209        forall( TT... | { T * alloc_internal$( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
     210
    210211                T * alloc_internal$( void *       , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
    211212                return alloc_internal$( Resize, (T*)0p, Align, Dim, Fill, rest);
     
    231232                return alloc_internal$( (void*)0p, (T*)0p, (_Alignof(T) > libAlign() ? _Alignof(T) : libAlign()), dim, (S_fill(T)){'0'}, all);
    232233            }
     234
    233235        } // distribution TT
    234236} // distribution T
  • src/AST/Decl.cpp

    r97fed44 rf57f6ea0  
    2626#include "Node.hpp"            // for readonly
    2727#include "Type.hpp"            // for readonly
    28 #include "Expr.hpp"
    2928
    3029namespace ast {
     
    6665        for (auto & tp : this->type_params) {
    6766                ftype->forall.emplace_back(new TypeInstType(tp->name, tp));
    68                 for (auto & ap: tp->assertions) {
    69                         ftype->assertions.emplace_back(new VariableExpr(loc, ap));
    70                 }
    7167        }
    7268        this->type = ftype;
  • src/AST/Decl.hpp

    r97fed44 rf57f6ea0  
    3434// Must be included in *all* AST classes; should be #undef'd at the end of the file
    3535#define MUTATE_FRIEND \
    36         template<typename node_t> friend node_t * mutate(const node_t * node); \
     36    template<typename node_t> friend node_t * mutate(const node_t * node); \
    3737        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3838
     
    135135        std::vector< ptr<Expr> > withExprs;
    136136
     137
    137138        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
    138139                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
  • src/AST/Eval.hpp

    r97fed44 rf57f6ea0  
    2424template< typename... Args >
    2525UntypedExpr * call( const CodeLocation & loc, const std::string & name, Args &&... args ) {
    26         return new UntypedExpr {
    27                 loc, new NameExpr { loc, name },
     26        return new UntypedExpr { 
     27                loc, new NameExpr { loc, name }, 
    2828                std::vector< ptr< Expr > > { std::forward< Args >( args )... } };
    2929}
  • src/AST/Print.cpp

    r97fed44 rf57f6ea0  
    333333                print( node->funcSpec );
    334334
    335 
    336 
    337                 if ( node->type && node->isTypeFixed ) {
     335                if ( node->type ) {
    338336                        node->type->accept( *this );
    339337                } else {
    340                         if (!node->type_params.empty()) {
    341                                 os << "forall" << endl;
    342                                 ++indent;
    343                                 printAll(node->type_params);
    344                                 os << indent;
    345                                 --indent;
    346 
    347                                 if (!node->assertions.empty()) {
    348                                         os << "with assertions" << endl;
    349                                         ++indent;
    350                                         printAll(node->assertions);
    351                                         os << indent;
    352                                         --indent;
    353                                 }
    354                         }
    355 
    356                         os << "function" << endl;
    357                         if ( ! node->params.empty() ) {
    358                                 os << indent << "... with parameters" << endl;
    359                                 ++indent;
    360                                 printAll( node->params );
    361                                 if ( node->type->isVarArgs ) {
    362                                         os << indent << "and a variable number of other arguments" << endl;
    363                                 }
    364                                 --indent;
    365                         } else if ( node->type->isVarArgs ) {
    366                                 os << indent+1 << "accepting unspecified arguments" << endl;
    367                         }
    368 
    369                         os << indent << "... returning";
    370                         if ( node->returns.empty() ) {
    371                                 os << " nothing" << endl;
    372                         } else {
    373                                 os << endl;
    374                                 ++indent;
    375                                 printAll( node->returns );
    376                                 --indent;
    377                         }
     338                        os << "untyped entity";
    378339                }
    379340
  • src/Validate/InitializerLength.cpp

    r97fed44 rf57f6ea0  
    1414//
    1515
    16 #include "InitializerLength.hpp"
     16//#include "InitializerLength.hpp"
    1717
    1818#include "AST/Expr.hpp"
  • src/Validate/InitializerLength.hpp

    r97fed44 rf57f6ea0  
    1414//
    1515
    16 #pragma once
    17 
    18 namespace ast {
    19         class TranslationUnit;
    20 }
    21 
    2216namespace Validate {
    2317
  • tests/concurrent/.expect/ctor-check.txt

    r97fed44 rf57f6ea0  
    22?{}: function
    33... with parameters
    4   this: lvalue reference to instance of struct Empty with body
     4  lvalue reference to instance of struct Empty with body
    55... returning nothing
    66 with body
  • tests/concurrent/preempt.cfa

    r97fed44 rf57f6ea0  
    1 #include <fstream.hfa>
    21#include <kernel.hfa>
    32#include <thread.hfa>
     
    2625thread worker_t {
    2726        int value;
    28         unsigned spin;
    2927};
    3028
    3129void ?{}( worker_t & this, int value ) {
    3230        this.value = value;
    33         this.spin = 0;
    3431}
    3532
    3633void main(worker_t & this) {
    3734        while(TEST(counter < N)) {
    38                 if(this.spin > 100_000_000) abort | "Worker" | this.value | "has been spinning too long! (" | this.spin | ")";
    3935                __cfaabi_check_preemption();
    4036                if( (counter % 7) == this.value ) {
     
    4440                        if( (next % 100) == 0 ) printf("%d\n", (int)next);
    4541                        __cfaabi_check_preemption();
    46                         this.spin = 0;
    4742                }
    4843                __cfaabi_check_preemption();
    4944                KICK_WATCHDOG;
    50                 this.spin++;
    5145        }
    5246}
  • tests/device/cpu.cfa

    r97fed44 rf57f6ea0  
    1515
    1616
     17#include <fstream.hfa>
    1718#include <device/cpu.hfa>
    18 #include <limits.hfa>
    19 #include <fstream.hfa>
    2019#include <stdlib.hfa>
    2120
     
    119118
    120119        unsigned found_level = 0;
    121         unsigned found = MAX;
     120        unsigned found = -1u;
    122121        for(i; idxs) {
    123122                unsigned idx = idxs - 1 - i;
     
    137136        }
    138137
    139         /* paranoid */ verify(found != MAX);
     138        /* paranoid */ verify(found != -1u);
    140139        return found;
    141140}
  • tests/io/io-acquire-in.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 09:13:43 2022
    13 // Update Count     : 73
     12// Last Modified On : Wed Oct  6 18:04:58 2021
     13// Update Count     : 72
    1414//
    1515
     
    1717#include <thread.hfa>
    1818#include <mutex_stmt.hfa>
    19 
    20 Duration default_preemption() { return 0; }
    2119
    2220        // above output used as input to parallel threads
  • tests/io/io-acquire-no-io.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 09:13:54 2022
    13 // Update Count     : 73
     12// Last Modified On : Wed Oct  6 18:04:58 2021
     13// Update Count     : 72
    1414//
    1515
     
    1717#include <thread.hfa>
    1818#include <mutex_stmt.hfa>
    19 
    20 Duration default_preemption() { return 0; }
    2119
    2220multiple_acquisition_lock soutLock, sinLock;
  • tests/io/io-acquire-out.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 09:14:06 2022
    13 // Update Count     : 73
     12// Last Modified On : Wed Oct  6 18:04:58 2021
     13// Update Count     : 72
    1414//
    1515
     
    1717#include <thread.hfa>
    1818#include <mutex_stmt.hfa>
    19 
    20 Duration default_preemption() { return 0; }
    2119
    2220thread T {};
  • tests/io/io-acquire.cfa

    r97fed44 rf57f6ea0  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 09:13:18 2022
    13 // Update Count     : 74
     12// Last Modified On : Mon Jan 10 07:57:12 2022
     13// Update Count     : 73
    1414//
    1515
     
    1717#include <thread.hfa>
    1818#include <mutex_stmt.hfa>
    19 
    20 Duration default_preemption() { return 0; }
    2119
    2220thread T {};
  • tests/unified_locking/.expect/locks.txt

    r97fed44 rf57f6ea0  
    1111Start Test 6: owner lock and condition variable 3 wait/notify all
    1212Done Test 6
    13 Start Test 7: linear backoff lock and condition variable single wait/notify
     13Start Test 7: fast lock and condition variable single wait/notify
    1414Done Test 7
    15 Start Test 8: linear backoff lock and condition variable 3 wait/notify all
     15Start Test 8: fast lock and condition variable 3 wait/notify all
    1616Done Test 8
    17 Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify
     17Start Test 9: linear backoff lock and condition variable single wait/notify
    1818Done Test 9
    19 Start Test 10: owner lock and condition variable multiple acquire and wait/notify
     19Start Test 10: linear backoff lock and condition variable 3 wait/notify all
    2020Done Test 10
    21 Start Test 11: no lock condition variable wait/notify
     21Start Test 11: multi acquisiton lock and condition variable multiple acquire and wait/notify
    2222Done Test 11
    23 Start Test 12: locked condition variable wait/notify with front()
     23Start Test 12: owner lock and condition variable multiple acquire and wait/notify
    2424Done Test 12
     25Start Test 13: no lock condition variable wait/notify
     26Done Test 13
     27Start Test 14: locked condition variable wait/notify with front()
     28Done Test 14
  • tests/unified_locking/locks.cfa

    r97fed44 rf57f6ea0  
    1515condition_variable( owner_lock ) c_o;
    1616
     17fast_lock f;
     18condition_variable( fast_lock ) c_f;
     19
    1720linear_backoff_then_block_lock l;
    1821condition_variable( linear_backoff_then_block_lock ) c_l;
     
    7174                }
    7275                unlock(s);
     76        }
     77}
     78
     79thread T_C_F_WS1 {};
     80
     81void main( T_C_F_WS1 & this ) {
     82        for (unsigned int i = 0; i < num_times; i++) {
     83                lock(f);
     84                if(empty(c_f) && i != num_times - 1) {
     85                        wait(c_f,f);
     86                }else{
     87                        notify_one(c_f);
     88                }
     89                unlock(f);
     90        }
     91}
     92
     93thread T_C_F_WB1 {};
     94
     95void main( T_C_F_WB1 & this ) {
     96        for (unsigned int i = 0; i < num_times; i++) {
     97                lock(f);
     98                if(counter(c_f) == 3 || i == num_times - 1) {
     99                        notify_all(c_f);
     100                }else{
     101                        wait(c_f,f);
     102                }
     103                unlock(f);
    73104        }
    74105}
     
    286317        printf("Done Test 6\n");
    287318
    288         printf("Start Test 7: linear backoff lock and condition variable single wait/notify\n");
     319        printf("Start Test 7: fast lock and condition variable single wait/notify\n");
     320        {
     321                T_C_F_WS1 t1[2];
     322        }
     323        printf("Done Test 7\n");
     324
     325        printf("Start Test 8: fast lock and condition variable 3 wait/notify all\n");
     326        {
     327                T_C_F_WB1 t1[4];
     328        }
     329        printf("Done Test 8\n");
     330
     331        printf("Start Test 9: linear backoff lock and condition variable single wait/notify\n");
    289332        {
    290333                T_C_L_WS1 t1[2];
    291334        }
    292         printf("Done Test 7\n");
    293 
    294         printf("Start Test 8: linear backoff lock and condition variable 3 wait/notify all\n");
     335        printf("Done Test 9\n");
     336
     337        printf("Start Test 10: linear backoff lock and condition variable 3 wait/notify all\n");
    295338        {
    296339                T_C_L_WB1 t1[4];
    297340        }
    298         printf("Done Test 8\n");
    299 
    300         printf("Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
     341        printf("Done Test 10\n");
     342
     343        printf("Start Test 11: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
    301344        {
    302345                T_C_M_WS2 t1[2];
    303346        }
    304         printf("Done Test 9\n");
    305 
    306         printf("Start Test 10: owner lock and condition variable multiple acquire and wait/notify\n");
     347        printf("Done Test 11\n");
     348
     349        printf("Start Test 12: owner lock and condition variable multiple acquire and wait/notify\n");
    307350        {
    308351                T_C_O_WS2 t1[2];
    309352        }
    310         printf("Done Test 10\n");
    311 
    312         printf("Start Test 11: no lock condition variable wait/notify\n");
     353        printf("Done Test 12\n");
     354
     355        printf("Start Test 13: no lock condition variable wait/notify\n");
    313356        {
    314357                T_C_NLW t1;
    315358                T_C_NLS t2;
    316359        }
    317         printf("Done Test 11\n");
    318 
    319         printf("Start Test 12: locked condition variable wait/notify with front()\n");
     360        printf("Done Test 13\n");
     361
     362        printf("Start Test 14: locked condition variable wait/notify with front()\n");
    320363        {
    321364                T_C_S_WNF t1[2];
    322365        }
    323         printf("Done Test 12\n");
    324 }
     366        printf("Done Test 14\n");
     367}
Note: See TracChangeset for help on using the changeset viewer.