Changeset 5235d49


Ignore:
Timestamp:
Jan 1, 2022, 11:14:35 AM (3 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
12c1eef
Parents:
7770cc8 (diff), db1ebed (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
11 added
20 edited

Legend:

Unmodified
Added
Removed
  • driver/as.cc

    r7770cc8 r5235d49  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // as.c -- map assembler file, scan for debug information. If found, expand file by one character and insert Cforall
    8 //         language code on the N line from the start of the debug information.
     7// as.c -- map assembler file, scan for debug information, then language code, and skip N lines forward to code. If
     8//         code is C dialect, possibly expand file by one character, and replace with Cforall language code.
    99//
    1010// Author           : Peter A. Buhr
    1111// Created On       : Wed Aug  1 10:49:42 2018
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Sat Sep  8 08:40:16 2018
    14 // Update Count     : 97
     13// Last Modified On : Wed Dec  8 07:56:12 2021
     14// Update Count     : 136
    1515//
    1616
     
    1818#include <cstdlib>                                                                              // exit
    1919#include <fcntl.h>                                                                              // open
    20 #include <unistd.h>
    21 #include <sys/stat.h>
     20#include <cstring>                                                                              // strstr, memmove
     21#include <unistd.h>                                                                             // ftruncate,execvp
     22#include <sys/stat.h>                                                                   // fstat
    2223#include <sys/mman.h>                                                                   // mmap
    23 #include <string.h>
    2424
    2525//#define __DEBUG_H__
    26 
    27 #ifdef __DEBUG_H__
    28 #include <iostream>
    29 using namespace std;
    30 #endif // __DEBUG_H__
    3126
    3227int main( const int argc, const char * argv[] ) {
    3328        #ifdef __DEBUG_H__
    3429        for ( int i = 0; i < argc; i += 1 ) {
    35                 cerr << argv[i] << endl;
     30                fprintf( stderr, "%s\n", argv[i] );
    3631        } // for
    3732        #endif // __DEBUG_H__
     
    4843                if ( start == (void *)-1 ) { perror( "mmap" ); exit( EXIT_FAILURE ); };
    4944
    50                 if ( char * cursor = strstr( start, ".Ldebug_info0:" ) ) { // debug information ?
    51                         // Expand file by one byte to hold 2 character Cforall language code.
    52                         if ( ftruncate( fd, size + 1 ) ) { perror( "ftruncate" ); exit( EXIT_FAILURE ); };
     45                char * dcursor;
     46                if ( (dcursor = strstr( start, ".Ldebug_info0:" ) ) ) { // debug information ?
    5347
    54                         for ( int i = 0; i < 8; i += 1 ) {                      // move N (magic) lines forward
    55                                 cursor = strstr( cursor, "\n" ) + 1;
    56                         } // for
     48                        if ( char * cursor = strstr( dcursor, ".long\t.LASF" ) ) { // language code ?
     49                                for ( int i = 0; i < 2; i += 1 ) {              // move N (magic) lines forward
     50                                        cursor = strstr( cursor, "\n" ) + 1;
     51                                } // for
     52                                cursor -= 2;                                                    // backup over "d\n", where d is a hex digit
     53                                // From elfcpp/dwarf.h in the binutils source tree.
     54                                // DW_LANG_C89 = 0x1, DW_LANG_C = 0x2, DW_LANG_C99 = 0xc, DW_LANG_C11 = 0x1d
     55                                if ( *(cursor - 2) == '0' && *(cursor - 1) == 'x' &&
     56                                         (*cursor == 'c' || *cursor == '1' || *cursor == '2') ) { // C99/C89/C
     57                                        // Expand file by one byte to hold 2 character Cforall language code.
     58                                        if ( ftruncate( fd, size + 1 ) ) { perror( "ftruncate" ); exit( EXIT_FAILURE ); };
     59                                        memmove( cursor + 2, cursor + 1, start + size - cursor - 1 ); // move remaining text 1 character right
     60                                } else if ( *(cursor - 3) == '0' && *(cursor - 2) == 'x' && *(cursor - 1) == '1' && *cursor == 'd' ) { // C11
     61                                } else {
     62                                        for ( int i = 0; i < 6; i += 1 ) {      // move N (magic) lines forward
     63                                                cursor = strstr( cursor, "\n" ) + 1;
     64                                        } // for
     65                                        fprintf( stderr, "*** ERROR *** Invalid C language code found in assembler file: %s\n"
     66                                                         "Assembler debug information:\n%.*s",
     67                                                         argv[argc - 1], (int)(cursor - dcursor), dcursor );
     68                                        exit( EXIT_FAILURE );
     69                                } // if
    5770
    58                         cursor -= 2;                                                            // backup over "c\n" language value
    59                         if ( *(cursor - 1) != 'x' ) { fprintf( stderr, "invalid C language code\n" ); exit( EXIT_FAILURE ); };
    60 
    61                         memmove( cursor + 2, cursor + 1, start + size - cursor - 1 ); // move remaining text 1 character right
    62 
    63                         *(cursor) = '2';                                                        // replace C language value with CFA
    64                         *(cursor + 1) = '5';
     71                                *(cursor - 1) = '2';                                    // replace C89/C/C99/C11 language code with CFA code
     72                                *cursor = '5';
     73                        } // if
    6574                } // if
    6675
  • libcfa/src/Makefile.am

    r7770cc8 r5235d49  
    8585        time.hfa \
    8686        bits/weakso_locks.hfa \
     87        algorithms/range_iterator.hfa \
    8788        containers/maybe.hfa \
    8889        containers/pair.hfa \
  • libcfa/src/concurrency/io.cfa

    r7770cc8 r5235d49  
    3333                #include <sys/syscall.h>
    3434                #include <sys/eventfd.h>
     35                #include <sys/uio.h>
    3536
    3637                #include <linux/io_uring.h>
     
    133134        }
    134135
    135         bool __cfa_io_flush( processor * proc, bool wait ) {
     136        bool __cfa_io_flush( processor * proc, int min_comp ) {
    136137                /* paranoid */ verify( ! __preemption_enabled() );
    137138                /* paranoid */ verify( proc );
     
    144145
    145146                __STATS__( true, io.calls.flush++; )
    146                 int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, wait ? 1 : 0, 0, (sigset_t *)0p, _NSIG / 8);
     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);
    147148                if( ret < 0 ) {
    148149                        switch((int)errno) {
     
    302303                ctx->proc->io.dirty   = true;
    303304                if(sq.to_submit > 30 || !lazy) {
    304                         __cfa_io_flush( ctx->proc, false );
     305                        __cfa_io_flush( ctx->proc, 0 );
    305306                }
    306307        }
     
    502503        }
    503504
    504         #if defined(IO_URING_IDLE)
    505                 bool __kernel_read(processor * proc, io_future_t & future, char buf[], int fd) {
     505        #if defined(CFA_WITH_IO_URING_IDLE)
     506                bool __kernel_read(processor * proc, io_future_t & future, iovec & iov, int fd) {
    506507                        $io_context * ctx = proc->io.ctx;
    507508                        /* paranoid */ verify( ! __preemption_enabled() );
     
    518519                        __fill( &sqe, 1, &idx, ctx );
    519520
    520                         sqe->opcode = IORING_OP_READ;
    521521                        sqe->user_data = (uintptr_t)&future;
    522522                        sqe->flags = 0;
     523                        sqe->fd = fd;
     524                        sqe->off = 0;
    523525                        sqe->ioprio = 0;
    524                         sqe->fd = 0;
    525                         sqe->off = 0;
    526526                        sqe->fsync_flags = 0;
    527527                        sqe->__pad2[0] = 0;
    528528                        sqe->__pad2[1] = 0;
    529529                        sqe->__pad2[2] = 0;
    530                         sqe->addr = (uintptr_t)buf;
    531                         sqe->len = sizeof(uint64_t);
     530
     531                        #if defined(CFA_HAVE_IORING_OP_READ)
     532                                sqe->opcode = IORING_OP_READ;
     533                                sqe->addr = (uint64_t)iov.iov_base;
     534                                sqe->len = iov.iov_len;
     535                        #elif defined(CFA_HAVE_READV) && defined(CFA_HAVE_IORING_OP_READV)
     536                                sqe->opcode = IORING_OP_READV;
     537                                sqe->addr = (uintptr_t)&iov;
     538                                sqe->len = 1;
     539                        #else
     540                                #error CFA_WITH_IO_URING_IDLE but none of CFA_HAVE_READV, CFA_HAVE_IORING_OP_READV or CFA_HAVE_IORING_OP_READ defined
     541                        #endif
    532542
    533543                        asm volatile("": : :"memory");
  • libcfa/src/concurrency/io/setup.cfa

    r7770cc8 r5235d49  
    3232
    3333        void __cfa_io_start( processor * proc ) {}
    34         bool __cfa_io_flush( processor * proc, bool ) {}
     34        bool __cfa_io_flush( processor * proc, int ) {}
    3535        void __cfa_io_stop ( processor * proc ) {}
    3636
     
    220220                cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
    221221
    222                 #if !defined(IO_URING_IDLE)
     222                #if !defined(CFA_WITH_IO_URING_IDLE)
    223223                        // Step 4 : eventfd
    224224                        // io_uring_register is so f*cking slow on some machine that it
  • libcfa/src/concurrency/kernel.cfa

    r7770cc8 r5235d49  
    2727extern "C" {
    2828        #include <sys/eventfd.h>
     29        #include <sys/uio.h>
    2930}
    3031
     
    125126static void __wake_one(cluster * cltr);
    126127
    127 static void idle_sleep(processor * proc, io_future_t & future, char buf[]);
     128static void idle_sleep(processor * proc, io_future_t & future, iovec & iov);
    128129static bool mark_idle (__cluster_proc_list & idles, processor & proc);
    129130static void mark_awake(__cluster_proc_list & idles, processor & proc);
     
    131132extern void __cfa_io_start( processor * );
    132133extern bool __cfa_io_drain( processor * );
    133 extern bool __cfa_io_flush( processor *, bool wait );
     134extern bool __cfa_io_flush( processor *, int min_comp );
    134135extern void __cfa_io_stop ( processor * );
    135136static inline bool __maybe_io_drain( processor * );
    136137
    137 #if defined(IO_URING_IDLE) && defined(CFA_HAVE_LINUX_IO_URING_H)
    138         extern bool __kernel_read(processor * proc, io_future_t & future, char buf[], int fd);
     138#if defined(CFA_WITH_IO_URING_IDLE)
     139        extern bool __kernel_read(processor * proc, io_future_t & future, iovec &, int fd);
    139140#endif
    140141
     
    171172        io_future_t future; // used for idle sleep when io_uring is present
    172173        future.self.ptr = 1p;  // mark it as already fulfilled so we know if there is a pending request or not
    173         char buf[sizeof(uint64_t)];
     174        eventfd_t idle_val;
     175        iovec idle_iovec = { &idle_val, sizeof(idle_val) };
    174176
    175177        __cfa_io_start( this );
     
    206208
    207209                        if( !readyThread ) {
    208                                 __cfa_io_flush( this, false );
     210                                __cfa_io_flush( this, 0 );
    209211
    210212                                readyThread = __next_thread_slow( this->cltr );
     
    237239                                }
    238240
    239                                 idle_sleep( this, future, buf );
     241                                idle_sleep( this, future, idle_iovec );
    240242
    241243                                // We were woken up, remove self from idle
     
    258260
    259261                        if(this->io.pending && !this->io.dirty) {
    260                                 __cfa_io_flush( this, false );
     262                                __cfa_io_flush( this, 0 );
    261263                        }
    262264
     
    274276
    275277                                // If we can't find a thread, might as well flush any outstanding I/O
    276                                 if(this->io.pending) { __cfa_io_flush( this, false ); }
     278                                if(this->io.pending) { __cfa_io_flush( this, 0 ); }
    277279
    278280                                // Spin a little on I/O, just in case
     
    369371
    370372                        if(this->io.pending && !this->io.dirty) {
    371                                 __cfa_io_flush( this, false );
     373                                __cfa_io_flush( this, 0 );
    372374                        }
    373375
     
    379381
    380382                __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this);
     383        }
     384
     385        for(int i = 0; !available(future); i++) {
     386                if(i > 1000) __cfaabi_dbg_write( "ERROR: kernel has bin spinning on a flush after exit loop.\n", 60);
     387                __cfa_io_flush( this, 1 );
    381388        }
    382389
     
    779786}
    780787
    781 static void idle_sleep(processor * this, io_future_t & future, char buf[]) {
    782         #if !defined(IO_URING_IDLE) || !defined(CFA_HAVE_LINUX_IO_URING_H)
     788static void idle_sleep(processor * this, io_future_t & future, iovec & iov) {
     789        #if !defined(CFA_WITH_IO_URING_IDLE)
    783790                #if !defined(__CFA_NO_STATISTICS__)
    784791                        if(this->print_halts) {
     
    813820                #endif
    814821        #else
    815                 #if !defined(CFA_HAVE_IORING_OP_READ)
    816                         #error this is only implemented if the read is present
    817                 #endif
    818822                // Do we already have a pending read
    819823                if(available(future)) {
     
    821825                        reset(future);
    822826
    823                         __kernel_read(this, future, buf, this->idle_fd );
    824                 }
    825 
    826                 __cfa_io_flush( this, true );
     827                        __kernel_read(this, future, iov, this->idle_fd );
     828                }
     829
     830                __cfa_io_flush( this, 1 );
    827831        #endif
    828832}
  • libcfa/src/concurrency/kernel_private.hfa

    r7770cc8 r5235d49  
    3939}
    4040
    41 // #define IO_URING_IDLE
     41// Defines whether or not we *want* to use io_uring_enter as the idle_sleep blocking call
     42#define CFA_WANT_IO_URING_IDLE
     43
     44// Defines whether or not we *can* use io_uring_enter as the idle_sleep blocking call
     45#if defined(CFA_WANT_IO_URING_IDLE) && defined(CFA_HAVE_LINUX_IO_URING_H)
     46        #if defined(CFA_HAVE_IORING_OP_READ) || (defined(CFA_HAVE_READV) && defined(CFA_HAVE_IORING_OP_READV))
     47                #define CFA_WITH_IO_URING_IDLE
     48        #endif
     49#endif
    4250
    4351//-----------------------------------------------------------------------------
  • libcfa/src/device/cpu.cfa

    r7770cc8 r5235d49  
    3030        #include <fcntl.h>
    3131}
     32
     33#include "algorithms/range_iterator.hfa"
    3234
    3335// search a string for character 'character' but looking atmost at len
     
    135137                count++;
    136138        }
    137         iterate_dir(path, lambda);
     139        int ret = iterate_dir(path, lambda);
     140        if(ret == ENOTDIR) return 0;
    138141
    139142        /* paranoid */ verifyf(count == max + 1, "Inconsistent %s count, counted %d, but max %s was %d", prefix, count, prefix, (int)max);
     
    143146
    144147// Count number of cpus in the system
    145 static int count_cpus(void) {
     148static [int, const char *] count_cpus(void) {
    146149        const char * fpath = "/sys/devices/system/cpu/online";
    147150        int fd = open(fpath, 0, O_RDONLY);
     
    159162
    160163        const char * _;
    161         int cnt = read_width(buff, r - 1, &_);
    162         /* paranoid */ verify(cnt == count_prefix_dirs("/sys/devices/system/cpu", "cpu"));
    163         return cnt;
     164        return [read_width(buff, r - 1, &_), strndup(buff, r - 1)];
    164165}
    165166
     
    226227
    227228struct raw_cache_instance {
    228         idx_range_t range;
    229         unsigned width;
    230         unsigned char level;
     229        idx_range_t range;      // A text description of the cpus covered
     230        unsigned width;         // The number of cpus covered
     231        unsigned char level;    // the cache level
    231232        // FIXME add at least size and type
    232233};
     
    235236static void ^?{}(raw_cache_instance & this) { free(this.range);}
    236237
    237 raw_cache_instance ** build_raw_cache_table(unsigned cpus, unsigned idxs, unsigned cache_levels)
     238// Returns a 2D array of instances of size [cpu count][cache levels]
     239// where cache level doesn't include instruction caches
     240raw_cache_instance ** build_raw_cache_table(unsigned cpus_c, idx_range_t cpus, unsigned idxs, unsigned cache_levels)
    238241{
    239         raw_cache_instance ** raw = alloc(cpus);
    240         for(i; cpus) {
     242        raw_cache_instance ** raw = alloc(cpus_c, '\0'`fill);
     243
     244        RangeIter rc = { cpus };
     245        while(moveNext(rc)) {
     246                unsigned i = rc.com;
    241247                raw[i] = alloc(cache_levels);
    242248                void addcache(unsigned fidx, unsigned char level, idx_range_t range, size_t len) {
     
    263269
    264270// returns an allocate list of all the different distinct last level caches
    265 static [*llc_map_t, size_t cnt] distinct_llcs(unsigned cpus, unsigned llc_idx, raw_cache_instance ** raw) {
     271static [*llc_map_t, size_t cnt] distinct_llcs(idx_range_t cpus, unsigned llc_idx, raw_cache_instance ** raw) {
    266272        // Allocate at least one element
    267273        llc_map_t* ranges = alloc();
    268274        size_t range_cnt = 1;
    269275
     276        RangeIter rc = { cpus };
     277        __attribute__((unused)) bool ret =
     278        moveNext(rc);
     279        /* paranoid */ verify( ret );
     280        /* paranoid */ verify( rc.com >= 0 );
     281
    270282        // Initialize with element 0
    271         ranges->raw = &raw[0][llc_idx];
     283        ranges->raw = &raw[rc.com][llc_idx];
    272284        ranges->count = 0;
    273285        ranges->start = -1u;
    274286
    275287        // Go over all other cpus
    276         CPU_LOOP: for(i; 1~cpus) {
     288        CPU_LOOP: while(moveNext(rc)) {
     289                unsigned i = rc.com;
    277290                // Check if the range is already there
    278291                raw_cache_instance * candidate = &raw[i][llc_idx];
     
    304317}
    305318
    306 static [[]cpu_pairing_t] get_cpu_pairings(unsigned cpus, raw_cache_instance ** raw, llc_map_t * maps, size_t map_cnt) {
    307         cpu_pairing_t * pairings = alloc(cpus);
    308 
    309         CPU_LOOP: for(i; cpus) {
     319static [[]cpu_pairing_t] get_cpu_pairings(unsigned cpus_c, idx_range_t cpus, raw_cache_instance ** raw, llc_map_t * maps, size_t map_cnt) {
     320        cpu_pairing_t * pairings = alloc(cpus_c);
     321
     322        RangeIter rc = { cpus };
     323        CPU_LOOP: while(moveNext(rc)) {
     324                unsigned i = rc.com;
    310325                pairings[i].cpu = i;
    311326                idx_range_t want = raw[i][0].range;
     
    327342extern "C" {
    328343        void __cfaabi_device_startup( void ) {
    329                 int cpus = count_cpus();
     344                int cpus_c;
     345                const char * cpus;
     346                [cpus_c, cpus] = count_cpus();
     347                #if defined(__CFA_WITH_VERIFY__)
     348                // Verify that the mapping is self consistant.
     349                {
     350                        RangeIter rc = { cpus };
     351                        while(moveNext(rc)) {
     352                                unsigned i = rc.com;
     353                                verify(cpus_c > i);
     354                        }
     355                }
     356                #endif
     357
    330358                int idxs = count_cache_indexes();
    331359
     
    333361                unsigned cache_levels = 0;
    334362                unsigned llc = 0;
    335                 {
     363                if (idxs != 0) {
    336364                        unsigned char prev = -1u;
    337365                        void first(unsigned idx, unsigned char level, const char * map, size_t len) {
     
    345373
    346374                // Read in raw data
    347                 raw_cache_instance ** raw = build_raw_cache_table(cpus, idxs, cache_levels);
     375                raw_cache_instance ** raw = build_raw_cache_table(cpus_c, cpus, idxs, cache_levels);
    348376
    349377                // Find number of distinct cache instances
     
    362390                                width2 += maps[i].raw->width;
    363391                        }
    364                         verify(width1 == cpus);
    365                         verify(width2 == cpus);
     392                        verify(width1 == cpus_c);
     393                        verify(width2 == cpus_c);
    366394                }
    367395                #endif
    368396
    369397                // Get mappings from cpu to cache instance
    370                 cpu_pairing_t * pairings = get_cpu_pairings(cpus, raw, maps, map_cnt);
     398                cpu_pairing_t * pairings = get_cpu_pairings(cpus_c, cpus, raw, maps, map_cnt);
    371399
    372400                // Sort by cache instance
    373                 qsort(pairings, cpus);
     401                qsort(pairings, cpus_c);
    374402
    375403                {
    376404                        unsigned it = 0;
    377                         for(i; cpus) {
     405                        RangeIter rc = { cpus };
     406                        while(moveNext(rc)) {
     407                                unsigned i = rc.com;
    378408                                unsigned llc_id = pairings[i].id;
    379409                                if(maps[llc_id].start == -1u) {
     
    384414                                }
    385415                        }
    386                         /* paranoid */ verify(it == cpus);
     416                        /* paranoid */ verify(it == cpus_c);
    387417                }
    388418
    389419                // From the mappings build the actual cpu map we want
    390                 struct cpu_map_entry_t * entries = alloc(cpus);
    391                 for(i; cpus) { entries[i].count = 0; }
    392                 for(i; cpus) {
     420                struct cpu_map_entry_t * entries = alloc(cpus_c);
     421                for(i; cpus_c) { entries[i].count = 0; }
     422
     423                RangeIter rc = { cpus };
     424                while(moveNext(rc)) {
     425                        unsigned i = rc.com;
    393426                        /* paranoid */ verify(pairings[i].id < map_cnt);
    394427                        unsigned c = pairings[i].cpu;
     
    406439                free(pairings);
    407440
    408                 for(i; cpus) {
    409                         for(j; cache_levels) {
     441                for(i; cpus_c) {
     442                        if( raw[i] ) for(j; cache_levels) {
    410443                                ^(raw[i][j]){};
    411444                        }
     
    415448
    416449                cpu_info.llc_map = entries;
    417                 cpu_info.hthrd_count = cpus;
     450                cpu_info.hthrd_count = cpus_c;
     451                cpu_info.llc_count = map_cnt;
    418452        }
    419453
  • libcfa/src/device/cpu.hfa

    r7770cc8 r5235d49  
    2323
    2424struct cpu_info_t {
    25          // array of size [hthrd_count]
     25        // Array of size [hthrd_count]
    2626        const cpu_map_entry_t * llc_map;
    2727
    28          // Number of _hardware_ threads present in the system
     28        // Number of _hardware_ threads present in the system
    2929        size_t hthrd_count;
     30
     31        // Number of distinct last level caches
     32        size_t llc_count;
    3033};
    3134
  • libcfa/src/stdlib.cfa

    r7770cc8 r5235d49  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov 12 07:46:09 2020
    13 // Update Count     : 503
     12// Last Modified On : Wed Dec 29 15:32:44 2021
     13// Update Count     : 512
    1414//
    1515
     
    221221//---------------------------------------
    222222
    223 bool threading_enabled(void) __attribute__((weak)) {
    224         return false;
    225 }
     223static uint32_t seed = 0;                                                               // current seed
     224static thread_local uint32_t state;                                             // random state
     225
     226void set_seed( uint32_t seed_ ) { state = seed = seed_; }
     227uint32_t get_seed() { return seed; }
     228
     229#define GENERATOR LCG
     230
     231inline uint32_t MarsagliaXor( uint32_t & state ) {
     232        if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
     233        else if ( unlikely( state == 0 ) ) state = seed;
     234        state ^= state << 6;
     235        state ^= state >> 21;
     236        state ^= state << 7;
     237        return state;
     238} // MarsagliaXor
     239
     240inline uint32_t LCG( uint32_t & state ) {                               // linear congruential generator
     241        if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
     242        else if ( unlikely( state == 0 ) ) state = seed;
     243        return state = 36973 * (state & 65535) + (state >> 16);
     244} // LCG
     245
     246uint32_t prng( PRNG & prng ) with( prng ) { callcnt += 1; return GENERATOR( state ); }
     247
     248uint32_t prng( void ) { return GENERATOR( state ); }
     249
     250//---------------------------------------
     251
     252bool threading_enabled( void ) __attribute__(( weak )) { return false; }
    226253
    227254// Local Variables: //
  • libcfa/src/stdlib.hfa

    r7770cc8 r5235d49  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 20 21:20:03 2021
    13 // Update Count     : 575
     12// Last Modified On : Wed Dec 29 15:30:58 2021
     13// Update Count     : 591
    1414//
    1515
     
    169169                return ret;
    170170        }
     171        S_fill(T)               ?`fill ( zero_t ) = void; // FIX ME: remove this once ticket 214 is resolved
     172        S_fill(T)               ?`fill ( T * a )                                { return (S_fill(T)){ 'T', '0', 0, a }; } // FIX ME: remove this once ticket 214 is resolved
    171173        S_fill(T)               ?`fill ( char c )                               { return (S_fill(T)){ 'c', c }; }
    172         S_fill(T)               ?`fill ( T * a )                                { return (S_fill(T)){ 'T', '0', 0, a }; }
    173174        S_fill(T)               ?`fill ( T a[], size_t nmemb )  { return (S_fill(T)){ 'a', '0', nmemb * sizeof(T), a }; }
    174175
     
    362363
    363364static inline {
    364         long int random( long int l, long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l) + l; } // [l,u)
    365         long int random( long int u ) { if ( u < 0 ) return random( u, 0 ); else return random( 0, u ); } // [0,u)
     365        long int random( long int l, long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l + 1) + l; } // [l,u]
     366        long int random( long int u ) { return random( 0, u - 1 ); } // [0,u)
    366367        unsigned long int random( void ) { return lrand48(); }
    367368        unsigned long int random( unsigned long int u ) { return lrand48() % u; } // [0,u)
    368         unsigned long int random( unsigned long int l, unsigned long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l) + l; } // [l,u)
     369        unsigned long int random( unsigned long int l, unsigned long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l + 1) + l; } // [l,u]
    369370
    370371        char random( void ) { return (unsigned long int)random(); }
     
    387388//---------------------------------------
    388389
     390struct PRNG {
     391        uint32_t callcnt;                                                                       // call count
     392        uint32_t seed;                                                                          // current seed
     393        uint32_t state;                                                                         // random state
     394}; // PRNG
     395
     396extern uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
     397static inline {
     398        void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; } // set seed
     399        void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); } // random seed
     400        void ?{}( PRNG & prng, uint32_t seed ) { set_seed( prng, seed ); } // fixed seed
     401        uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
     402        uint32_t prng( PRNG & prng, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng ) % u; } // [0,u)
     403        uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng, u - l + 1 ) + l; } // [l,u]
     404        uint32_t calls( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return callcnt; }
     405} // distribution
     406
     407extern void set_seed( uint32_t seed );                                  // set per thread seed
     408extern uint32_t get_seed();                                                             // get seed
     409extern uint32_t prng( void ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
     410static inline {
     411        uint32_t prng( uint32_t u ) __attribute__(( warn_unused_result ));
     412        uint32_t prng( uint32_t u ) { return prng() % u; }      // [0,u)
     413        uint32_t prng( uint32_t l, uint32_t u ) __attribute__(( warn_unused_result ));
     414        uint32_t prng( uint32_t l, uint32_t u ) { return prng( u - l + 1 ) + l; } // [l,u]
     415} // distribution
     416
     417//---------------------------------------
     418
    389419extern bool threading_enabled( void ) OPTIONAL_THREAD;
    390420
  • src/AST/Expr.cpp

    r7770cc8 r5235d49  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May 15 17:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Created On       : Thr Jun 13 13:38:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Created On       : Tue Nov 30 14:23:00 2021
     13// Update Count     : 7
    1414//
    1515
     
    141141        /// The type of the address of a type.
    142142        /// Caller is responsible for managing returned memory
    143         Type * addrType( const Type * type ) {
    144                 if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * >( type ) ) {
    145                         return new ReferenceType{ addrType( refType->base ), refType->qualifiers };
     143        Type * addrType( const ptr<Type> & type ) {
     144                if ( auto refType = type.as< ReferenceType >() ) {
     145                        return new ReferenceType( addrType( refType->base ), refType->qualifiers );
    146146                } else {
    147                         return new PointerType{ type };
     147                        return new PointerType( type );
    148148                }
    149149        }
    150 }
    151 
    152 AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    153         if ( arg->result ) {
    154                 if ( arg->get_lvalue() ) {
    155                         // lvalue, retains all levels of reference, and gains a pointer inside the references
    156                         Type * res = addrType( arg->result );
    157                         result = res;
     150
     151        /// The type of the address of an expression.
     152        /// Caller is responsible for managing returned memory
     153        Type * addrExprType( const CodeLocation & loc, const Expr * arg ) {
     154                assert( arg );
     155                // If the expression's type is unknown, the address type is unknown.
     156                if ( nullptr == arg->result ) {
     157                        return nullptr;
     158                // An lvalue is transformed directly.
     159                } else if ( arg->get_lvalue() ) {
     160                        return addrType( arg->result );
     161                // Strip a layer of reference to "create" an lvalue expression.
     162                } else if ( auto refType = arg->result.as< ReferenceType >() ) {
     163                        return addrType( refType->base );
    158164                } else {
    159                         // taking address of non-lvalue, must be a reference, loses one layer of reference
    160                         if ( const ReferenceType * refType =
    161                                         dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    162                                 Type * res = addrType( refType->base );
    163                                 result = res;
    164                         } else {
    165                                 SemanticError( loc, arg->result.get(),
    166                                         "Attempt to take address of non-lvalue expression: " );
    167                         }
     165                        SemanticError( loc, arg->result.get(),
     166                                "Attempt to take address of non-lvalue expression: " );
    168167                }
    169168        }
    170169}
     170
     171AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) :
     172        Expr( loc, addrExprType( loc, a ) ), arg( a )
     173{}
    171174
    172175// --- LabelAddressExpr
  • src/AST/Print.cpp

    r7770cc8 r5235d49  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Print.cpp --
     7// Print.cpp -- Print an AST (or sub-tree) to a stream.
    88//
    99// Author           : Thierry Delisle
  • src/AST/Print.hpp

    r7770cc8 r5235d49  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Print.hpp --
     7// Print.hpp -- Print an AST (or sub-tree) to a stream.
    88//
    99// Author           : Thierry Delisle
     
    3535template< typename Coll >
    3636void printAll( std::ostream & os, const Coll & c, Indenter indent = {} ) {
    37     for ( const auto & i : c ) {
    38         if ( ! i ) continue;
    39        
    40         os << indent;
    41         print( os, i, indent );
    42         os << std::endl;
    43     }
     37        for ( const auto & i : c ) {
     38                if ( ! i ) continue;
     39
     40                os << indent;
     41                print( os, i, indent );
     42                os << std::endl;
     43        }
    4444}
    4545
  • src/Concurrency/Keywords.h

    r7770cc8 r5235d49  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Keywords.h --
     7// Keywords.h -- Implement concurrency constructs from their keywords.
    88//
    99// Author           : Thierry Delisle
     
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace Concurrency {
     
    2427        void implementMutexFuncs( std::list< Declaration * > & translationUnit );
    2528        void implementThreadStarter( std::list< Declaration * > & translationUnit );
     29
     30/// Implement the sue-like keywords and the suspend keyword.
     31void implementKeywords( ast::TranslationUnit & translationUnit );
     32/// Implement the mutex parameters and mutex statement.
     33void implementMutex( ast::TranslationUnit & translationUnit );
     34/// Add the thread starter code to constructors.
     35void implementThreadStarter( ast::TranslationUnit & translationUnit );
    2636};
    2737
  • src/Concurrency/module.mk

    r7770cc8 r5235d49  
    1515###############################################################################
    1616
    17 SRC += Concurrency/Keywords.cc Concurrency/Keywords.h Concurrency/Waitfor.cc Concurrency/Waitfor.h
    18 SRCDEMANGLE += Concurrency/Keywords.cc
     17SRC_CONCURRENCY = \
     18        Concurrency/KeywordsNew.cpp \
     19        Concurrency/Keywords.cc
    1920
     21SRC += $(SRC_CONCURRENCY) \
     22        Concurrency/Keywords.h \
     23        Concurrency/Waitfor.cc \
     24        Concurrency/Waitfor.h
     25
     26SRCDEMANGLE += $(SRC_CONCURRENCY)
     27
  • src/Validate/module.mk

    r7770cc8 r5235d49  
    1616
    1717SRC_VALIDATE = \
     18        Validate/CompoundLiteral.cpp \
     19        Validate/CompoundLiteral.hpp \
    1820        Validate/HandleAttributes.cc \
    1921        Validate/HandleAttributes.h \
  • src/main.cc

    r7770cc8 r5235d49  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Nov 12 11:06:00 2021
    13 // Update Count     : 658
     12// Last Modified On : Tue Nov 30 10:25:00 2021
     13// Update Count     : 659
    1414//
    1515
     
    5050#include "Common/UnimplementedError.h"      // for UnimplementedError
    5151#include "Common/utility.h"                 // for deleteAll, filter, printAll
     52#include "Concurrency/Keywords.h"           // for implementMutex, implement...
    5253#include "Concurrency/Waitfor.h"            // for generateWaitfor
    5354#include "ControlStruct/ExceptDecl.h"       // for translateExcept
     
    7374#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    7475#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     76#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    7577#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
    7678#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
     
    325327                PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
    326328                PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
    327                 PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
    328329
    329330                CodeTools::fillLocations( translationUnit );
     
    338339                        forceFillCodeLocations( transUnit );
    339340
     341                        PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
     342                        PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
     343                        PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
    340344                        PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
    341345                        PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
     
    402406                        translationUnit = convert( move( transUnit ) );
    403407                } else {
     408                        PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
    404409                        PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
    405410
  • tests/.expect/random.x64.txt

    r7770cc8 r5235d49  
    11õ
    22=
    3 V
     3K
    44-911259971
    556
    6 -4
     611
    771232105397
    880
    9 18
     911
    1010-914096085
    11111
    12 15
     1220
    13132077092859
    14141
    15 11
     1512
    16160.677254
    17170.678106775246139
  • tests/.expect/random.x86.txt

    r7770cc8 r5235d49  
    11õ
    22=
    3 V
     3K
    44-911259971
    556
    6 -4
     611
    771232105397
    880
    9 18
     911
    1010-914096085
    11111
    12 15
     1220
    13132077092859
    14141
    15 11
     1512
    16160.677254
    17170.678106775246139
  • tests/pybin/tools.py

    r7770cc8 r5235d49  
    374374
    375375        if not os.path.isfile(core):
    376                 return 1, "ERR No core dump"
     376                return 1, "ERR No core dump (limit soft: {} hard: {})".format(*resource.getrlimit(resource.RLIMIT_CORE))
    377377
    378378        try:
Note: See TracChangeset for help on using the changeset viewer.