Changeset c76bd34


Ignore:
Timestamp:
Oct 7, 2020, 4:31:43 PM (5 years ago)
Author:
Colby Alexander Parsons <caparsons@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
848439f
Parents:
ae2c27a (diff), 597c5d18 (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 into master

Files:
54 added
3 deleted
168 edited
121 moved

Legend:

Unmodified
Added
Removed
  • .gitignore

    rae2c27a rc76bd34  
    7979doc/user/pointer2.tex
    8080doc/user/EHMHierarchy.tex
     81
     82# generated by npm
     83package-lock.json
  • Jenkinsfile

    rae2c27a rc76bd34  
    102102
    103103                echo GitLogMessage()
    104 
    105                 // This is a complete hack but it solves problems with automake thinking it needs to regenerate makefiles
    106                 // We fudged automake/missing to handle that but automake stills bakes prints inside the makefiles
    107                 // and these cause more problems.
    108                 sh 'find . -name Makefile.in -exec touch {} +'
    109104        }
    110105}
     
    465460                                        description: 'Which compiler to use',                                   \
    466461                                        name: 'Compiler',                                                                       \
    467                                         choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',                                   \
     462                                        choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',   \
    468463                                        defaultValue: 'gcc-8',                                                          \
    469464                                ],                                                                                              \
  • benchmark/Makefile.am

    rae2c27a rc76bd34  
    113113creation_cfa_generator_DURATION = 1000000000
    114114creation_upp_coroutine_DURATION = ${creation_cfa_coroutine_eager_DURATION}
    115 creation_cfa_thread_DURATION = 10000000
    116 creation_upp_thread_DURATION = ${creation_cfa_thread_DURATION}
    117115creation_DURATION = 10000000
    118116
     
    148146
    149147cleancsv:
    150         rm -f compile.csv basic.csv ctxswitch.csv mutex.csv scheduling.csv
     148        rm -f compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv
    151149
    152150jenkins$(EXEEXT): cleancsv
     
    159157        +make mutex.csv
    160158        -+make mutex.diff.csv
    161         +make scheduling.csv
    162         -+make scheduling.diff.csv
     159        +make schedint.csv
     160        -+make schedint.diff.csv
    163161@DOifskipcompile@
    164162        cat compile.csv
     
    169167        cat mutex.csv
    170168        -cat mutex.diff.csv
    171         cat scheduling.csv
    172         -cat scheduling.diff.csv
     169        cat schedint.csv
     170        -cat schedint.diff.csv
    173171
    174172compile.csv:
     
    200198        $(srcdir)/fixcsv.sh $@
    201199
    202 scheduling.csv:
     200schedint.csv:
    203201        echo "building $@"
    204202        echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@
     
    291289ctxswitch-python_coroutine$(EXEEXT):
    292290        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    293         echo "python3.7 $(srcdir)/ctxswitch/python_cor.py" >> a.out
     291        echo "python3 $(srcdir)/ctxswitch/python_cor.py \"$$""@\"" >> a.out
    294292        chmod a+x a.out
    295293
    296294ctxswitch-nodejs_coroutine$(EXEEXT):
    297295        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    298         echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out
     296        echo "nodejs $(srcdir)/ctxswitch/node_cor.js \"$$""@\"" >> a.out
    299297        chmod a+x a.out
    300298
    301299ctxswitch-nodejs_await$(EXEEXT):
    302300        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    303         echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out
     301        echo "nodejs $(srcdir)/ctxswitch/node_await.js \"$$""@\"" >> a.out
    304302        chmod a+x a.out
    305303
     
    313311        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/ctxswitch/JavaThread.java
    314312        echo "#!/bin/sh" > a.out
    315         echo "java JavaThread" >> a.out
     313        echo "java JavaThread \"$$""@\"" >> a.out
    316314        chmod a+x a.out
    317315
     
    355353        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/mutex/JavaThread.java
    356354        echo "#!/bin/sh" > a.out
    357         echo "java JavaThread" >> a.out
     355        echo "java JavaThread \"$$""@\"" >> a.out
    358356        chmod a+x a.out
    359357
     
    387385        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
    388386        echo "#!/bin/sh" > a.out
    389         echo "java JavaThread" >> a.out
     387        echo "java JavaThread \"$$""@\"" >> a.out
    390388        chmod a+x a.out
    391389
     
    454452creation-python_coroutine$(EXEEXT):
    455453        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    456         echo "python3.7 $(srcdir)/creation/python_cor.py" >> a.out
     454        echo "python3 $(srcdir)/creation/python_cor.py \"$$""@\"" >> a.out
    457455        chmod a+x a.out
    458456
    459457creation-nodejs_coroutine$(EXEEXT):
    460458        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    461         echo "nodejs $(srcdir)/creation/node_cor.js" >> a.out
     459        echo "nodejs $(srcdir)/creation/node_cor.js \"$$""@\"" >> a.out
    462460        chmod a+x a.out
    463461
     
    471469        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java
    472470        echo "#!/bin/sh" > a.out
    473         echo "java JavaThread" >> a.out
     471        echo "java JavaThread \"$$""@\"" >> a.out
    474472        chmod a+x a.out
    475473
     
    492490
    493491compile-array$(EXEEXT):
    494         $(CFACOMPILE) -fsyntax-only -w $(testdir)/array.cfa
     492        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/array.cfa
    495493
    496494compile-attributes$(EXEEXT):
    497         $(CFACOMPILE) -fsyntax-only -w $(testdir)/attributes.cfa
     495        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/attributes.cfa
    498496
    499497compile-empty$(EXEEXT):
    500         $(CFACOMPILE) -fsyntax-only -w $(srcdir)/compile/empty.cfa
     498        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(srcdir)/compile/empty.cfa
    501499
    502500compile-expression$(EXEEXT):
    503         $(CFACOMPILE) -fsyntax-only -w $(testdir)/expression.cfa
     501        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/expression.cfa
    504502
    505503compile-io$(EXEEXT):
    506         $(CFACOMPILE) -fsyntax-only -w $(testdir)/io1.cfa
     504        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/io1.cfa
    507505
    508506compile-monitor$(EXEEXT):
    509         $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
     507        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
    510508
    511509compile-operators$(EXEEXT):
    512         $(CFACOMPILE) -fsyntax-only -w $(testdir)/operators.cfa
     510        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/operators.cfa
    513511
    514512compile-thread$(EXEEXT):
    515         $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/thread.cfa
     513        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/thread.cfa
    516514
    517515compile-typeof$(EXEEXT):
    518         $(CFACOMPILE) -fsyntax-only -w $(testdir)/typeof.cfa
     516        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/typeof.cfa
    519517
    520518## =========================================================================================================
  • benchmark/creation/JavaThread.java

    rae2c27a rc76bd34  
    11public class JavaThread {
    22        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
    3         // Bijective   
     3        // Bijective
    44        // Cycle length for non-zero values is 4G-1.
    55        // 0 is absorbing and should be avoided -- fixed point.
    66        // The returned value is typically masked to produce a positive value.
    7         static volatile int Ticket = 0 ; 
     7        static volatile int Ticket = 0 ;
    88
    99        private static int nextRandom (int x) {
    10                 if (x == 0) { 
     10                if (x == 0) {
    1111                        // reseed the PRNG
    12                         // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 
    13                         // Note that we use a non-atomic racy increment -- the race is rare and benign. 
    14                         // If the race is a concern switch to an AtomicInteger. 
    15                         // In addition accesses to the RW volatile global "Ticket"  variable are not 
    16                         // (readily) predictable at compile-time so the JIT will not be able to elide 
    17                         // nextRandom() invocations. 
    18                         x = ++Ticket ; 
    19                         if (x == 0) x = 1 ; 
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger.
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations.
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
    2020                }
    2121                x ^= x << 6;
    2222                x ^= x >>> 21;
    2323                x ^= x << 7;
    24                 return x ;   
     24                return x ;
    2525        }
    2626        static int x = 2;
    2727
    28         static private int times = Integer.parseInt("10000") ;
     28        static private long times = Long.parseLong("10000") ;
    2929
    3030        public static class MyThread extends Thread {
     
    3333        }
    3434        public static void helper() throws InterruptedException {
    35                 for(int i = 1; i <= times; i += 1) {
     35                for(long i = 1; i <= times; i += 1) {
    3636                        MyThread m = new MyThread();
    3737                        x = nextRandom( x );
     
    4747        }
    4848        public static void main(String[] args) throws InterruptedException {
    49                 if ( args.length > 2 ) System.exit( 1 );
    50                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
     49                if ( args.length > 1 ) System.exit( 1 );
     50                if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
    5151
    52                 for (int i = Integer.parseInt("5"); --i >= 0 ; ) { 
     52                for (int i = Integer.parseInt("5"); --i >= 0 ; ) {
    5353                        InnerMain();
    5454                        Thread.sleep(2000);             // 2 seconds
  • benchmark/ctxswitch/JavaThread.java

    rae2c27a rc76bd34  
    11public class JavaThread {
    22        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
    3         // Bijective   
     3        // Bijective
    44        // Cycle length for non-zero values is 4G-1.
    55        // 0 is absorbing and should be avoided -- fixed point.
    66        // The returned value is typically masked to produce a positive value.
    7         static volatile int Ticket = 0 ; 
     7        static volatile int Ticket = 0 ;
    88
    99        private static int nextRandom (int x) {
    10                 if (x == 0) { 
     10                if (x == 0) {
    1111                        // reseed the PRNG
    12                         // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 
    13                         // Note that we use a non-atomic racy increment -- the race is rare and benign. 
    14                         // If the race is a concern switch to an AtomicInteger. 
    15                         // In addition accesses to the RW volatile global "Ticket"  variable are not 
    16                         // (readily) predictable at compile-time so the JIT will not be able to elide 
    17                         // nextRandom() invocations. 
    18                         x = ++Ticket ; 
    19                         if (x == 0) x = 1 ; 
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger.
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations.
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
    2020                }
    2121                x ^= x << 6;
    2222                x ^= x >>> 21;
    2323                x ^= x << 7;
    24                 return x ;   
     24                return x ;
    2525        }
    2626        static int x = 2;
    2727
    28         static private int times = Integer.parseInt("100000");
     28        static private long times = Long.parseLong("100000");
    2929
    3030        public static void helper() {
    31                 for(int i = 1; i <= times; i += 1) {
     31                for(long i = 1; i <= times; i += 1) {
    3232                        Thread.yield();
    3333                }
     
    4040        }
    4141        public static void main(String[] args) throws InterruptedException {
    42                 if ( args.length > 2 ) System.exit( 1 );
    43                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
     42                if ( args.length > 1 ) System.exit( 1 );
     43                if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
    4444
    4545                for (int i = Integer.parseInt("5"); --i >= 0 ; ) {
  • benchmark/io/http/filecache.cfa

    rae2c27a rc76bd34  
    7373        cache_line * entries;
    7474        size_t size;
     75        int * rawfds;
     76        int nfds;
    7577} file_cache;
    7678
     
    98100}
    99101
    100 int put_file( cache_line & entry ) {
     102int put_file( cache_line & entry, int fd ) {
    101103        uint32_t idx = murmur3_32( (const uint8_t *)entry.file, strlen(entry.file), options.file_cache.hash_seed ) % file_cache.size;
    102104
     
    108110
    109111        file_cache.entries[idx] = entry;
     112        file_cache.entries[idx].fd = fd;
    110113        return i > 0 ? 1 : 0;
    111114}
     
    121124        size_t fcount = 0;
    122125        size_t fsize = 16;
    123         cache_line * raw = 0p;
    124         raw = alloc(raw, fsize, true);
     126        cache_line * raw = alloc(fsize);
    125127        // Step 1 get a dense array of all files
    126128        int walk(const char *fpath, const struct stat *sb, int typeflag) {
     
    131133                if(fcount > fsize) {
    132134                        fsize *= 2;
    133                         raw = alloc(raw, fsize, true);
     135                        raw = alloc(fsize, raw`realloc);
    134136                }
    135137
     
    162164        file_cache.entries = anew(file_cache.size);
    163165
     166        if(options.file_cache.fixed_fds) {
     167                file_cache.nfds   = fcount;
     168                file_cache.rawfds = alloc(fcount);
     169        }
     170
    164171        // Step 3 fill the cache
    165172        int conflicts = 0;
    166173        for(i; fcount) {
    167                 conflicts += put_file( raw[i] );
     174                int fd;
     175                if(options.file_cache.fixed_fds) {
     176                        file_cache.rawfds[i] = raw[i].fd;
     177                        fd = i;
     178                }
     179                else {
     180                        fd = raw[i].fd;
     181                }
     182                conflicts += put_file( raw[i], fd );
    168183        }
    169184        printf("Filled cache from path \"%s\" with %zu files\n", path, fcount);
     
    197212        }
    198213
    199         return [aalloc(extra), 0];
     214        size_t s = file_cache.nfds + extra;
     215        int * data = alloc(s, file_cache.rawfds`realloc);
     216        return [data, file_cache.nfds];
    200217}
    201218
  • benchmark/io/http/main.cfa

    rae2c27a rc76bd34  
    1212#include <kernel.hfa>
    1313#include <stats.hfa>
     14#include <time.hfa>
    1415#include <thread.hfa>
    1516
    16 #include "channel.hfa"
    1717#include "filecache.hfa"
    1818#include "options.hfa"
    1919#include "worker.hfa"
    2020
     21extern void register_fixed_files( cluster &, int *, unsigned count );
     22
     23Duration default_preemption() {
     24        return 0;
     25}
     26
    2127//=============================================================================================
    2228// Globals
    2329//=============================================================================================
    24 channel & wait_connect;
    25 
    2630struct ServerProc {
    2731        processor self;
     
    8488        // Run Server Cluster
    8589        {
    86                 cluster cl = { "Server Cluster", options.clopts.flags };
     90                cluster cl = { "Server Cluster", options.clopts.params };
    8791                #if !defined(__CFA_NO_STATISTICS__)
    8892                        print_stats_at_exit( cl, CFA_STATS_READY_Q | CFA_STATS_IO );
    8993                #endif
    9094                options.clopts.instance = &cl;
    91 
    92                 channel chan = { options.clopts.chan_size };
    93                 &wait_connect = &chan;
    9495
    9596                int pipe_cnt = options.clopts.nworkers * 2;
     
    102103                }
    103104
     105                if(options.file_cache.fixed_fds) {
     106                        register_fixed_files(cl, fds, pipe_off);
     107                }
     108
    104109                {
    105110                        ServerProc procs[options.clopts.nprocs];
     
    107112                                Worker workers[options.clopts.nworkers];
    108113                                for(i; options.clopts.nworkers) {
    109                                         if( options.file_cache.fixed_fds ) {
    110                                                 workers[i].pipe[0] = pipe_off + (i * 2) + 0;
    111                                                 workers[i].pipe[1] = pipe_off + (i * 2) + 1;
    112                                         }
    113                                         else {
     114                                        // if( options.file_cache.fixed_fds ) {
     115                                        //      workers[i].pipe[0] = pipe_off + (i * 2) + 0;
     116                                        //      workers[i].pipe[1] = pipe_off + (i * 2) + 1;
     117                                        // }
     118                                        // else
     119                                        {
    114120                                                workers[i].pipe[0] = fds[pipe_off + (i * 2) + 0];
    115121                                                workers[i].pipe[1] = fds[pipe_off + (i * 2) + 1];
     122                                                workers[i].sockfd  = server_fd;
     123                                                workers[i].addr    = (struct sockaddr *)&address;
     124                                                workers[i].addrlen = (socklen_t*)&addrlen;
     125                                                workers[i].flags   = 0;
    116126                                        }
    117                                         unpark( workers[i] __cfaabi_dbg_ctx2 );
     127                                        unpark( workers[i] );
    118128                                }
    119129                                printf("%d workers started on %d processors\n", options.clopts.nworkers, options.clopts.nprocs);
    120130                                {
    121                                         Acceptor acceptor = { server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen, 0 };
    122 
    123131                                        char buffer[128];
    124132                                        while(!feof(stdin)) {
     
    127135
    128136                                        printf("Shutting Down\n");
    129                                 }
    130                                 printf("Acceptor Closed\n");
    131 
    132                                 // Clean-up the workers
    133                                 for(options.clopts.nworkers) {
    134                                         put( wait_connect, -1 );
    135137                                }
    136138                        }
  • benchmark/io/http/options.cfa

    rae2c27a rc76bd34  
    3131                1,     // nworkers;
    3232                0,     // flags;
    33                 10,    // chan_size;
    3433                false, // procstats
    3534                false, // viewhalts
     
    3938
    4039const char * parse_options( int argc, char * argv[] ) {
    41         bool uthrdpo = false;
    4240        bool subthrd = false;
    4341        bool eagrsub = false;
     
    5250                {'t', "threads",        "Number of worker threads to use", options.clopts.nworkers},
    5351                {'b', "accept-backlog", "Maximum number of pending accepts", options.socket.backlog},
    54                 {'B', "channel-size",   "Maximum number of accepted connection pending", options.clopts.chan_size},
    5552                {'r', "request_len",    "Maximum number of bytes in the http request, requests with more data will be answered with Http Code 414", options.socket.buflen},
    5653                {'S', "seed",           "seed to use for hashing", options.file_cache.hash_seed },
    5754                {'C', "cache-size",     "Size of the cache to use, if set to small, will uses closes power of 2", options.file_cache.size },
    5855                {'l', "list-files",     "List the files in the specified path and exit", options.file_cache.list, parse_settrue },
    59                 {'u', "userthread",     "If set, cluster uses user-thread to poll I/O", uthrdpo, parse_settrue },
    6056                {'s', "submitthread",   "If set, cluster uses polling thread to submit I/O", subthrd, parse_settrue },
    6157                {'e', "eagersubmit",    "If set, cluster submits I/O eagerly but still aggregates submits", eagrsub, parse_settrue},
     
    7167        parse_args( argc, argv, opt, opt_cnt, "[OPTIONS]... [PATH]\ncforall http server", left );
    7268
    73         if( uthrdpo ) {
    74                 options.clopts.flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD;
    75         }
    76 
    77         if( subthrd ) {
    78                 options.clopts.flags |= CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS;
    79         }
    80 
    81         if( eagrsub ) {
    82                 options.clopts.flags |= CFA_CLUSTER_IO_EAGER_SUBMITS;
    83         }
     69        options.clopts.params.poller_submits = subthrd;
     70        options.clopts.params.eager_submits  = eagrsub;
    8471
    8572        if( fixedfd ) {
     
    8875
    8976        if( sqkpoll ) {
    90                 options.clopts.flags |= CFA_CLUSTER_IO_KERNEL_POLL_SUBMITS;
     77                options.clopts.params.poll_submit = true;
    9178                options.file_cache.fixed_fds = true;
    9279        }
    9380
    9481        if( iokpoll ) {
    95                 options.clopts.flags |= CFA_CLUSTER_IO_KERNEL_POLL_COMPLETES;
     82                options.clopts.params.poll_complete = true;
    9683                options.file_cache.open_flags |= O_DIRECT;
    9784        }
    9885
    99         options.clopts.flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET);
     86        options.clopts.params.num_ready = sublen;
    10087
    10188        if( left[0] == 0p ) { return "."; }
  • benchmark/io/http/options.hfa

    rae2c27a rc76bd34  
    22
    33#include <stdint.h>
     4
     5#include <kernel.hfa>
    46
    57struct cluster;
     
    2325                int nprocs;
    2426                int nworkers;
    25                 int flags;
    26                 int chan_size;
     27                io_context_params params;
    2728                bool procstats;
    2829                bool viewhalts;
  • benchmark/io/http/protocol.cfa

    rae2c27a rc76bd34  
    1111extern "C" {
    1212      int snprintf ( char * s, size_t n, const char * format, ... );
     13        #include <linux/io_uring.h>
    1314}
    1415#include <string.h>
    15 
    1616#include <errno.h>
    1717
     18#include "options.hfa"
    1819
    1920const char * http_msgs[] = {
     
    7475        READ:
    7576        for() {
    76                 int ret = cfa_read(fd, it, count);
    77                 if(ret == 0 ) return [OK200, true, 0p, 0];
     77                int ret = cfa_read(fd, (void*)it, count, 0, -1`s, 0p, 0p);
     78                if(ret == 0 ) return [OK200, true, 0, 0];
    7879                if(ret < 0 ) {
    7980                        if( errno == EAGAIN || errno == EWOULDBLOCK) continue READ;
     
    8889                count -= ret;
    8990
    90                 if( count < 1 ) return [E414, false, 0p, 0];
     91                if( count < 1 ) return [E414, false, 0, 0];
    9192        }
    9293
     
    9596        it = buffer;
    9697        int ret = memcmp(it, "GET /", 5);
    97         if( ret != 0 ) return [E400, false, 0p, 0];
     98        if( ret != 0 ) return [E400, false, 0, 0];
    9899        it += 5;
    99100
     
    106107        ssize_t ret;
    107108        SPLICE1: while(count > 0) {
    108                 ret = cfa_splice(ans_fd, &offset, pipe[1], 0p, count, SPLICE_F_MOVE | SPLICE_F_MORE);
     109                ret = cfa_splice(ans_fd, &offset, pipe[1], 0p, count, SPLICE_F_MOVE | SPLICE_F_MORE, 0, -1`s, 0p, 0p);
    109110                if( ret < 0 ) {
    110111                        if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE1;
     
    116117                size_t in_pipe = ret;
    117118                SPLICE2: while(in_pipe > 0) {
    118                         ret = cfa_splice(pipe[0], 0p, fd, 0p, in_pipe, SPLICE_F_MOVE | SPLICE_F_MORE);
     119                        ret = cfa_splice(pipe[0], 0p, fd, 0p, in_pipe, SPLICE_F_MOVE | SPLICE_F_MORE, 0, -1`s, 0p, 0p);
    119120                        if( ret < 0 ) {
    120121                                if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE2;
  • benchmark/io/http/worker.cfa

    rae2c27a rc76bd34  
    2222
    2323void main( Worker & this ) {
    24         park( __cfaabi_dbg_ctx );
     24        park();
    2525        /* paranoid */ assert( this.pipe[0] != -1 );
    2626        /* paranoid */ assert( this.pipe[1] != -1 );
     
    2828        CONNECTION:
    2929        for() {
    30                 int fd = take(wait_connect);
    31                 if (fd < 0) break;
     30                int fd = cfa_accept4( this.[sockfd, addr, addrlen, flags], 0, -1`s, 0p, 0p );
     31                if(fd < 0) {
     32                        if( errno == ECONNABORTED ) break;
     33                        abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) );
     34                }
    3235
    3336                printf("New connection %d, waiting for requests\n", fd);
     
    8285        }
    8386}
    84 
    85 //=============================================================================================
    86 // Acceptor Thread
    87 //=============================================================================================
    88 void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags ) {
    89         ((thread&)this){ "Acceptor Thread", *options.clopts.instance };
    90         this.sockfd  = sockfd;
    91         this.addr    = addr;
    92         this.addrlen = addrlen;
    93         this.flags   = flags;
    94 }
    95 
    96 void main( Acceptor & this ) {
    97         for() {
    98                 int ret = cfa_accept4( this.[sockfd, addr, addrlen, flags] );
    99                 if(ret < 0) {
    100                         if( errno == ECONNABORTED ) break;
    101                         abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) );
    102                 }
    103 
    104                 printf("New connection accepted\n");
    105                 put( wait_connect, ret );
    106         }
    107 }
  • benchmark/io/http/worker.hfa

    rae2c27a rc76bd34  
    77}
    88
    9 #include "channel.hfa"
    10 
    11 extern channel & wait_connect;
    12 
    139//=============================================================================================
    1410// Worker Thread
     
    1713thread Worker {
    1814        int pipe[2];
    19 };
    20 void ?{}( Worker & this );
    21 void main( Worker & );
    22 
    23 //=============================================================================================
    24 // Acceptor Thread
    25 //=============================================================================================
    26 thread Acceptor {
    2715        int sockfd;
    2816        struct sockaddr * addr;
     
    3018        int flags;
    3119};
    32 
    33 void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags );
    34 void main( Acceptor & this );
     20void ?{}( Worker & this);
     21void main( Worker & );
  • benchmark/io/readv.cfa

    rae2c27a rc76bd34  
    5454
    5555void main( Reader & ) {
    56         park( __cfaabi_dbg_ctx );
     56        park();
    5757        /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
    5858
     
    151151
    152152                                for(i; nthreads) {
    153                                         unpark( threads[i] __cfaabi_dbg_ctx2 );
     153                                        unpark( threads[i] );
    154154                                }
    155155                                wait(duration, start, end, is_tty);
  • benchmark/mutex/JavaThread.java

    rae2c27a rc76bd34  
    11public class JavaThread {
    22        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
    3         // Bijective   
     3        // Bijective
    44        // Cycle length for non-zero values is 4G-1.
    55        // 0 is absorbing and should be avoided -- fixed point.
    66        // The returned value is typically masked to produce a positive value.
    7         static volatile int Ticket = 0 ; 
     7        static volatile int Ticket = 0 ;
    88
    99        private static int nextRandom (int x) {
    10                 if (x == 0) { 
     10                if (x == 0) {
    1111                        // reseed the PRNG
    12                         // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 
    13                         // Note that we use a non-atomic racy increment -- the race is rare and benign. 
    14                         // If the race is a concern switch to an AtomicInteger. 
    15                         // In addition accesses to the RW volatile global "Ticket"  variable are not 
    16                         // (readily) predictable at compile-time so the JIT will not be able to elide 
    17                         // nextRandom() invocations. 
    18                         x = ++Ticket ; 
    19                         if (x == 0) x = 1 ; 
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger.
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations.
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
    2020                }
    2121                x ^= x << 6;
    2222                x ^= x >>> 21;
    2323                x ^= x << 7;
    24                 return x ;   
     24                return x ;
    2525        }
    2626        static int x = 2;
    2727
    28         static private int times = Integer.parseInt("100000000");
     28        static private long times = Long.parseLong("100000000");
    2929
    3030        public synchronized void noop() {
     
    3434                JavaThread j = new JavaThread();
    3535                // Inhibit biased locking ...
    36                 x = (j.hashCode() ^ System.identityHashCode(j)) | 1 ;     
    37                 for(int i = 1; i <= times; i += 1) {
     36                x = (j.hashCode() ^ System.identityHashCode(j)) | 1 ;
     37                for(long i = 1; i <= times; i += 1) {
    3838                        x = nextRandom(x);
    3939                        j.noop();
     
    4747        }
    4848        public static void main(String[] args) throws InterruptedException {
    49                 if ( args.length > 2 ) System.exit( 1 );
    50                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
     49                if ( args.length > 1 ) System.exit( 1 );
     50                if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
    5151
    52                 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 
     52                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
    5353                        InnerMain();
    5454                        Thread.sleep(2000);     // 2 seconds
  • benchmark/mutexC/JavaThread.java

    rae2c27a rc76bd34  
    11class Noop {
    22        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
    3         // Bijective   
     3        // Bijective
    44        // Cycle length for non-zero values is 4G-1.
    55        // 0 is absorbing and should be avoided -- fixed point.
    66        // The returned value is typically masked to produce a positive value.
    7         static volatile int Ticket = 0 ; 
     7        static volatile int Ticket = 0 ;
    88
    99        public static int nextRandom( int x ) {
    10                 if (x == 0) { 
     10                if (x == 0) {
    1111                        // reseed the PRNG
    12                         // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 
    13                         // Note that we use a non-atomic racy increment -- the race is rare and benign. 
    14                         // If the race is a concern switch to an AtomicInteger. 
    15                         // In addition accesses to the RW volatile global "Ticket"  variable are not 
    16                         // (readily) predictable at compile-time so the JIT will not be able to elide 
    17                         // nextRandom() invocations. 
    18                         x = ++Ticket ; 
    19                         if (x == 0) x = 1 ; 
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger.
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations.
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
    2020                }
    2121                x ^= x << 6;
    2222                x ^= x >>> 21;
    2323                x ^= x << 7;
    24                 return x ;   
     24                return x ;
    2525        }
    2626}
     
    4747        static int x = 2;
    4848
    49         static private int times = Integer.parseInt("10000000");
     49        static private long times = Long.parseLong("10000000");
    5050
    5151        public static void call( Monitor m ) throws InterruptedException {
     
    5353                m.go = true;
    5454                //while ( ! m.go2 );
    55                 for ( int i = 0; i < times; i += 1 ) {
     55                for ( long i = 0; i < times; i += 1 ) {
    5656                        m.call();
    5757                        x = Noop.nextRandom( x );
     
    7171        public static void main( String[] args ) throws InterruptedException {
    7272                if ( args.length > 2 ) System.exit( 1 );
    73                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
     73                if ( args.length == 2 ) { times = Long.parseLong(args[1]); }
    7474
    75                 if ( args.length > 2 ) System.exit( 1 );
    76                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
    77 
    78                 for ( int i = Integer.parseInt("5"); --i >= 0 ; ) {
     75                for ( int i = Integer.parseInt("5"); --i >= 0 ; ) {
    7976                        InnerMain();
    8077                        // Thread.sleep(2000);  // 2 seconds
  • benchmark/readyQ/yield.cfa

    rae2c27a rc76bd34  
    3232
    3333void main( Yielder & this ) {
    34         park( __cfaabi_dbg_ctx );
     34        park();
    3535        /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
    3636
     
    7070
    7171                                for(i; nthreads) {
    72                                         unpark( threads[i] __cfaabi_dbg_ctx2 );
     72                                        unpark( threads[i] );
    7373                                }
    7474                                wait(duration, start, end, is_tty);
  • benchmark/schedint/JavaThread.java

    rae2c27a rc76bd34  
    2424public class JavaThread {
    2525        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
    26         // Bijective   
     26        // Bijective
    2727        // Cycle length for non-zero values is 4G-1.
    2828        // 0 is absorbing and should be avoided -- fixed point.
    2929        // The returned value is typically masked to produce a positive value.
    30         static volatile int Ticket = 0 ; 
     30        static volatile int Ticket = 0 ;
    3131
    3232        private static int nextRandom (int x) {
    33                 if (x == 0) { 
     33                if (x == 0) {
    3434                        // reseed the PRNG
    35                         // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 
    36                         // Note that we use a non-atomic racy increment -- the race is rare and benign. 
    37                         // If the race is a concern switch to an AtomicInteger. 
    38                         // In addition accesses to the RW volatile global "Ticket"  variable are not 
    39                         // (readily) predictable at compile-time so the JIT will not be able to elide 
    40                         // nextRandom() invocations. 
    41                         x = ++Ticket ; 
    42                         if (x == 0) x = 1 ; 
     35                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     36                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     37                        // If the race is a concern switch to an AtomicInteger.
     38                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     39                        // (readily) predictable at compile-time so the JIT will not be able to elide
     40                        // nextRandom() invocations.
     41                        x = ++Ticket ;
     42                        if (x == 0) x = 1 ;
    4343                }
    4444                x ^= x << 6;
    4545                x ^= x >>> 21;
    4646                x ^= x << 7;
    47                 return x ;   
     47                return x ;
    4848        }
    4949        static int x = 2;
    5050
    51         static private int times = Integer.parseInt("1000000");
     51        static private long times = Long.parseLong("1000000");
    5252
    5353        public static void helper( Monitor m ) throws InterruptedException {
    54                 for(int i = 1; i <= times; i += 1) {
     54                for(long i = 1; i <= times; i += 1) {
    5555                        m.wait();               // relase monitor lock
    5656                        m.next = true;
     
    7575        }
    7676        public static void main(String[] args) throws InterruptedException {
    77                 if ( args.length > 2 ) System.exit( 1 );
    78                 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }
     77                if ( args.length > 1 ) System.exit( 1 );
     78                if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
    7979
    80                 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 
     80                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
    8181                        InnerMain();
    8282                        Thread.sleep(2000);     // 2 seconds
  • doc/LaTeXmacros/common.tex

    rae2c27a rc76bd34  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Sep  4 13:56:52 2020
    14 %% Update Count     : 383
     13%% Last Modified On : Mon Oct  5 09:34:46 2020
     14%% Update Count     : 464
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\newlength{\parindentlnth}
    5656\setlength{\parindentlnth}{\parindent}
    57 
    58 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
    59 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
    60 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    61 
    62 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    63 \newlength{\columnposn}
    64 \setlength{\gcolumnposn}{2.75in}
    65 \setlength{\columnposn}{\gcolumnposn}
    66 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    67 \newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    68 
    69 % allow escape sequence in lstinline
    70 %\usepackage{etoolbox}
    71 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
    7257
    7358\usepackage{pslatex}                                    % reduce size of san serif font
     
    244229\usepackage{listings}                                                                   % format program code
    245230\usepackage{lstlang}
    246 
    247 \newcommand{\CFADefaults}{%
     231\makeatletter
     232
     233\newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
     234\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
     235\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     236
     237\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     238\newlength{\columnposn}
     239\setlength{\gcolumnposn}{2.75in}
     240\setlength{\columnposn}{\gcolumnposn}
     241\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
     242\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     243
     244% allow escape sequence in lstinline
     245%\usepackage{etoolbox}
     246%\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
     247
     248% allow adding to lst literate
     249\def\addToLiterate#1{\protect\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}}
     250\lst@Key{add to literate}{}{\addToLiterate{#1}}
     251\makeatother
     252
     253\newcommand{\CFAStyle}{%
    248254\lstset{
    249 language=CFA,
    250255columns=fullflexible,
    251256basicstyle=\linespread{0.9}\sf,                 % reduce line spacing and use sanserif font
     
    262267belowskip=3pt,
    263268% replace/adjust listing characters that look bad in sanserif
    264 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     269literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    265270        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    266271        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
     272}% lstset
     273}% CFAStyle
     274
     275\ifdefined\CFALatin% extra Latin-1 escape characters
     276\lstnewenvironment{cfa}[1][]{
     277\lstset{
     278language=CFA,
    267279moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    268280moredelim=**[is][\color{blue}]{ß}{ß},   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    269281moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    270282moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     283% replace/adjust listing characters that look bad in sanserif
     284add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    271285}% lstset
    272 }% CFADefaults
    273 \newcommand{\CFAStyle}{%
    274 \CFADefaults
     286\lstset{#1}
     287}{}
    275288% inline code ©...© (copyright symbol) emacs: C-q M-)
    276289\lstMakeShortInline©                                    % single-character for \lstinline
    277 }% CFAStyle
    278 
    279 \lstnewenvironment{cfa}[1][]
    280 {\CFADefaults\lstset{#1}}
    281 {}
     290\else% regular ASCI characters
     291\lstnewenvironment{cfa}[1][]{
     292\lstset{
     293language=CFA,
     294escapechar=\$,                                                  % LaTeX escape in CFA code
     295moredelim=**[is][\color{red}]{@}{@},    % red highlighting @...@
     296}% lstset
     297\lstset{#1}
     298}{}
     299% inline code @...@ (at symbol)
     300\lstMakeShortInline@                                    % single-character for \lstinline
     301\fi%
    282302
    283303% Local Variables: %
  • doc/LaTeXmacros/lstlang.sty

    rae2c27a rc76bd34  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Tue Jan  8 14:40:33 2019
    11 %% Update Count     : 21
     10%% Last Modified On : Wed Sep 23 22:40:04 2020
     11%% Update Count     : 24
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    115115                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    116116                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
    117                 __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
     117                __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
    118118                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
    119                 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,
     119                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread,
    120120                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
    121121                virtual, __volatile, __volatile__, waitfor, when, with, zero_t,
     
    125125
    126126% C++ programming language
    127 \lstdefinelanguage{C++}[ANSI]{C++}{}
     127\lstdefinelanguage{C++}[ANSI]{C++}{
     128        morekeywords={nullptr,}
     129}
    128130
    129131% uC++ programming language, based on ANSI C++
  • doc/bibliography/pl.bib

    rae2c27a rc76bd34  
    10051005    key         = {Cforall Benchmarks},
    10061006    author      = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}},
    1007     howpublished= {\href{https://plg.uwaterloo.ca/~cforall/doc/CforallConcurrentBenchmarks.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-doc/\-CforallConcurrentBenchmarks.tar}},
     1007    howpublished= {\href{https://github.com/cforall/ConcurrentBenchmarks_SPE20}{https://\-github.com/\-cforall/\-ConcurrentBenchmarks\_SPE20}},
    10081008}
    10091009
     
    19731973    title       = {Cooperating Sequential Processes},
    19741974    institution = {Technological University},
    1975     address     = {Eindhoven, Netherlands},
     1975    address     = {Eindhoven, Neth.},
    19761976    year        = 1965,
    19771977    note        = {Reprinted in \cite{Genuys68} pp. 43--112.}
  • doc/papers/concurrency/Paper.tex

    rae2c27a rc76bd34  
    224224{}
    225225\lstnewenvironment{C++}[1][]                            % use C++ style
    226 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     226{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    227227{}
    228228\lstnewenvironment{uC++}[1][]
    229 {\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     229{\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    230230{}
    231231\lstnewenvironment{Go}[1][]
    232 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     232{\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    233233{}
    234234\lstnewenvironment{python}[1][]
    235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     235{\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    236236{}
    237237\lstnewenvironment{java}[1][]
    238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     238{\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    239239{}
    240240
     
    284284
    285285\begin{document}
    286 \linenumbers                            % comment out to turn off line numbering
     286%\linenumbers                           % comment out to turn off line numbering
    287287
    288288\maketitle
     
    450450\hline
    451451stateful                        & thread        & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\
    452 \hline   
    453 \hline   
     452\hline
     453\hline
    454454No                                      & No            & \textbf{1}\ \ \ @struct@                              & \textbf{2}\ \ \ @mutex@ @struct@              \\
    455 \hline   
     455\hline
    456456Yes (stackless)         & No            & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @mutex@ @generator@   \\
    457 \hline   
     457\hline
    458458Yes (stackful)          & No            & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @mutex@ @coroutine@   \\
    459 \hline   
     459\hline
    460460No                                      & Yes           & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\
    461 \hline   
     461\hline
    462462Yes (stackless)         & Yes           & \textbf{9}\ \ \ {\color{red}rejected} & \textbf{10}\ \ \ {\color{red}rejected} \\
    463 \hline   
     463\hline
    464464Yes (stackful)          & Yes           & \textbf{11}\ \ \ @thread@                             & \textbf{12}\ \ @mutex@ @thread@               \\
    465465\end{tabular}
     
    28962896\label{s:RuntimeStructureCluster}
    28972897
    2898 A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue.
     2898A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue~\cite{Buhr90a}.
    28992899The term \newterm{virtual processor} is introduced as a synonym for kernel thread to disambiguate between user and kernel thread.
    29002900From the language perspective, a virtual processor is an actual processor (core).
     
    29922992\end{cfa}
    29932993where CPU time in nanoseconds is from the appropriate language clock.
    2994 Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language.
     2994Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language;
     2995each @N@ appears after the experiment name in the following tables.
    29952996The total time is divided by @N@ to obtain the average time for a benchmark.
    29962997Each benchmark experiment is run 13 times and the average appears in the table.
     2998For languages with a runtime JIT (Java, Node.js, Python), a single half-hour long experiment is run to check stability;
     2999all long-experiment results are statistically equivalent, \ie median/average/standard-deviation correlate with the short-experiment results, indicating the short experiments reached a steady state.
    29973000All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallConcurrentBenchmarks}.
    2998 % tar --exclude-ignore=exclude -cvhf benchmark.tar benchmark
    2999 % cp -p benchmark.tar /u/cforall/public_html/doc/concurrent_benchmark.tar
    30003001
    30013002\paragraph{Creation}
     
    30063007
    30073008\begin{multicols}{2}
    3008 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3009 \begin{cfa}
    3010 @coroutine@ MyCoroutine {};
     3009\begin{cfa}[xleftmargin=0pt]
     3010`coroutine` MyCoroutine {};
    30113011void ?{}( MyCoroutine & this ) {
    30123012#ifdef EAGER
     
    30163016void main( MyCoroutine & ) {}
    30173017int main() {
    3018         BENCH( for ( N ) { @MyCoroutine c;@ } )
     3018        BENCH( for ( N ) { `MyCoroutine c;` } )
    30193019        sout | result;
    30203020}
     
    30303030
    30313031\begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}}
    3032 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3033 \CFA generator                  & 0.6           & 0.6           & 0.0           \\
    3034 \CFA coroutine lazy             & 13.4          & 13.1          & 0.5           \\
    3035 \CFA coroutine eager    & 144.7         & 143.9         & 1.5           \\
    3036 \CFA thread                             & 466.4         & 468.0         & 11.3          \\
    3037 \uC coroutine                   & 155.6         & 155.7         & 1.7           \\
    3038 \uC thread                              & 523.4         & 523.9         & 7.7           \\
    3039 Python generator                & 123.2         & 124.3         & 4.1           \\
    3040 Node.js generator               & 33.4          & 33.5          & 0.3           \\
    3041 Goroutine thread                & 751.0         & 750.5         & 3.1           \\
    3042 Rust tokio thread               & 1860.0        & 1881.1        & 37.6          \\
    3043 Rust thread                             & 53801.0       & 53896.8       & 274.9         \\
    3044 Java thread                             & 120274.0      & 120722.9      & 2356.7        \\
    3045 Pthreads thread                 & 31465.5       & 31419.5       & 140.4
     3032\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3033\CFA generator (1B)                     & 0.6           & 0.6           & 0.0           \\
     3034\CFA coroutine lazy     (100M)  & 13.4          & 13.1          & 0.5           \\
     3035\CFA coroutine eager (10M)      & 144.7         & 143.9         & 1.5           \\
     3036\CFA thread (10M)                       & 466.4         & 468.0         & 11.3          \\
     3037\uC coroutine (10M)                     & 155.6         & 155.7         & 1.7           \\
     3038\uC thread (10M)                        & 523.4         & 523.9         & 7.7           \\
     3039Python generator (10M)          & 123.2         & 124.3         & 4.1           \\
     3040Node.js generator (10M)         & 33.4          & 33.5          & 0.3           \\
     3041Goroutine thread (10M)          & 751.0         & 750.5         & 3.1           \\
     3042Rust tokio thread (10M)         & 1860.0        & 1881.1        & 37.6          \\
     3043Rust thread     (250K)                  & 53801.0       & 53896.8       & 274.9         \\
     3044Java thread (250K)                      & 119256.0      & 119679.2      & 2244.0        \\
     3045% Java thread (1 000 000)               & 123100.0      & 123052.5      & 751.6         \\
     3046Pthreads thread (250K)          & 31465.5       & 31419.5       & 140.4
    30463047\end{tabular}
    30473048\end{multicols}
     
    30523053Internal scheduling is measured using a cycle of two threads signalling and waiting.
    30533054Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}.
    3054 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    3055 Java scheduling is significantly greater because the benchmark explicitly creates multiple threads in order to prevent the JIT from making the program sequential, \ie removing all locking.
     3055Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
     3056User-level threading has one kernel thread, eliminating contention between the threads (direct handoff of the kernel thread).
     3057Kernel-level threading has two kernel threads allowing some contention.
    30563058
    30573059\begin{multicols}{2}
    3058 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3059 \begin{cfa}
     3060\setlength{\tabcolsep}{3pt}
     3061\begin{cfa}[xleftmargin=0pt]
    30603062volatile int go = 0;
    3061 @condition c;@
    3062 @monitor@ M {} m1/*, m2, m3, m4*/;
    3063 void call( M & @mutex p1/*, p2, p3, p4*/@ ) {
    3064         @signal( c );@
    3065 }
    3066 void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
     3063`condition c;`
     3064`monitor` M {} m1/*, m2, m3, m4*/;
     3065void call( M & `mutex p1/*, p2, p3, p4*/` ) {
     3066        `signal( c );`
     3067}
     3068void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
    30673069        go = 1; // continue other thread
    3068         for ( N ) { @wait( c );@ } );
     3070        for ( N ) { `wait( c );` } );
    30693071}
    30703072thread T {};
     
    30913093
    30923094\begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}}
    3093 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3094 \CFA @signal@, 1 monitor        & 364.4         & 364.2         & 4.4           \\
    3095 \CFA @signal@, 2 monitor        & 484.4         & 483.9         & 8.8           \\
    3096 \CFA @signal@, 4 monitor        & 709.1         & 707.7         & 15.0          \\
    3097 \uC @signal@ monitor            & 328.3         & 327.4         & 2.4           \\
    3098 Rust cond. variable                     & 7514.0        & 7437.4        & 397.2         \\
    3099 Java @notify@ monitor           & 9623.0        & 9654.6        & 236.2         \\
    3100 Pthreads cond. variable         & 5553.7        & 5576.1        & 345.6
     3095\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3096\CFA @signal@, 1 monitor (10M)  & 364.4         & 364.2         & 4.4           \\
     3097\CFA @signal@, 2 monitor (10M)  & 484.4         & 483.9         & 8.8           \\
     3098\CFA @signal@, 4 monitor (10M)  & 709.1         & 707.7         & 15.0          \\
     3099\uC @signal@ monitor (10M)              & 328.3         & 327.4         & 2.4           \\
     3100Rust cond. variable     (1M)            & 7514.0        & 7437.4        & 397.2         \\
     3101Java @notify@ monitor (1M)              & 8717.0        & 8774.1        & 471.8         \\
     3102% Java @notify@ monitor (100 000 000)           & 8634.0        & 8683.5        & 330.5         \\
     3103Pthreads cond. variable (1M)    & 5553.7        & 5576.1        & 345.6
    31013104\end{tabular}
    31023105\end{multicols}
     
    31073110External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
    31083111Figure~\ref{f:schedext} shows the code for \CFA with results in Table~\ref{t:schedext}.
    3109 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     3112Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
    31103113
    31113114\begin{multicols}{2}
    3112 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3115\setlength{\tabcolsep}{5pt}
    31133116\vspace*{-16pt}
    3114 \begin{cfa}
    3115 @monitor@ M {} m1/*, m2, m3, m4*/;
    3116 void call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
    3117 void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
    3118         for ( N ) { @waitfor( call : p1/*, p2, p3, p4*/ );@ }
     3117\begin{cfa}[xleftmargin=0pt]
     3118`monitor` M {} m1/*, m2, m3, m4*/;
     3119void call( M & `mutex p1/*, p2, p3, p4*/` ) {}
     3120void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
     3121        for ( N ) { `waitfor( call : p1/*, p2, p3, p4*/ );` }
    31193122}
    31203123thread T {};
     
    31333136\columnbreak
    31343137
    3135 \vspace*{-16pt}
     3138\vspace*{-18pt}
    31363139\captionof{table}{External-scheduling comparison (nanoseconds)}
    31373140\label{t:schedext}
    31383141\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3139 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3140 \CFA @waitfor@, 1 monitor       & 367.1 & 365.3 & 5.0   \\
    3141 \CFA @waitfor@, 2 monitor       & 463.0 & 464.6 & 7.1   \\
    3142 \CFA @waitfor@, 4 monitor       & 689.6 & 696.2 & 21.5  \\
    3143 \uC \lstinline[language=uC++]|_Accept| monitor  & 328.2 & 329.1 & 3.4   \\
    3144 Go \lstinline[language=Golang]|select| channel  & 365.0 & 365.5 & 1.2
     3142\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3143\CFA @waitfor@, 1 monitor (10M) & 367.1 & 365.3 & 5.0   \\
     3144\CFA @waitfor@, 2 monitor (10M) & 463.0 & 464.6 & 7.1   \\
     3145\CFA @waitfor@, 4 monitor (10M) & 689.6 & 696.2 & 21.5  \\
     3146\uC \lstinline[language=uC++]|_Accept| monitor (10M)    & 328.2 & 329.1 & 3.4   \\
     3147Go \lstinline[language=Golang]|select| channel (10M)    & 365.0 & 365.5 & 1.2
    31453148\end{tabular}
    31463149\end{multicols}
     
    31553158
    31563159\begin{multicols}{2}
    3157 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3158 \begin{cfa}
    3159 @monitor@ M {} m1/*, m2, m3, m4*/;
    3160 call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
     3160\setlength{\tabcolsep}{3pt}
     3161\begin{cfa}[xleftmargin=0pt]
     3162`monitor` M {} m1/*, m2, m3, m4*/;
     3163call( M & `mutex p1/*, p2, p3, p4*/` ) {}
    31613164int main() {
    31623165        BENCH( for( N ) call( m1/*, m2, m3, m4*/ ); )
     
    31733176\label{t:mutex}
    31743177\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3175 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3176 test-and-test-set lock                  & 19.1  & 18.9  & 0.4   \\
    3177 \CFA @mutex@ function, 1 arg.   & 48.3  & 47.8  & 0.9   \\
    3178 \CFA @mutex@ function, 2 arg.   & 86.7  & 87.6  & 1.9   \\
    3179 \CFA @mutex@ function, 4 arg.   & 173.4 & 169.4 & 5.9   \\
    3180 \uC @monitor@ member rtn.               & 54.8  & 54.8  & 0.1   \\
    3181 Goroutine mutex lock                    & 34.0  & 34.0  & 0.0   \\
    3182 Rust mutex lock                                 & 33.0  & 33.2  & 0.8   \\
    3183 Java synchronized method                & 31.0  & 31.0  & 0.0   \\
    3184 Pthreads mutex Lock                             & 31.0  & 31.1  & 0.4
     3178\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3179test-and-test-set lock (50M)            & 19.1  & 18.9  & 0.4   \\
     3180\CFA @mutex@ function, 1 arg. (50M)     & 48.3  & 47.8  & 0.9   \\
     3181\CFA @mutex@ function, 2 arg. (50M)     & 86.7  & 87.6  & 1.9   \\
     3182\CFA @mutex@ function, 4 arg. (50M)     & 173.4 & 169.4 & 5.9   \\
     3183\uC @monitor@ member rtn. (50M)         & 54.8  & 54.8  & 0.1   \\
     3184Goroutine mutex lock (50M)                      & 34.0  & 34.0  & 0.0   \\
     3185Rust mutex lock (50M)                           & 33.0  & 33.2  & 0.8   \\
     3186Java synchronized method (50M)          & 31.0  & 30.9  & 0.5   \\
     3187% Java synchronized method (10 000 000 000)             & 31.0 & 30.2 & 0.9 \\
     3188Pthreads mutex Lock (50M)                       & 31.0  & 31.1  & 0.4
    31853189\end{tabular}
    31863190\end{multicols}
     
    32013205% To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca>
    32023206% Date: Fri, 24 Jan 2020 13:49:18 -0500
    3203 % 
     3207%
    32043208% I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the
    32053209% event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of
     
    32113215
    32123216\begin{multicols}{2}
    3213 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3214 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3215 @coroutine@ C {};
    3216 void main( C & ) { for () { @suspend;@ } }
     3217\begin{cfa}[xleftmargin=0pt]
     3218`coroutine` C {};
     3219void main( C & ) { for () { `suspend;` } }
    32173220int main() { // coroutine test
    32183221        C c;
    3219         BENCH( for ( N ) { @resume( c );@ } )
     3222        BENCH( for ( N ) { `resume( c );` } )
    32203223        sout | result;
    32213224}
    32223225int main() { // thread test
    3223         BENCH( for ( N ) { @yield();@ } )
     3226        BENCH( for ( N ) { `yield();` } )
    32243227        sout | result;
    32253228}
     
    32343237\label{t:ctx-switch}
    32353238\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3236 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3237 C function                      & 1.8           & 1.8           & 0.0   \\
    3238 \CFA generator          & 1.8           & 2.0           & 0.3   \\
    3239 \CFA coroutine          & 32.5          & 32.9          & 0.8   \\
    3240 \CFA thread                     & 93.8          & 93.6          & 2.2   \\
    3241 \uC coroutine           & 50.3          & 50.3          & 0.2   \\
    3242 \uC thread                      & 97.3          & 97.4          & 1.0   \\
    3243 Python generator        & 40.9          & 41.3          & 1.5   \\
    3244 Node.js await           & 1852.2        & 1854.7        & 16.4  \\
    3245 Node.js generator       & 33.3          & 33.4          & 0.3   \\
    3246 Goroutine thread        & 143.0         & 143.3         & 1.1   \\
    3247 Rust async await        & 32.0          & 32.0          & 0.0   \\
    3248 Rust tokio thread       & 143.0         & 143.0         & 1.7   \\
    3249 Rust thread                     & 332.0         & 331.4         & 2.4   \\
    3250 Java thread                     & 405.0         & 415.0         & 17.6  \\
    3251 Pthreads thread         & 334.3         & 335.2         & 3.9
     3239\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3240C function (10B)                        & 1.8           & 1.8           & 0.0   \\
     3241\CFA generator (5B)                     & 1.8           & 2.0           & 0.3   \\
     3242\CFA coroutine (100M)           & 32.5          & 32.9          & 0.8   \\
     3243\CFA thread (100M)                      & 93.8          & 93.6          & 2.2   \\
     3244\uC coroutine (100M)            & 50.3          & 50.3          & 0.2   \\
     3245\uC thread (100M)                       & 97.3          & 97.4          & 1.0   \\
     3246Python generator (100M)         & 40.9          & 41.3          & 1.5   \\
     3247Node.js await (5M)                      & 1852.2        & 1854.7        & 16.4  \\
     3248Node.js generator (100M)        & 33.3          & 33.4          & 0.3   \\
     3249Goroutine thread (100M)         & 143.0         & 143.3         & 1.1   \\
     3250Rust async await (100M)         & 32.0          & 32.0          & 0.0   \\
     3251Rust tokio thread (100M)        & 143.0         & 143.0         & 1.7   \\
     3252Rust thread (25M)                       & 332.0         & 331.4         & 2.4   \\
     3253Java thread (100M)                      & 405.0         & 415.0         & 17.6  \\
     3254% Java thread (  100 000 000)                   & 413.0 & 414.2 & 6.2 \\
     3255% Java thread (5 000 000 000)                   & 415.0 & 415.2 & 6.1 \\
     3256Pthreads thread (25M)           & 334.3         & 335.2         & 3.9
    32523257\end{tabular}
    32533258\end{multicols}
     
    32583263Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results.
    32593264Note, pthreads has a fast zero-contention mutex lock checked in user space.
    3260 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions.
     3265Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions (context-switching or locking).
     3266As well, for locking experiments, M:N threading has less contention if only one kernel thread is used.
    32613267Languages with stackful coroutines have higher cost than stackless coroutines because of stack allocation and context switching;
    32623268however, stackful \uC and \CFA coroutines have approximately the same performance as stackless Python and Node.js generators.
    32633269The \CFA stackless generator is approximately 25 times faster for suspend/resume and 200 times faster for creation than stackless Python and Node.js generators.
     3270The Node.js context-switch is costly when asynchronous await must enter the event engine because a promise is not fulfilled.
     3271Finally, the benchmark results correlate across programming languages with and without JIT, indicating the JIT has completed any runtime optimizations.
    32643272
    32653273
     
    33193327
    33203328The authors recognize the design assistance of Aaron Moss, Rob Schluntz, Andrew Beach, and Michael Brooks; David Dice for commenting and helping with the Java benchmarks; and Gregor Richards for helping with the Node.js benchmarks.
    3321 This research is funded by a grant from Waterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.
     3329This research is funded by the NSERC/Waterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.
    33223330
    33233331{%
  • doc/papers/concurrency/annex/local.bib

    rae2c27a rc76bd34  
    5959@manual{Cpp-Transactions,
    6060        keywords        = {C++, Transactional Memory},
    61         title           = {Technical Specification for C++ Extensions for Transactional Memory},
     61        title           = {Tech. Spec. for C++ Extensions for Transactional Memory},
    6262        organization= {International Standard ISO/IEC TS 19841:2015 },
    6363        publisher   = {American National Standards Institute},
  • doc/papers/concurrency/mail2

    rae2c27a rc76bd34  
    959959Software: Practice and Experience Editorial Office
    960960
     961
     962
     963Date: Wed, 2 Sep 2020 20:55:34 +0000
     964From: Richard Jones <onbehalfof@manuscriptcentral.com>
     965Reply-To: R.E.Jones@kent.ac.uk
     966To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     967Subject: Software: Practice and Experience - Decision on Manuscript ID
     968 SPE-19-0219.R2
     969
     97002-Sep-2020
     971
     972Dear Dr Buhr,
     973
     974Many thanks for submitting SPE-19-0219.R2 entitled "Advanced Control-flow and Concurrency in Cforall" to Software: Practice and Experience. The paper has now been reviewed and the comments of the referees are included at the bottom of this letter. I apologise for the length of time it has taken to get these.
     975
     976Both reviewers consider this paper to be close to acceptance. However, before I can accept this paper, I would like you address the comments of Reviewer 2, particularly with regard to the description of the adaptation Java harness to deal with warmup. I would expect to see a convincing argument that the computation has reached a steady state. I would also like you to provide the values for N for each benchmark run. This should be very straightforward for you to do. There are a couple of papers on steady state that you may wish to consult (though I am certainly not pushing my own work).
     977
     9781) Barrett, Edd; Bolz-Tereick, Carl Friedrich; Killick, Rebecca; Mount, Sarah and Tratt, Laurence. Virtual Machine Warmup Blows Hot and Cold. OOPSLA 2017. https://doi.org/10.1145/3133876
     979Virtual Machines (VMs) with Just-In-Time (JIT) compilers are traditionally thought to execute programs in two phases: the initial warmup phase determines which parts of a program would most benefit from dynamic compilation, before JIT compiling those parts into machine code; subsequently the program is said to be at a steady state of peak performance. Measurement methodologies almost always discard data collected during the warmup phase such that reported measurements focus entirely on peak performance. We introduce a fully automated statistical approach, based on changepoint analysis, which allows us to determine if a program has reached a steady state and, if so, whether that represents peak performance or not. Using this, we show that even when run in the most controlled of circumstances, small, deterministic, widely studied microbenchmarks often fail to reach a steady state of peak performance on a variety of common VMs. Repeating our experiment on 3 different machines, we found that at most 43.5% of pairs consistently reach a steady state of peak performance.
     980
     9812) Kalibera, Tomas and Jones, Richard. Rigorous Benchmarking in Reasonable Time. ISMM  2013. https://doi.org/10.1145/2555670.2464160
     982Experimental evaluation is key to systems research. Because modern systems are complex and non-deterministic, good experimental methodology demands that researchers account for uncertainty. To obtain valid results, they are expected to run many iterations of benchmarks, invoke virtual machines (VMs) several times, or even rebuild VM or benchmark binaries more than once. All this repetition costs time to complete experiments. Currently, many evaluations give up on sufficient repetition or rigorous statistical methods, or even run benchmarks only in training sizes. The results reported often lack proper variation estimates and, when a small difference between two systems is reported, some are simply unreliable.In contrast, we provide a statistically rigorous methodology for repetition and summarising results that makes efficient use of experimentation time. Time efficiency comes from two key observations. First, a given benchmark on a given platform is typically prone to much less non-determinism than the common worst-case of published corner-case studies. Second, repetition is most needed where most uncertainty arises (whether between builds, between executions or between iterations). We capture experimentation cost with a novel mathematical model, which we use to identify the number of repetitions at each level of an experiment necessary and sufficient to obtain a given level of precision.We present our methodology as a cookbook that guides researchers on the number of repetitions they should run to obtain reliable results. We also show how to present results with an effect size confidence interval. As an example, we show how to use our methodology to conduct throughput experiments with the DaCapo and SPEC CPU benchmarks on three recent platforms.
     983
     984You have 42 days from the date of this email to submit your revision. If you are unable to complete the revision within this time, please contact me to request a short extension.
     985
     986You can upload your revised manuscript and submit it through your Author Center. Log into https://mc.manuscriptcentral.com/spe and enter your Author Center, where you will find your manuscript title listed under "Manuscripts with Decisions".
     987
     988When submitting your revised manuscript, you will be able to respond to the comments made by the referee(s) in the space provided.  You can use this space to document any changes you make to the original manuscript.
     989
     990If you would like help with English language editing, or other article preparation support, Wiley Editing Services offers expert help with English Language Editing, as well as translation, manuscript formatting, and figure formatting at www.wileyauthors.com/eeo/preparation. You can also check out our resources for Preparing Your Article for general guidance about writing and preparing your manuscript at www.wileyauthors.com/eeo/prepresources.
     991 
     992Once again, thank you for submitting your manuscript to Software: Practice and Experience. I look forward to receiving your revision.
     993
     994Sincerely,
     995Richard
     996
     997Prof. Richard Jones
     998Editor, Software: Practice and Experience
     999R.E.Jones@kent.ac.uk
     1000
     1001Referee(s)' Comments to Author:
     1002
     1003Reviewing: 1
     1004
     1005Comments to the Author
     1006Overall, I felt that this draft was an improvement on previous drafts and I don't have further changes to request.
     1007
     1008I appreciated the new language to clarify the relationship of external and internal scheduling, for example, as well as the new measurements of Rust tokio. Also, while I still believe that the choice between thread/generator/coroutine and so forth could be made crisper and clearer, the current draft of Section 2 did seem adequate to me in terms of specifying the considerations that users would have to take into account to make the choice.
     1009
     1010
     1011Reviewing: 2
     1012
     1013Comments to the Author
     1014First: let me apologise for the delay on this review. I'll blame the global pandemic combined with my institution's senior management's counterproductive decisions for taking up most of my time and all of my energy.
     1015
     1016At this point, reading the responses, I think we've been around the course enough times that further iteration is unlikely to really improve the paper any further, so I'm happy to recommend acceptance.    My main comments are that there were some good points in the responses to *all* the reviews and I strongly encourage the authors to incorporate those discursive responses into the final paper so they may benefit readers as well as reviewers.   I agree with the recommendations of reviewer #2 that the paper could usefully be split in to two, which I think I made to a previous revision, but I'm happy to leave that decision to the Editor.
     1017
     1018Finally, the paper needs to describe how the Java harness was adapted to deal with warmup; why the computation has warmed up and reached a steady state - similarly for js and Python. The tables should also give the "N" chosen for each benchmark run.
     1019 
     1020minor points
     1021* don't start sentences with "However"
     1022* most downloaded isn't an "Award"
     1023
     1024
     1025
     1026Date: Thu, 1 Oct 2020 05:34:29 +0000
     1027From: Richard Jones <onbehalfof@manuscriptcentral.com>
     1028Reply-To: R.E.Jones@kent.ac.uk
     1029To: pabuhr@uwaterloo.ca
     1030Subject: Revision reminder - SPE-19-0219.R2
     1031
     103201-Oct-2020
     1033
     1034Dear Dr Buhr
     1035
     1036SPE-19-0219.R2
     1037
     1038This is a reminder that your opportunity to revise and re-submit your manuscript will expire 14 days from now. If you require more time please contact me directly and I may grant an extension to this deadline, otherwise the option to submit a revision online, will not be available.
     1039
     1040If your article is of potential interest to the general public, (which means it must be timely, groundbreaking, interesting and impact on everyday society) then please e-mail ejp@wiley.co.uk explaining the public interest side of the research. Wiley will then investigate the potential for undertaking a global press campaign on the article.
     1041
     1042I look forward to receiving your revision.
     1043
     1044Sincerely,
     1045
     1046Prof. Richard Jones
     1047Editor, Software: Practice and Experience
     1048
     1049https://mc.manuscriptcentral.com/spe
     1050
     1051
     1052
     1053Date: Tue, 6 Oct 2020 15:29:41 +0000
     1054From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com>
     1055Reply-To: speoffice@wiley.com
     1056To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     1057Subject: SPE-19-0219.R3 successfully submitted
     1058
     105906-Oct-2020
     1060
     1061Dear Dr Buhr,
     1062
     1063Your manuscript entitled "Advanced Control-flow and Concurrency in Cforall" has been successfully submitted online and is presently being given full consideration for publication in Software: Practice and Experience.
     1064
     1065Your manuscript number is SPE-19-0219.R3.  Please mention this number in all future correspondence regarding this submission.
     1066
     1067You can view the status of your manuscript at any time by checking your Author Center after logging into https://mc.manuscriptcentral.com/spe.  If you have difficulty using this site, please click the 'Get Help Now' link at the top right corner of the site.
     1068
     1069
     1070Thank you for submitting your manuscript to Software: Practice and Experience.
     1071
     1072Sincerely,
     1073
     1074Software: Practice and Experience Editorial Office
     1075
  • doc/refrat/refrat.tex

    rae2c27a rc76bd34  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Jan 31 17:30:23 2018
    14 %% Update Count     : 108
     13%% Last Modified On : Mon Oct  5 09:02:53 2020
     14%% Update Count     : 110
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
    3533\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3634\usepackage{latexsym}                                   % \Box glyph
    3735\usepackage{mathptmx}                                   % better math font with "times"
    3836\usepackage[usenames]{color}
    39 \input{common}                                          % common CFA document macros
    40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    41 \usepackage{breakurl}
    42 \renewcommand{\UrlFont}{\small\sf}
    43 
    44 \usepackage[pagewise]{lineno}
    45 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    46 \usepackage[firstpage]{draftwatermark}
    47 \SetWatermarkLightness{0.9}
    48 
    49 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    50 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    51 % AFTER HYPERREF.
    52 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    53 
    54 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    55 \setlength{\headsep}{0.25in}
    56 
    57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    58 
    59 \CFAStyle                                                                                               % use default CFA format-style
    60 \lstnewenvironment{C++}[1][]                            % use C++ style
    61 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}}
    62 {}
    63 
     37\newcommand{\CFALatin}{}
    6438% inline code ©...© (copyright symbol) emacs: C-q M-)
    6539% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6943% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    7044% math escape $...$ (dollar symbol)
     45\input{common}                                          % common CFA document macros
     46\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     47\usepackage{breakurl}
     48\renewcommand{\UrlFont}{\small\sf}
     49
     50\usepackage[pagewise]{lineno}
     51\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     52\usepackage[firstpage]{draftwatermark}
     53\SetWatermarkLightness{0.9}
     54
     55% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     56% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     57% AFTER HYPERREF.
     58\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     59
     60\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     61\setlength{\headsep}{0.25in}
    7162
    7263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    7364
     65\CFAStyle                                                                                               % use default CFA format-style
     66\lstnewenvironment{C++}[1][]                            % use C++ style
     67{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     68{}
     69
     70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     71
    7472% Names used in the document.
    75 \newcommand{\Version}{\input{../../version}}
     73\newcommand{\Version}{\input{build/version}}
    7674\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7775\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
  • doc/theses/andrew_beach_MMath/thesis.tex

    rae2c27a rc76bd34  
    3434\usepackage[toc,abbreviations]{glossaries-extra}
    3535
    36 % Main glossary entries -- definitions of relevant terminology
    37 \newglossaryentry{computer}
    38 {
    39 name=computer,
    40 description={A programmable machine that receives input data,
    41                stores and manipulates the data, and provides
    42                formatted output}
    43 }
    44 
    45 % Nomenclature glossary entries -- New definitions, or unusual terminology
    46 \newglossary*{nomenclature}{Nomenclature}
    47 \newglossaryentry{dingledorf}
    48 {
    49 type=nomenclature,
    50 name=dingledorf,
    51 description={A person of supposed average intelligence who makes incredibly
    52                brainless misjudgments}
    53 }
    54 
    55 % List of Abbreviations (abbreviations are from the glossaries-extra package)
    56 \newabbreviation{aaaaz}{AAAAZ}{American Association of Amature Astronomers
    57                and Zoologists}
    58 
    59 % List of Symbols
    60 \newglossary*{symbols}{List of Symbols}
    61 \newglossaryentry{rvec}
    62 {
    63 name={$\mathbf{v}$},
    64 sort={label},
    65 type=symbols,
    66 description={Random vector: a location in n-dimensional Cartesian space, where
    67                each dimensional component is determined by a random process}
    68 }
     36% Define all the glossaries.
     37\input{glossaries}
    6938
    7039% Generate the glossaries defined above.
  • doc/theses/thierry_delisle_PhD/.gitignore

    rae2c27a rc76bd34  
    1111comp_II/comp_II.pdf
    1212comp_II/comp_II.ps
     13comp_II/presentation.pdf
     14
     15thesis/build/
     16thesis/fig/*.fig.bak
     17thesis/thesis.pdf
     18thesis/thesis.ps
    1319
    1420!Makefile
  • doc/theses/thierry_delisle_PhD/comp_II/comp_II.tex

    rae2c27a rc76bd34  
    6060\section{Introduction}
    6161\subsection{\CFA and the \CFA concurrency package}
    62 \CFA\cite{Moss18} is a modern, polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.
     62\CFA~\cite{Moss18} is a modern, polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.
    6363It aims to add high-productivity features while maintaining the predictable performance of C.
    64 As such, concurrency in \CFA\cite{Delisle19} aims to offer simple and safe high-level tools while still allowing performant code.
    65 \CFA concurrent code is written in the synchronous programming paradigm but uses \glspl{uthrd} in order to achieve the simplicity and maintainability of synchronous programming without sacrificing the efficiency of asynchronous programming.
     64As such, concurrency in \CFA~\cite{Delisle19} aims to offer simple and safe high-level tools while still allowing performant code.
     65\CFA concurrent code is written in the synchronous programming paradigm but uses \glspl{uthrd} to achieve the simplicity and maintainability of synchronous programming without sacrificing the efficiency of asynchronous programming.
    6666As such, the \CFA \newterm{scheduler} is a preemptive user-level scheduler that maps \glspl{uthrd} onto \glspl{kthrd}.
    6767
     68\subsection{Scheduling}
    6869\newterm{Scheduling} occurs when execution switches from one thread to another, where the second thread is implicitly chosen by the scheduler.
    69 This scheduling is an indirect handoff, as opposed to generators and coroutines which explicitly switch to the next generator and coroutine respectively.
     70This scheduling is an indirect handoff, as opposed to generators and coroutines that explicitly switch to the next generator and coroutine respectively.
    7071The cost of switching between two threads for an indirect handoff has two components:
    7172\begin{enumerate}
     
    7576and the cost of scheduling, \ie deciding which thread to run next among all the threads ready to run.
    7677\end{enumerate}
    77 The first cost is generally constant and fixed\footnote{Affecting the constant context-switch cost is whether it is done in one step, after the scheduling, or in two steps, context-switching to a third fixed thread before scheduling.}, while the scheduling cost can vary based on the system state.
    78 Adding multiple \glspl{kthrd} does not fundamentally change the scheduler semantics or requirements, it simply adds new correctness requirements, \ie \newterm{linearizability}\footnote{Meaning, however fast the CPU threads run, there is an equivalent sequential order that gives the same result.}, and a new dimension to performance: scalability, where scheduling cost now also depends on contention.
     78The first cost is generally constant\footnote{Affecting the constant context-switch cost is whether it is done in one step, where the first thread schedules the second, or in two steps, where the first thread context switches to a third scheduler thread.}, while the scheduling cost can vary based on the system state.
     79Adding multiple \glspl{kthrd} does not fundamentally change the scheduler semantics or requirements, it simply adds new correctness requirements, \ie \newterm{linearizability}\footnote{Meaning however fast the CPU threads run, there is an equivalent sequential order that gives the same result.}, and a new dimension to performance: scalability, where scheduling cost also depends on contention.
    7980The more threads switch, the more the administration cost of scheduling becomes noticeable.
    8081It is therefore important to build a scheduler with the lowest possible cost and latency.
    8182Another important consideration is \newterm{fairness}.
    8283In principle, scheduling should give the illusion of perfect fairness, where all threads ready to run are running \emph{simultaneously}.
     84In practice, there can be advantages to unfair scheduling, similar to the express cash register at a grocery store.
    8385While the illusion of simultaneity is easier to reason about, it can break down if the scheduler allows too much unfairness.
    8486Therefore, the scheduler should offer as much fairness as needed to guarantee eventual progress, but use unfairness to help performance.
    85 In practice, threads must wait in turn but there can be advantages to unfair scheduling, similar to the express cash register at a grocery store.
    86 
    87 The goal of this research is to produce a scheduler that is simple for programmers to understand and offers good performance.
     87
     88\subsection{Research Goal}
     89The goal of this research is to produce a scheduler that is simple for programmers to understand and offers good general performance.
    8890Here understandability does not refer to the API but to how much scheduling concerns programmers need to take into account when writing a \CFA concurrent package.
    89 Therefore, the main goal of this proposal is :
     91Therefore, the main consequence of this goal is :
    9092\begin{quote}
    9193The \CFA scheduler should be \emph{viable} for \emph{any} workload.
    9294\end{quote}
    9395
    94 For a general-purpose scheduler, it is impossible to produce an optimal algorithm as it would require knowledge of the future behaviour of threads.
    95 As such, scheduling performance is generally either defined by the best-case scenario, \ie a workload to which the scheduler is tailored, or the worst-case scenario, \ie the scheduler behaves no worse than \emph{X}.
     96For a general-purpose scheduler, it is impossible to produce an optimal algorithm as that requires knowledge of the future behaviour of threads.
     97As such, scheduling performance is generally either defined by a best-case scenario, \ie a workload to which the scheduler is tailored, or a worst-case scenario, \ie the scheduler behaves no worse than \emph{X}.
    9698For this proposal, the performance is evaluated using the second approach to allow \CFA programmers to rely on scheduling performance.
    9799Because there is no optimal scheduler, ultimately \CFA may allow programmers to write their own scheduler; but that is not the subject of this proposal, which considers only the default scheduler.
     
    103105        \item creating an abstraction layer over the operating system to handle kernel-threads spinning unnecessarily,
    104106        \item scheduling blocking I/O operations,
    105         \item and writing sufficient library tools to allow developers to indirectly use the scheduler, either through tuning knobs or replacing the default scheduler.
     107        \item and writing sufficient library tools to allow developers to indirectly use the scheduler, either through tuning knobs in the default scheduler or replacing the default scheduler.
    106108\end{enumerate}
    107109
     
    119121\paragraph{Performance} The performance of a scheduler can generally be measured in terms of scheduling cost, scalability and latency.
    120122\newterm{Scheduling cost} is the cost to switch from one thread to another, as mentioned above.
    121 For simple applications, where a single kernel thread does most of the scheduling, it is generally the dominating cost.
    122 \newterm{Scalability} is the cost of adding multiple kernel threads because it increases the time for context switching because of contention by multiple threads accessing shared resources, \eg the ready queue.
     123For compute-bound concurrent applications with little context switching, the scheduling cost is negligible.
     124For applications with high context-switch rates, scheduling cost can begin to dominating the cost.
     125\newterm{Scalability} is the cost of adding multiple kernel threads.
     126It can increase the time for scheduling because of contention from the multiple threads accessing shared resources, \eg a single ready queue.
    123127Finally, \newterm{tail latency} is service delay and relates to thread fairness.
    124 Specifically, latency measures how long a thread waits to run once scheduled and is evaluated in the worst case.
     128Specifically, latency measures how long a thread waits to run once scheduled and is evaluated by the worst case.
    125129The \CFA scheduler should offer good performance for all three metrics.
    126130
     
    128132\newterm{Eventual progress} guarantees every scheduled thread is eventually run, \ie prevent starvation.
    129133As a hard requirement, the \CFA scheduler must guarantee eventual progress, otherwise the above-mentioned illusion of simultaneous execution is broken and the scheduler becomes much more complex to reason about.
    130 \newterm{Predictability} and \newterm{reliability} mean similar workloads achieve similar performance and programmer execution intuition is respected.
    131 For example, a thread that yields aggressively should not run more often than other tasks.
     134\newterm{Predictability} and \newterm{reliability} mean similar workloads achieve similar performance so programmer execution intuition is respected.
     135For example, a thread that yields aggressively should not run more often than other threads.
    132136While this is intuitive, it does not hold true for many work-stealing or feedback based schedulers.
    133 The \CFA scheduler must guarantee eventual progress and should be predictable and offer reliable performance.
     137The \CFA scheduler must guarantee eventual progress, should be predictable, and offer reliable performance.
    134138
    135139\paragraph{Efficiency} Finally, efficient usage of CPU resources is also an important requirement and is discussed in depth towards the end of the proposal.
    136 \newterm{Efficiency} means avoiding using CPU cycles when there are no threads to run, and conversely, use all CPUs available when the workload can benefit from it.
     140\newterm{Efficiency} means avoiding using CPU cycles when there are no threads to run (to conserve energy), and conversely, using as many available CPU cycles when the workload can benefit from it.
    137141Balancing these two states is where the complexity lies.
    138142The \CFA scheduler should be efficient with respect to the underlying (shared) computer.
     
    146150\begin{enumerate}
    147151        \item Threads live long enough for useful feedback information to be gathered.
    148         \item Threads belong to multiple users so fairness across threads is insufficient.
     152        \item Threads belong to multiple users so fairness across users is important.
    149153\end{enumerate}
    150154
     
    159163In the case of the \CFA scheduler, every thread runs in the same user space and is controlled by the same user.
    160164Fairness across users is therefore a given and it is then possible to safely ignore the possibility that threads are malevolent.
    161 This approach allows for a much simpler fairness metric and in this proposal \emph{fairness} is defined as: when multiple threads are cycling through the system, the total ordering of threads being scheduled, \ie pushed onto the ready queue, should not differ much from the total ordering of threads being executed, \ie popped from the ready queue.
     165This approach allows for a much simpler fairness metric, and in this proposal, \emph{fairness} is defined as:
     166\begin{quote}
     167When multiple threads are cycling through the system, the total ordering of threads being scheduled, \ie pushed onto the ready queue, should not differ much from the total ordering of threads being executed, \ie popped from the ready queue.
     168\end{quote}
    162169
    163170Since feedback is not necessarily feasible within the lifetime of all threads and a simple fairness metric can be used, the scheduling strategy proposed for the \CFA runtime does not use per-threads feedback.
     
    169176Threads with equal priority are scheduled using a secondary strategy, often something simple like round robin or FIFO.
    170177A consequence of priority is that, as long as there is a thread with a higher priority that desires to run, a thread with a lower priority does not run.
    171 This possible starving of threads can dramatically increase programming complexity since starving threads and priority inversion (prioritizing a lower priority thread) can both lead to serious problems.
     178The potential for thread starvation dramatically increases programming complexity since starving threads and priority inversion (prioritizing a lower priority thread) can both lead to serious problems.
    172179
    173180An important observation is that threads do not need to have explicit priorities for problems to occur.
    174 Indeed, any system with multiple ready queues that attempts to exhaust one queue before accessing the other queues, essentially provide implicit priority, which can encounter starvation problems.
     181Indeed, any system with multiple ready queues that attempts to exhaust one queue before accessing the other queues, essentially provides implicit priority, which can encounter starvation problems.
    175182For example, a popular scheduling strategy that suffers from implicit priorities is work stealing.
    176183\newterm{Work stealing} is generally presented as follows:
     
    180187        \item If a processor's ready queue is empty, attempt to run threads from some other processor's ready queue.
    181188\end{enumerate}
    182 
    183189In a loaded system\footnote{A \newterm{loaded system} is a system where threads are being run at the same rate they are scheduled.}, if a thread does not yield, block, or preempt for an extended period of time, threads on the same processor's list starve if no other processors exhaust their list.
    184190
    185 Since priorities can be complex for programmers to incorporate into their execution intuition, the scheduling strategy proposed for the \CFA runtime does not use a strategy with either implicit or explicit thread priorities.
     191Since priorities can be complex for programmers to incorporate into their execution intuition, the \CFA scheduling strategy does not provided explicit priorities and attempts to eliminate implicit priorities.
    186192
    187193\subsection{Schedulers without feedback or priorities}
     
    191197Thankfully, strict FIFO is not needed for sufficient fairness.
    192198Since concurrency is inherently non-deterministic, fairness concerns in scheduling are only a problem if a thread repeatedly runs before another thread can run.
    193 Some relaxation is possible because non-determinism means programmers already handle ordering problems to produce correct code and hence rely on weak guarantees, \eg that a specific thread will \emph{eventually} run.
     199Some relaxation is possible because non-determinism means programmers already handle ordering problems to produce correct code and hence rely on weak guarantees, \eg that a thread \emph{eventually} runs.
    194200Since some reordering does not break correctness, the FIFO fairness guarantee can be significantly relaxed without causing problems.
    195201For this proposal, the target guarantee is that the \CFA scheduler provides \emph{probable} FIFO ordering, which allows reordering but makes it improbable that threads are reordered far from their position in total ordering.
    196202
    197203The \CFA scheduler fairness is defined as follows:
    198 \begin{itemize}
    199         \item Given two threads $X$ and $Y$, the odds that thread $X$ runs $N$ times \emph{after} thread $Y$ is scheduled but \emph{before} it is run, decreases exponentially with regard to $N$.
    200 \end{itemize}
     204\begin{quote}
     205Given two threads $X$ and $Y$, the odds that thread $X$ runs $N$ times \emph{after} thread $Y$ is scheduled but \emph{before} it is run, decreases exponentially with regard to $N$.
     206\end{quote}
    201207While this is not a bounded guarantee, the probability that unfairness persist for long periods of times decreases exponentially, making persisting unfairness virtually impossible.
    202208
     
    210216The described queue uses an array of underlying strictly FIFO queues as shown in Figure~\ref{fig:base}\footnote{For this section, the number of underlying queues is assumed to be constant.
    211217Section~\ref{sec:resize} discusses resizing the array.}.
    212 Pushing new data is done by selecting one of these underlying queues at random, recording a timestamp for the operation and pushing to the selected queue.
     218Pushing new data is done by selecting one of the underlying queues at random, recording a timestamp for the operation, and pushing to the selected queue.
    213219Popping is done by selecting two queues at random and popping from the queue with the oldest timestamp.
    214 A higher number of underlying queues lead to less contention on each queue and therefore better performance.
    215 In a loaded system, it is highly likely the queues are non-empty, \ie several tasks are on each of the underlying queues.
    216 This means that selecting a queue at random to pop from is highly likely to yield a queue with available items.
     220A higher number of underlying queues leads to less contention on each queue and therefore better performance.
     221In a loaded system, it is highly likely the queues are non-empty, \ie several threads are on each of the underlying queues.
     222For this case, selecting a queue at random to pop from is highly likely to yield a queue with available items.
    217223In Figure~\ref{fig:base}, ignoring the ellipsis, the chances of getting an empty queue is 2/7 per pick, meaning two random picks yield an item approximately 9 times out of 10.
    218224
     
    221227                \input{base.pstex_t}
    222228        \end{center}
    223         \caption{Relaxed FIFO list at the base of the scheduler: an array of strictly FIFO lists.
    224         The timestamp is in all nodes and cell arrays.}
     229        \caption{Loaded relaxed FIFO list base on an array of strictly FIFO lists.
     230        A timestamp appears in each node and array cell.}
    225231        \label{fig:base}
    226232\end{figure}
     
    230236                \input{empty.pstex_t}
    231237        \end{center}
    232         \caption{``More empty'' state of the queue: the array contains many empty cells.}
     238        \caption{Underloaded relaxed FIFO list where the array contains many empty cells.}
    233239        \label{fig:empty}
    234240\end{figure}
    235241
    236 When the ready queue is \emph{more empty}, \ie several of the queues are empty, selecting a random queue for popping is less likely to yield a successful selection and more attempts are needed, resulting in a performance degradation.
     242In an underloaded system, several of the queues are empty, so selecting a random queue for popping is less likely to yield a successful selection and more attempts are needed, resulting in a performance degradation.
    237243Figure~\ref{fig:empty} shows an example with fewer elements, where the chances of getting an empty queue is 5/7 per pick, meaning two random picks yield an item only half the time.
    238244Since the ready queue is not empty, the pop operation \emph{must} find an element before returning and therefore must retry.
     
    262268\end{table}
    263269
    264 Performance can be improved in case~D (Table~\ref{tab:perfcases}) by adding information to help processors find which inner queues are used.
     270Performance can be improved in Table~\ref{tab:perfcases} case~D by adding information to help processors find which inner queues are used.
    265271This addition aims to avoid the cost of retrying the pop operation but does not affect contention on the underlying queues and can incur some management cost for both push and pop operations.
    266272The approach used to encode this information can vary in density and be either global or local.
     
    273279With a multi-word bitmask, this maximum limit can be increased arbitrarily, but it is not possible to check if the queue is empty by reading the bitmask atomically.
    274280
    275 Finally, a dense bitmap, either single or multi-word, causes additional problems in case C (Table 1), because many processors are continuously scanning the bitmask to find the few available threads.
     281Finally, a dense bitmap, either single or multi-word, causes additional problems in Table~\ref{tab:perfcases} case C, because many processors are continuously scanning the bitmask to find the few available threads.
    276282This increased contention on the bitmask(s) reduces performance because of cache misses after updates and the bitmask is updated more frequently by the scanning processors racing to read and/or update that information.
    277283This increased update frequency means the information in the bitmask is more often stale before a processor can use it to find an item, \ie mask read says there are available user threads but none on queue.
     
    279285\begin{figure}
    280286        \begin{center}
    281                 {\resizebox{0.8\textwidth}{!}{\input{emptybit}}}
    282         \end{center}
    283         \caption{``More empty'' queue with added bitmask to indicate which array cells have items.}
     287                {\resizebox{0.73\textwidth}{!}{\input{emptybit}}}
     288        \end{center}
     289        \vspace*{-5pt}
     290        \caption{Underloaded queue with added bitmask to indicate which array cells have items.}
    284291        \label{fig:emptybit}
     292        \begin{center}
     293                {\resizebox{0.73\textwidth}{!}{\input{emptytree}}}
     294        \end{center}
     295        \vspace*{-5pt}
     296        \caption{Underloaded queue with added binary search tree indicate which array cells have items.}
     297        \label{fig:emptytree}
     298        \begin{center}
     299                {\resizebox{0.9\textwidth}{!}{\input{emptytls}}}
     300        \end{center}
     301        \vspace*{-5pt}
     302        \caption{Underloaded queue with added per processor bitmask to indicate which array cells have items.}
     303        \label{fig:emptytls}
    285304\end{figure}
    286305
    287 Figure~\ref{fig:emptytree} shows another approach using a hierarchical tree data-structure to reduce contention and has been shown to work in similar cases~\cite{ellen2007snzi}\footnote{This particular paper seems to be patented in the US.
    288 How does that affect \CFA? Can I use it in my work?}.
    289 However, this approach may lead to poorer performance in case~B (Table~\ref{tab:perfcases}) due to the inherent pointer chasing cost and already low contention cost in that case.
    290 
    291 \begin{figure}
    292         \begin{center}
    293                 {\resizebox{0.8\textwidth}{!}{\input{emptytree}}}
    294         \end{center}
    295         \caption{``More empty'' queue with added binary search tree indicate which array cells have items.}
    296         \label{fig:emptytree}
    297 \end{figure}
    298 
    299 Finally, a third approach is to use dense information, similar to the bitmap, but have each thread keep its own independent copy of it.
     306Figure~\ref{fig:emptytree} shows an approach using a hierarchical tree data-structure to reduce contention and has been shown to work in similar cases~\cite{ellen2007snzi}.
     307However, this approach may lead to poorer performance in Table~\ref{tab:perfcases} case~B due to the inherent pointer chasing cost and already low contention cost in that case.
     308
     309Figure~\ref{fig:emptytls} shows an approach using dense information, similar to the bitmap, but have each thread keep its own independent copy of it.
    300310While this approach can offer good scalability \emph{and} low latency, the liveliness of the information can become a problem.
    301 In the simple cases, local copies of which underlying queues are empty can become stale and end-up not being useful for the pop operation.
     311In the simple cases, local copies can become stale and end-up not being useful for the pop operation.
    302312A more serious problem is that reliable information is necessary for some parts of this algorithm to be correct.
    303313As mentioned in this section, processors must know \emph{reliably} whether the list is empty or not to decide if they can return \texttt{NULL} or if they must keep looking during a pop operation.
    304314Section~\ref{sec:sleep} discusses another case where reliable information is required for the algorithm to be correct.
    305315
    306 \begin{figure}
    307         \begin{center}
    308                 \input{emptytls}
    309         \end{center}
    310         \caption{``More empty'' queue with added per processor bitmask to indicate which array cells have items.}
    311         \label{fig:emptytls}
    312 \end{figure}
    313 
    314316There is a fundamental tradeoff among these approach.
    315 Dense global information about empty underlying queues helps zero-contention cases at the cost of high-contention case.
    316 Sparse global information helps high-contention cases but increases latency in zero-contention-cases, to read and ``aggregate'' the information\footnote{Hierarchical structures, \eg binary search tree, effectively aggregate information but follow pointer chains, learning information at each node.
     317Dense global information about empty underlying queues helps zero-contention cases at the cost of the high-contention case.
     318Sparse global information helps high-contention cases but increases latency in zero-contention cases to read and ``aggregate'' the information\footnote{Hierarchical structures, \eg binary search tree, effectively aggregate information but follow pointer chains, learning information at each node.
    317319Similarly, other sparse schemes need to read multiple cachelines to acquire all the information needed.}.
    318 Finally, dense local information has both the advantages of low latency in zero-contention cases and scalability in high-contention cases. However the information can become stale making it difficult to use to ensure correctness.
     320Finally, dense local information has both the advantages of low latency in zero-contention cases and scalability in high-contention cases.
     321However, the information can become stale making it difficult to use to ensure correctness.
    319322The fact that these solutions have these fundamental limits suggest to me a better solution that attempts to combine these properties in an interesting way.
    320323Also, the lock discussed in Section~\ref{sec:resize} allows for solutions that adapt to the number of processors, which could also prove useful.
     
    323326
    324327How much scalability is actually needed is highly debatable.
    325 \emph{libfibre}\cite{libfibre} has compared favourably to other schedulers in webserver tests\cite{Karsten20} and uses a single atomic counter in its scheduling algorithm similarly to the proposed bitmask.
     328\emph{libfibre}~\cite{libfibre} has compared favourably to other schedulers in webserver tests~\cite{Karsten20} and uses a single atomic counter in its scheduling algorithm similarly to the proposed bitmask.
    326329As such, the single atomic instruction on a shared cacheline may be sufficiently performant.
    327330
    328 I have built a prototype of this ready queue in the shape of a data queue, \ie nodes on the queue are structures with a single int representing a thread and intrusive data fields.
    329 Using this prototype, I ran preliminary performance experiments that confirm the expected performance in Table~\ref{tab:perfcases}.
    330 However, these experiments only offer a hint at the actual performance of the scheduler since threads form more complex operations than simple integer nodes, \eg threads are not independent of each other, when a thread blocks some other thread must intervene to wake it.
     331I have built a prototype of this ready queue in the shape of a data queue, \ie nodes on the queue are structures with a single $int$ representing a thread and intrusive data fields.
     332Using this prototype, preliminary performance experiments confirm the expected performance in Table~\ref{tab:perfcases}.
     333However, these experiments only offer a hint at the actual performance of the scheduler since threads are involved in more complex operations, \eg threads are not independent of each other: when a thread blocks some other thread must intervene to wake it.
    331334
    332335I have also integrated this prototype into the \CFA runtime, but have not yet created performance experiments to compare results, as creating one-to-one comparisons between the prototype and the \CFA runtime will be complex.
     
    345348Threads on a cluster are always scheduled on one of the processors of the cluster.
    346349Currently, the runtime handles dynamically adding and removing processors from clusters at any time.
    347 Since this is part of the existing design, the proposed scheduler must also support this behaviour.
     350Since this feature is part of the existing design, the proposed scheduler must also support this behaviour.
    348351However, dynamically resizing a cluster is considered a rare event associated with setup, tear down and major configuration changes.
    349352This assumption is made both in the design of the proposed scheduler as well as in the original design of the \CFA runtime system.
    350353As such, the proposed scheduler must honour the correctness of this behaviour but does not have any performance objectives with regard to resizing a cluster.
    351 How long adding or removing processors take and how much this disrupts the performance of other threads is considered a secondary concern since it should be amortized over long periods of times.
     354That is, the time to add or remove processors and how much this disrupts the performance of other threads is considered a secondary concern since it should be amortized over long periods of times.
    352355However, as mentioned in Section~\ref{sec:queue}, contention on the underlying queues can have a direct impact on performance.
    353356The number of underlying queues must therefore be adjusted as the number of processors grows or shrinks.
     
    371374
    372375There are possible alternatives to the reader-writer lock solution.
    373 This problem is effectively a memory reclamation problem and as such there is a large body of research on the subject\cite{michael2004hazard, brown2015reclaiming}.
     376This problem is effectively a memory reclamation problem and as such there is a large body of research on the subject~\cite{brown2015reclaiming, michael2004hazard}.
    374377However, the reader-write lock-solution is simple and can be leveraged to solve other problems (\eg processor ordering and memory reclamation of threads), which makes it an attractive solution.
    375378
     
    401404Individual processors always finish scheduling user threads before looking for new work, which means that the last processor to go to sleep cannot miss threads scheduled from inside the cluster (if they do, that demonstrates the ready queue is not linearizable).
    402405However, this guarantee does not hold if threads are scheduled from outside the cluster, either due to an external event like timers and I/O, or due to a user (or kernel) thread migrating from a different cluster.
    403 In this case, missed signals can lead to the cluster deadlocking\footnote{Clusters should only deadlock in cases where a \CFA programmer \emph{actually} write \CFA code that leads to a deadlock.}.
     406In this case, missed signals can lead to the cluster deadlocking\footnote{Clusters should only deadlock in cases where a \CFA programmer \emph{actually} writes \CFA code that leads to a deadlock.}.
    404407Therefore, it is important that the scheduling of threads include a mechanism where signals \emph{cannot} be missed.
    405408For performance reasons, it can be advantageous to have a secondary mechanism that allows signals to be missed in cases where it cannot lead to a deadlock.
    406 To be safe, this process must include a ``handshake'' where it is guaranteed that either~: the sleeping processor notices that a user thread is scheduled after the sleeping processor signalled its intent to block or code scheduling threads sees the intent to sleep before scheduling and be able to wake-up the processor.
     409To be safe, this process must include a ``handshake'' where it is guaranteed that either:
     410\begin{enumerate}
     411\item
     412the sleeping processor notices that a user thread is scheduled after the sleeping processor signalled its intent to block or
     413\item
     414code scheduling threads sees the intent to sleep before scheduling and be able to wake-up the processor.
     415\end{enumerate}
    407416This matter is complicated by the fact that pthreads and Linux offer few tools to implement this solution and no guarantee of ordering of threads waking up for most of these tools.
    408417
    409418Another important issue is avoiding kernel threads sleeping and waking frequently because there is a significant operating-system cost.
    410 This scenario happens when a program oscillates between high and low activity, needing most and then fewer processors.
     419This scenario happens when a program oscillates between high and low activity, needing most and then few processors.
    411420A possible partial solution is to order the processors so that the one which most recently went to sleep is woken up.
    412421This allows other sleeping processors to reach deeper sleep state (when these are available) while keeping ``hot'' processors warmer.
     
    417426Processors that are unnecessarily unblocked lead to unnecessary contention, CPU usage, and power consumption, while too many sleeping processors can lead to suboptimal throughput.
    418427Furthermore, transitions from sleeping to awake and vice versa also add unnecessary latency.
    419 There is already a wealth of research on the subject\cite{schillings1996engineering, wiki:thunderherd} and I may use an existing approach for the idle-sleep heuristic in this project, \eg\cite{Karsten20}.
     428There is already a wealth of research on the subject~\cite{schillings1996engineering, wiki:thunderherd} and I may use an existing approach for the idle-sleep heuristic in this project, \eg~\cite{Karsten20}.
    420429
    421430\subsection{Asynchronous I/O}
     
    432441an event-engine to (de)multiplex the operations,
    433442\item
    434 and a synchronous interface for users to use.
     443and a synchronous interface for users.
    435444\end{enumerate}
    436445None of these components currently exist in \CFA and I will need to build all three for this project.
    437446
    438 \paragraph{OS Abstraction}
    439 One fundamental part for converting blocking I/O operations into non-blocking ones is having an underlying asynchronous I/O interface to direct the I/O operations.
     447\paragraph{OS Asynchronous Abstraction}
     448One fundamental part for converting blocking I/O operations into non-blocking is having an underlying asynchronous I/O interface to direct the I/O operations.
    440449While there exists many different APIs for asynchronous I/O, it is not part of this proposal to create a novel API.
    441450It is sufficient to make one work in the complex context of the \CFA runtime.
    442 \uC uses the $select$\cite{select} as its interface, which handles ttys, pipes and sockets, but not disk.
     451\uC uses the $select$~\cite{select} as its interface, which handles ttys, pipes and sockets, but not disk.
    443452$select$ entails significant complexity and is being replaced in UNIX operating systems, which make it a less interesting alternative.
    444 Another popular interface is $epoll$\cite{epoll}, which is supposed to be cheaper than $select$.
    445 However, $epoll$ also does not handle the file system and anecdotal evidence suggest it has problems with Linux pipes and $TTY$s.
    446 A popular cross-platform alternative is $libuv$\cite{libuv}, which offers asynchronous sockets and asynchronous file system operations (among other features).
     453Another popular interface is $epoll$~\cite{epoll}, which is supposed to be cheaper than $select$.
     454However, $epoll$ also does not handle the file system and anecdotal evidence suggest it has problems with Linux pipes and ttys.
     455A popular cross-platform alternative is $libuv$~\cite{libuv}, which offers asynchronous sockets and asynchronous file system operations (among other features).
    447456However, as a full-featured library it includes much more than I need and could conflict with other features of \CFA unless significant effort is made to merge them together.
    448 A very recent alternative that I am investigating is $io_uring$\cite{io_uring}.
     457A very recent alternative that I am investigating is $io_uring$~\cite{io_uring}.
    449458It claims to address some of the issues with $epoll$ and my early investigating suggests that the claim is accurate.
    450 $io_uring$ uses a much more general approach where system calls are registered to a queue and later executed by the kernel, rather than relying on system calls to return an error instead of blocking and subsequently waiting for changes on file descriptors.
    451 I believe this approach allows for fewer problems, \eg the manpage for $open$\cite{open} states:
     459$io_uring$ uses a much more general approach where system calls are registered to a queue and later executed by the kernel, rather than relying on system calls to support returning an error instead of blocking.
     460I believe this approach allows for fewer problems, \eg the manpage for $open$~\cite{open} states:
    452461\begin{quote}
    453462Note that [the $O_NONBLOCK$ flag] has no effect for regular files and block devices;
     
    455464Since $O_NONBLOCK$ semantics might eventually be implemented, applications should not depend upon blocking behaviour when specifying this flag for regular files and block devices.
    456465\end{quote}
    457 This makes approach based on $epoll$/$select$ less reliable since they may not work for every file descriptors.
    458 For this reason, I plan to use $io_uring$ as the OS abstraction for the \CFA runtime unless further work shows problems I haven't encountered yet.
    459 However, only a small subset of the features are available in Ubuntu as of April 2020\cite{wiki:ubuntu-linux}, which will limit performance comparisons.
     466This makes approaches based on $select$/$epoll$ less reliable since they may not work for every file descriptors.
     467For this reason, I plan to use $io_uring$ as the OS abstraction for the \CFA runtime unless further work encounters a fatal problem.
     468However, only a small subset of the features are available in Ubuntu as of April 2020~\cite{wiki:ubuntu-linux}, which will limit performance comparisons.
    460469I do not believe this will affect the comparison result.
    461470
    462471\paragraph{Event Engine}
    463 Laying on top of the asynchronous interface layer is the event engine.
     472Above the OS asynchronous abstraction is the event engine.
    464473This engine is responsible for multiplexing (batching) the synchronous I/O requests into asynchronous I/O requests and demultiplexing the results to appropriate blocked user threads.
    465474This step can be straightforward for simple cases, but becomes quite complex when there are thousands of user threads performing both reads and writes, possibly on overlapping file descriptors.
     
    478487The interface can be novel but it is preferable to match the existing POSIX interface when possible to be compatible with existing code.
    479488Matching allows C programs written using this interface to be transparently converted to \CFA with minimal effort.
    480 Where new functionality is needed, I will create a novel interface to fill gaps and provide advanced features.
     489Where new functionality is needed, I will add novel interface extensions to fill gaps and provide advanced features.
    481490
    482491
     
    485494\section{Discussion}
    486495I believe that runtime system and scheduling are still open topics.
    487 Many ``state of the art'' production frameworks still use single-threaded event loops because of performance considerations, \eg \cite{nginx-design}, and, to my knowledge, no widely available system language offers modern threading facilities.
     496Many ``state of the art'' production frameworks still use single-threaded event loops because of performance considerations, \eg~\cite{nginx-design}, and, to my knowledge, no widely available system language offers modern threading facilities.
    488497I believe the proposed work offers a novel runtime and scheduling package, where existing work only offers fragments that users must assemble themselves when possible.
    489498
  • doc/theses/thierry_delisle_PhD/comp_II/img/system.fig

    rae2c27a rc76bd34  
    1 #FIG 3.2  Produced by xfig version 3.2.5c
     1#FIG 3.2  Produced by xfig version 3.2.7b
    22Landscape
    33Center
     
    36361 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 3600 15 15 4500 3600 4515 3615
    3737-6
    38 6 3225 4125 4650 4425
    39 6 4350 4200 4650 4350
    40 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 4275 15 15 4425 4275 4440 4290
    41 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 4275 15 15 4500 4275 4515 4290
    42 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4575 4275 15 15 4575 4275 4590 4290
    43 -6
    44 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 4275 225 150 3450 4275 3675 4425
    45 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4275 225 150 4050 4275 4275 4425
    46 -6
    47 6 6675 4125 7500 4425
    48 6 7200 4200 7500 4350
    49 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7275 4275 15 15 7275 4275 7290 4290
    50 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7350 4275 15 15 7350 4275 7365 4290
    51 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7425 4275 15 15 7425 4275 7440 4290
    52 -6
    53 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 4275 225 150 6900 4275 7125 4425
    54 -6
    55386 6675 3525 8025 3975
    56392 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
     
    79621 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3975 2850 150 150 3975 2850 4125 2850
    80631 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 7200 2775 150 150 7200 2775 7350 2775
    81 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 4860
     641 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 4830
    82651 3 0 1 0 0 0 0 0 0.000 1 0.0000 7200 2775 30 30 7200 2775 7230 2805
    83661 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 3600 150 150 3525 3600 3675 3600
    84 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3875 4800 100 100 3875 4800 3975 4800
    85 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4650 4800 150 75 4650 4800 4800 4875
     671 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4625 4838 100 100 4625 4838 4725 4838
    86682 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    8769         2400 4200 2400 3750 1950 3750 1950 4200 2400 4200
     
    153135        1 1 1.00 45.00 90.00
    154136         7875 3750 7875 2325 7200 2325 7200 2550
     1372 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5
     138         6975 4950 6750 4950 6750 4725 6975 4725 6975 4950
    1551392 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    156140         5850 4950 5850 4725 5625 4725 5625 4950 5850 4950
    157 2 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5
    158          6975 4950 6750 4950 6750 4725 6975 4725 6975 4950
    159 4 1 -1 0 0 0 10 0.0000 2 105 720 5550 4425 Processors\001
    160 4 1 -1 0 0 0 10 0.0000 2 120 1005 4200 3225 Blocked Tasks\001
    161 4 1 -1 0 0 0 10 0.0000 2 150 870 4200 3975 Ready Tasks\001
    162 4 1 -1 0 0 0 10 0.0000 2 135 1095 7350 1725 Other Cluster(s)\001
    163 4 1 -1 0 0 0 10 0.0000 2 105 840 4650 1725 User Cluster\001
    164 4 1 -1 0 0 0 10 0.0000 2 150 615 2175 3675 Manager\001
    165 4 1 -1 0 0 0 10 0.0000 2 105 990 2175 3525 Discrete-event\001
    166 4 1 -1 0 0 0 10 0.0000 2 135 795 2175 4350 preemption\001
    167 4 0 -1 0 0 0 10 0.0000 2 150 1290 2325 4875 generator/coroutine\001
    168 4 0 -1 0 0 0 10 0.0000 2 120 270 4050 4875 task\001
    169 4 0 -1 0 0 0 10 0.0000 2 105 450 7050 4875 cluster\001
    170 4 0 -1 0 0 0 10 0.0000 2 105 660 5925 4875 processor\001
    171 4 0 -1 0 0 0 10 0.0000 2 105 555 4875 4875 monitor\001
     1414 1 -1 0 0 0 10 0.0000 2 135 900 5550 4425 Processors\001
     1424 1 -1 0 0 0 10 0.0000 2 165 1170 4200 3975 Ready Threads\001
     1434 1 -1 0 0 0 10 0.0000 2 165 1440 7350 1725 Other Cluster(s)\001
     1444 1 -1 0 0 0 10 0.0000 2 135 1080 4650 1725 User Cluster\001
     1454 1 -1 0 0 0 10 0.0000 2 165 630 2175 3675 Manager\001
     1464 1 -1 0 0 0 10 0.0000 2 135 1260 2175 3525 Discrete-event\001
     1474 1 -1 0 0 0 10 0.0000 2 150 900 2175 4350 preemption\001
     1484 0 -1 0 0 0 10 0.0000 2 135 630 7050 4875 cluster\001
     1494 1 -1 0 0 0 10 0.0000 2 135 1350 4200 3225 Blocked Threads\001
     1504 0 -1 0 0 0 10 0.0000 2 135 540 4800 4875 thread\001
     1514 0 -1 0 0 0 10 0.0000 2 120 810 5925 4875 processor\001
     1524 0 -1 0 0 0 10 0.0000 2 165 1710 2325 4875 generator/coroutine\001
  • doc/user/Makefile

    rae2c27a rc76bd34  
    5555
    5656${DOCUMENT} : ${BASE}.ps
    57         ps2pdf $<
     57        ps2pdf -dPDFSETTINGS=/prepress $<
    5858
    5959${BASE}.ps : ${BASE}.dvi
  • doc/user/user.tex

    rae2c27a rc76bd34  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Mar  6 13:34:52 2020
    14 %% Update Count     : 3924
     13%% Last Modified On : Mon Oct  5 08:57:29 2020
     14%% Update Count     : 3998
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
     33\usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
     34\renewcommand{\thesubfigure}{\alph{subfigure})}
    3535\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3636\usepackage{latexsym}                                   % \Box glyph
    3737\usepackage{mathptmx}                                   % better math font with "times"
    3838\usepackage[usenames]{color}
    39 \input{common}                                          % common CFA document macros
    40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    41 \usepackage{breakurl}
    42 
    43 \usepackage[pagewise]{lineno}
    44 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    45 \usepackage[firstpage]{draftwatermark}
    46 \SetWatermarkLightness{0.9}
    47 
    48 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    49 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    50 % AFTER HYPERREF.
    51 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    52 
    53 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    54 \setlength{\headsep}{0.25in}
    55 
    56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    57 
    58 \CFAStyle                                                                                               % use default CFA format-style
    59 \lstnewenvironment{C++}[1][]                            % use C++ style
    60 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    61 {}
    62 
     39\newcommand{\CFALatin}{}
    6340% inline code ©...© (copyright symbol) emacs: C-q M-)
    6441% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6845% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    6946% math escape $...$ (dollar symbol)
     47\input{common}                                          % common CFA document macros
     48\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     49\usepackage{breakurl}
     50
     51\renewcommand\footnoterule{\kern -3pt\rule{0.3\linewidth}{0.15pt}\kern 2pt}
     52
     53\usepackage[pagewise]{lineno}
     54\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     55\usepackage[firstpage]{draftwatermark}
     56\SetWatermarkLightness{0.9}
     57
     58% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     59% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     60% AFTER HYPERREF.
     61\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     62
     63\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     64\setlength{\headsep}{0.25in}
     65
     66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     67
     68\CFAStyle                                                                                               % use default CFA format-style
     69\lstnewenvironment{C++}[1][]                            % use C++ style
     70{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     71{}
     72
     73\newsavebox{\myboxA}
     74\newsavebox{\myboxB}
    7075
    7176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    7984\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    8085\newcommand{\KWC}{K-W C\xspace}
    81 
    82 \newsavebox{\LstBox}
    8386
    8487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    253256
    254257The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name):
    255 \begin{lstlisting}
     258\begin{cfa}
    256259®forall( otype T )® T identity( T val ) { return val; }
    257260int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    258 \end{lstlisting}
     261\end{cfa}
    259262% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
    260263\CFA{}\hspace{1pt}'s polymorphism was originally formalized by \Index*{Glen Ditchfield}\index{Ditchfield, Glen}~\cite{Ditchfield92}, and first implemented by \Index*{Richard Bilson}\index{Bilson, Richard}~\cite{Bilson03}.
     
    275278\begin{comment}
    276279A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
    277 \begin{lstlisting}
     280\begin{cfa}
    278281void * bsearch( const void * key, const void * base, size_t dim, size_t size,
    279282                                int (* compar)( const void *, const void * ));
     
    284287double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    285288double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    286 \end{lstlisting}
     289\end{cfa}
    287290which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
    288 \begin{lstlisting}
     291\begin{cfa}
    289292forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
    290293        int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
     
    297300double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    298301int posn = bsearch( 5.0, vals, 10 );
    299 \end{lstlisting}
     302\end{cfa}
    300303The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result.
    301304Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     
    305308\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations.
    306309For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©:
    307 \begin{lstlisting}
     310\begin{cfa}
    308311forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    309312int * ip = malloc(); §\C{// select type and size from left-hand side}§
    310313double * dp = malloc();
    311314struct S {...} * sp = malloc();
    312 \end{lstlisting}
     315\end{cfa}
    313316where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    314317\end{comment}
     
    943946the same level as a ©case© clause; the target label may be case ©default©, but only associated
    944947with the current ©switch©/©choose© statement.
    945 
    946 
    947 \subsection{Loop Control}
    948 
    949 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    950 \begin{itemize}
    951 \item
    952 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
    953 \item
    954 An empty conditional implies comparison value of ©1© (true).
    955 \item
    956 A comparison N is implicit up-to exclusive range [0,N©®)®©.
    957 \item
    958 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
    959 \item
    960 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
    961 \item
    962 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
    963 \item
    964 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
    965 \item
    966 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
    967 \item
    968 ©0© is the implicit start value;
    969 \item
    970 ©1© is the implicit increment value.
    971 \item
    972 The up-to range uses operator ©+=© for increment;
    973 \item
    974 The down-to range uses operator ©-=© for decrement.
    975 \item
    976 ©@© means put nothing in this field.
    977 \item
    978 ©:© means start another index.
    979 \end{itemize}
    980948
    981949\begin{figure}
     
    10861054
    10871055
     1056\subsection{Loop Control}
     1057
     1058The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     1059\begin{itemize}
     1060\item
     1061The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
     1062\item
     1063An empty conditional implies comparison value of ©1© (true).
     1064\item
     1065A comparison N is implicit up-to exclusive range [0,N©®)®©.
     1066\item
     1067A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
     1068\item
     1069The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
     1070\item
     1071The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
     1072\item
     1073The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
     1074\item
     1075The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
     1076\item
     1077©0© is the implicit start value;
     1078\item
     1079©1© is the implicit increment value.
     1080\item
     1081The up-to range uses operator ©+=© for increment;
     1082\item
     1083The down-to range uses operator ©-=© for decrement.
     1084\item
     1085©@© means put nothing in this field.
     1086\item
     1087©:© means start another index.
     1088\end{itemize}
     1089
     1090
    10881091%\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    10891092\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     
    10951098for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
    10961099\VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels.
    1097 The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     1100The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
    10981101
    10991102\begin{figure}
    1100 \begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1101 \multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
    1102 \begin{cfa}
    1103 ®LC:® {
    1104         ... §declarations§ ...
    1105         ®LS:® switch ( ... ) {
    1106           case 3:
    1107                 ®LIF:® if ( ... ) {
    1108                         ®LF:® for ( ... ) {
    1109                                 ®LW:® while ( ... ) {
    1110                                         ... break ®LC®; ...
    1111                                         ... break ®LS®; ...
    1112                                         ... break ®LIF®; ...
    1113                                         ... continue ®LF;® ...
    1114                                         ... break ®LF®; ...
    1115                                         ... continue ®LW®; ...
    1116                                         ... break ®LW®; ...
    1117                                 } // while
    1118                         } // for
    1119                 } else {
    1120                         ... break ®LIF®; ...
    1121                 } // if
    1122         } // switch
     1103\centering
     1104\begin{lrbox}{\myboxA}
     1105\begin{cfa}[tabsize=3]
     1106®Compound:® {
     1107        ®Try:® try {
     1108                ®For:® for ( ... ) {
     1109                        ®While:® while ( ... ) {
     1110                                ®Do:® do {
     1111                                        ®If:® if ( ... ) {
     1112                                                ®Switch:® switch ( ... ) {
     1113                                                        case 3:
     1114                                                                ®break Compound®;
     1115                                                                ®break Try®;
     1116                                                                ®break For®;      /* or */  ®continue For®;
     1117                                                                ®break While®;  /* or */  ®continue While®;
     1118                                                                ®break Do®;      /* or */  ®continue Do®;
     1119                                                                ®break If®;
     1120                                                                ®break Switch®;
     1121                                                        } // switch
     1122                                                } else {
     1123                                                        ... ®break If®; ...     // terminate if
     1124                                                } // if
     1125                                } while ( ... ); // do
     1126                        } // while
     1127                } // for
     1128        } ®finally® { // always executed
     1129        } // try
    11231130} // compound
    11241131\end{cfa}
    1125 &
    1126 \begin{cfa}
     1132\end{lrbox}
     1133
     1134\begin{lrbox}{\myboxB}
     1135\begin{cfa}[tabsize=3]
    11271136{
    1128         ... §declarations§ ...
    1129         switch ( ... ) {
    1130           case 3:
    1131                 if ( ... ) {
    1132                         for ( ... ) {
    1133                                 while ( ... ) {
    1134                                         ... goto ®LC®; ...
    1135                                         ... goto ®LS®; ...
    1136                                         ... goto ®LIF®; ...
    1137                                         ... goto ®LFC®; ...
    1138                                         ... goto ®LFB®; ...
    1139                                         ... goto ®LWC®; ...
    1140                                         ... goto ®LWB®; ...
    1141                                   ®LWC®: ; } ®LWB:® ;
    1142                           ®LFC:® ; } ®LFB:® ;
    1143                 } else {
    1144                         ... goto ®LIF®; ...
    1145                 } ®L3:® ;
    1146         } ®LS:® ;
    1147 } ®LC:® ;
    1148 \end{cfa}
    1149 &
    1150 \begin{cfa}
    1151 
    1152 
    1153 
    1154 
    1155 
    1156 
    1157 
    1158 // terminate compound
    1159 // terminate switch
    1160 // terminate if
    1161 // continue loop
    1162 // terminate loop
    1163 // continue loop
    1164 // terminate loop
    1165 
    1166 
    1167 
    1168 // terminate if
    1169 
    1170 
    1171 
    1172 \end{cfa}
    1173 \end{tabular}
     1137
     1138                ®ForC:® for ( ... ) {
     1139                        ®WhileC:® while ( ... ) {
     1140                                ®DoC:® do {
     1141                                        if ( ... ) {
     1142                                                switch ( ... ) {
     1143                                                        case 3:
     1144                                                                ®goto Compound®;
     1145                                                                ®goto Try®;
     1146                                                                ®goto ForB®;      /* or */  ®goto ForC®;
     1147                                                                ®goto WhileB®;  /* or */  ®goto WhileC®;
     1148                                                                ®goto DoB®;      /* or */  ®goto DoC®;
     1149                                                                ®goto If®;
     1150                                                                ®goto Switch®;
     1151                                                        } ®Switch:® ;
     1152                                                } else {
     1153                                                        ... ®goto If®; ...      // terminate if
     1154                                                } ®If:®;
     1155                                } while ( ... ); ®DoB:® ;
     1156                        } ®WhileB:® ;
     1157                } ®ForB:® ;
     1158
     1159
     1160} ®Compound:® ;
     1161\end{cfa}
     1162\end{lrbox}
     1163
     1164\subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA}
     1165\hspace{2pt}
     1166\vrule
     1167\hspace{2pt}
     1168\subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB}
    11741169\caption{Multi-level Exit}
    11751170\label{f:MultiLevelExit}
     
    14261421try {
    14271422        f(...);
    1428 } catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
     1423} catch( E e ; §boolean-predicate§ ) {          §\C{// termination handler}§
    14291424        // recover and continue
    1430 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
     1425} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
    14311426        // repair and return
    14321427} finally {
     
    34913486For implicit formatted input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable.
    34923487\begin{cquote}
    3493 \begin{lrbox}{\LstBox}
     3488\begin{lrbox}{\myboxA}
    34943489\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    34953490int x;   double y   char z;
     
    34973492\end{lrbox}
    34983493\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3499 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
     3494\multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\
    35003495\multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    35013496\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     
    66726667For example, an initial alignment and fill capability are preserved during a resize copy so the copy has the same alignment and extended storage is filled.
    66736668Without sticky properties it is dangerous to use ©realloc©, resulting in an idiom of manually performing the reallocation to maintain correctness.
     6669\begin{cfa}
     6670
     6671\end{cfa}
    66746672
    66756673\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
     
    67216719
    67226720        // §\CFA§ safe general allocation, fill, resize, alignment, array
    6723         T * alloc( void );§\indexc{alloc}§
    6724         T * alloc( size_t dim );
    6725         T * alloc( T ptr[], size_t dim );
    6726         T * alloc_set( char fill );§\indexc{alloc_set}§
    6727         T * alloc_set( T fill );
    6728         T * alloc_set( size_t dim, char fill );
    6729         T * alloc_set( size_t dim, T fill );
    6730         T * alloc_set( size_t dim, const T fill[] );
    6731         T * alloc_set( T ptr[], size_t dim, char fill );
    6732 
    6733         T * alloc_align( size_t align );
    6734         T * alloc_align( size_t align, size_t dim );
    6735         T * alloc_align( T ptr[], size_t align ); // aligned realloc array
    6736         T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
    6737         T * alloc_align_set( size_t align, char fill );
    6738         T * alloc_align_set( size_t align, T fill );
    6739         T * alloc_align_set( size_t align, size_t dim, char fill );
    6740         T * alloc_align_set( size_t align, size_t dim, T fill );
    6741         T * alloc_align_set( size_t align, size_t dim, const T fill[] );
    6742         T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill );
     6721        T * alloc( void );§\indexc{alloc}§                                      §\C[3.5in]{// variable, T size}§
     6722        T * alloc( size_t dim );                                                        §\C{// array[dim], T size elements}§
     6723        T * alloc( T ptr[], size_t dim );                                       §\C{// realloc array[dim], T size elements}§
     6724
     6725        T * alloc_set( char fill );§\indexc{alloc_set}§         §\C{// variable, T size, fill bytes with value}§
     6726        T * alloc_set( T fill );                                                        §\C{// variable, T size, fill with value}§
     6727        T * alloc_set( size_t dim, char fill );                         §\C{// array[dim], T size elements, fill bytes with value}§
     6728        T * alloc_set( size_t dim, T fill );                            §\C{// array[dim], T size elements, fill elements with value}§
     6729        T * alloc_set( size_t dim, const T fill[] );            §\C{// array[dim], T size elements, fill elements with array}§
     6730        T * alloc_set( T ptr[], size_t dim, char fill );        §\C{// realloc array[dim], T size elements, fill bytes with value}§
     6731
     6732        T * alloc_align( size_t align );                                        §\C{// aligned variable, T size}§
     6733        T * alloc_align( size_t align, size_t dim );            §\C{// aligned array[dim], T size elements}§
     6734        T * alloc_align( T ptr[], size_t align );                       §\C{// realloc new aligned array}§
     6735        T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§
     6736
     6737        T * alloc_align_set( size_t align, char fill );         §\C{// aligned variable, T size, fill bytes with value}§
     6738        T * alloc_align_set( size_t align, T fill );            §\C{// aligned variable, T size, fill with value}§
     6739        T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§
     6740        T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§
     6741        T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§
     6742        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§
    67436743
    67446744        // §\CFA§ safe initialization/copy, i.e., implicit size specification
  • libcfa/configure.ac

    rae2c27a rc76bd34  
    166166AH_TEMPLATE([CFA_HAVE_IORING_OP_PROVIDE_BUFFERS],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_PROVIDE_BUFFERS.])
    167167AH_TEMPLATE([CFA_HAVE_IORING_OP_REMOVE_BUFFER],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_REMOVE_BUFFER.])
     168AH_TEMPLATE([CFA_HAVE_IORING_OP_TEE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_TEE.])
    168169AH_TEMPLATE([CFA_HAVE_IOSQE_FIXED_FILE],[Defined if io_uring support is present when compiling libcfathread and supports the flag FIXED_FILE.])
    169170AH_TEMPLATE([CFA_HAVE_IOSQE_IO_DRAIN],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_DRAIN.])
     
    173174AH_TEMPLATE([CFA_HAVE_SPLICE_F_FD_IN_FIXED],[Defined if io_uring support is present when compiling libcfathread and supports the flag SPLICE_F_FD_IN_FIXED.])
    174175AH_TEMPLATE([CFA_HAVE_IORING_SETUP_ATTACH_WQ],[Defined if io_uring support is present when compiling libcfathread and supports the flag IORING_SETUP_ATTACH_WQ.])
    175 AH_TEMPLATE([HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.])
    176 AH_TEMPLATE([HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.])
     176AH_TEMPLATE([CFA_HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.])
     177AH_TEMPLATE([CFA_HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.])
     178AH_TEMPLATE([CFA_HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.])
     179AH_TEMPLATE([CFA_HAVE_STATX],[Defined if statx support is present when compiling libcfathread.])
     180AH_TEMPLATE([CFA_HAVE_OPENAT2],[Defined if openat2 support is present when compiling libcfathread.])
    177181AH_TEMPLATE([__CFA_NO_STATISTICS__],[Defined if libcfathread was compiled without support for statistics.])
    178182
    179 define(ioring_ops, [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER])
     183define(ioring_ops, [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER,IORING_OP_TEE])
    180184define(ioring_flags, [IOSQE_FIXED_FILE,IOSQE_IO_DRAIN,IOSQE_ASYNC,IOSQE_IO_LINK,IOSQE_IO_HARDLINK,SPLICE_F_FD_IN_FIXED,IORING_SETUP_ATTACH_WQ])
    181185
     
    222226        ])
    223227])
    224 AC_CHECK_FUNCS([preadv2 pwritev2])
     228AC_CHECK_FUNC([preadv2], [AC_DEFINE([CFA_HAVE_PREADV2])])
     229AC_CHECK_FUNC([pwritev2], [AC_DEFINE([CFA_HAVE_PWRITEV2])])
    225230
    226231AC_CONFIG_FILES([
     
    229234        prelude/Makefile
    230235        ])
     236AC_CONFIG_FILES([src/concurrency/io/call.cfa], [python3 ${srcdir}/src/concurrency/io/call.cfa.in > src/concurrency/io/call.cfa])
    231237
    232238AC_CONFIG_HEADERS(prelude/defines.hfa)
  • libcfa/prelude/defines.hfa.in

    rae2c27a rc76bd34  
    117117
    118118/* Defined if io_uring support is present when compiling libcfathread and
     119   supports the operation IORING_OP_TEE. */
     120#undef CFA_HAVE_IORING_OP_TEE
     121
     122/* Defined if io_uring support is present when compiling libcfathread and
    119123   supports the operation IORING_OP_TIMEOUT. */
    120124#undef CFA_HAVE_IORING_OP_TIMEOUT
     
    163167#undef CFA_HAVE_LINUX_IO_URING_H
    164168
     169/* Defined if openat2 support is present when compiling libcfathread. */
     170#undef CFA_HAVE_OPENAT2
     171
     172/* Defined if preadv2 support is present when compiling libcfathread. */
     173#undef CFA_HAVE_PREADV2
     174
     175/* Defined if pwritev2 support is present when compiling libcfathread. */
     176#undef CFA_HAVE_PWRITEV2
     177
    165178/* Defined if io_uring support is present when compiling libcfathread and
    166179   supports the flag SPLICE_F_FD_IN_FIXED. */
    167180#undef CFA_HAVE_SPLICE_F_FD_IN_FIXED
    168181
     182/* Defined if statx support is present when compiling libcfathread. */
     183#undef CFA_HAVE_STATX
     184
    169185/* Location of include files. */
    170186#undef CFA_INCDIR
     
    188204#undef HAVE_MEMORY_H
    189205
    190 /* Define to 1 if you have the `preadv2' function. */
    191 #undef HAVE_PREADV2
    192 
    193 /* Define to 1 if you have the `pwritev2' function. */
    194 #undef HAVE_PWRITEV2
    195 
    196206/* Define to 1 if you have the <stdint.h> header file. */
    197207#undef HAVE_STDINT_H
  • libcfa/src/Makefile.am

    rae2c27a rc76bd34  
    6262        iterator.hfa \
    6363        limits.hfa \
     64        memory.hfa \
    6465        parseargs.hfa \
    6566        rational.hfa \
     
    8788inst_thread_headers_nosrc = \
    8889        bits/random.hfa \
     90        concurrency/clib/cfathread.h \
    8991        concurrency/invoke.h \
    9092        concurrency/kernel/fwd.hfa
     
    102104        concurrency/alarm.cfa \
    103105        concurrency/alarm.hfa \
     106        concurrency/clib/cfathread.cfa \
    104107        concurrency/CtxSwitch-@ARCHITECTURE@.S \
    105108        concurrency/invoke.c \
     
    107110        concurrency/io/setup.cfa \
    108111        concurrency/io/types.hfa \
    109         concurrency/iocall.cfa \
     112        concurrency/io/call.cfa \
    110113        concurrency/iofwd.hfa \
    111114        concurrency/kernel_private.hfa \
  • libcfa/src/bits/locks.hfa

    rae2c27a rc76bd34  
    164164
    165165        struct $thread;
    166         extern void park( __cfaabi_dbg_ctx_param );
    167         extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
     166        extern void park( void );
     167        extern void unpark( struct $thread * this );
    168168        static inline struct $thread * active_thread ();
    169169
     
    191191                                        /* paranoid */ verify( expected == 0p );
    192192                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    193                                                 park( __cfaabi_dbg_ctx );
     193                                                park();
    194194                                                return true;
    195195                                        }
     
    210210                                else {
    211211                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    212                                                 unpark( expected __cfaabi_dbg_ctx2 );
     212                                                unpark( expected );
    213213                                                return true;
    214214                                        }
     
    244244                                /* paranoid */ verify( expected == 0p );
    245245                                if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    246                                         park( __cfaabi_dbg_ctx );
     246                                        park();
    247247                                        /* paranoid */ verify( this.ptr == 1p );
    248248                                        return true;
     
    256256                        struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
    257257                        if( got == 0p ) return false;
    258                         unpark( got __cfaabi_dbg_ctx2 );
     258                        unpark( got );
    259259                        return true;
    260260                }
     
    357357                                struct oneshot * expected = this.ptr;
    358358                                // was this abandoned?
    359                                 if( expected == 3p ) { free( &this ); return false; }
     359                                #if defined(__GNUC__) && __GNUC__ >= 7
     360                                        #pragma GCC diagnostic push
     361                                        #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
     362                                #endif
     363                                        if( expected == 3p ) { free( &this ); return false; }
     364                                #if defined(__GNUC__) && __GNUC__ >= 7
     365                                        #pragma GCC diagnostic pop
     366                                #endif
    360367
    361368                                /* paranoid */ verify( expected != 1p ); // Future is already fulfilled, should not happen
  • libcfa/src/concurrency/CtxSwitch-i386.S

    rae2c27a rc76bd34  
    1010// Created On       : Tue Dec 6 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug 16 08:46:22 2020
    13 // Update Count     : 4
     12// Last Modified On : Sun Sep  6 18:23:37 2020
     13// Update Count     : 5
    1414//
    1515
     
    3535
    3636        // Copy the "from" context argument from the stack to register eax
    37         // Return address is at 0(%esp), with parameters following
     37        // Return address is at 0(%esp), with parameters following.
    3838
    3939        movl 4(%esp),%eax
     
    5050        movl %ebp,FP_OFFSET(%eax)
    5151
    52         // Copy the "to" context argument from the stack to register eax
    53         // Having pushed three words (= 12 bytes) on the stack, the
    54         // argument is now at 8 + 12 = 20(%esp)
     52        // Copy the "to" context argument from the stack to register eax. Having
     53        // pushed 3 words (= 12 bytes) on the stack, the argument is now at
     54        // 8 + 12 = 20(%esp).
    5555
    5656        movl 20(%esp),%eax
  • libcfa/src/concurrency/alarm.cfa

    rae2c27a rc76bd34  
    130130
    131131        register_self( &node );
    132         park( __cfaabi_dbg_ctx );
     132        park();
    133133
    134134        /* paranoid */ verify( !node.set );
  • libcfa/src/concurrency/coroutine.cfa

    rae2c27a rc76bd34  
    4747
    4848//-----------------------------------------------------------------------------
     49FORALL_DATA_INSTANCE(CoroutineCancelled,
     50                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
     51
     52struct __cfaehm_node {
     53        struct _Unwind_Exception unwind_exception;
     54        struct __cfaehm_node * next;
     55        int handler_index;
     56};
     57
     58forall(dtype T)
     59void mark_exception(CoroutineCancelled(T) *) {}
     60
     61forall(dtype T | sized(T))
     62void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
     63        dst->the_coroutine = src->the_coroutine;
     64        dst->the_exception = src->the_exception;
     65}
     66
     67forall(dtype T)
     68const char * msg(CoroutineCancelled(T) *) {
     69        return "CoroutineCancelled(...)";
     70}
     71
     72// This code should not be inlined. It is the error path on resume.
     73forall(dtype T | is_coroutine(T))
     74void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) {
     75        verify( desc->cancellation );
     76        desc->state = Cancelled;
     77        exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
     78
     79        CoroutineCancelled(T) except;
     80        except.the_coroutine = &cor;
     81        except.the_exception = except;
     82        throwResume except;
     83
     84        except->virtual_table->free( except );
     85        free( desc->cancellation );
     86        desc->cancellation = 0p;
     87}
     88
     89//-----------------------------------------------------------------------------
    4990// Global state variables
    5091
     
    180221        this->storage->limit = storage;
    181222        this->storage->base  = (void*)((intptr_t)storage + size);
     223        this->storage->exception_context.top_resume = 0p;
     224        this->storage->exception_context.current_exception = 0p;
    182225        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
    183226        *istorage |= userStack ? 0x1 : 0x0;
  • libcfa/src/concurrency/coroutine.hfa

    rae2c27a rc76bd34  
    1818#include <assert.h>
    1919#include "invoke.h"
     20#include "../exception.hfa"
     21
     22//-----------------------------------------------------------------------------
     23// Exception thrown from resume when a coroutine stack is cancelled.
     24// Should not have to be be sized (see trac #196).
     25FORALL_DATA_EXCEPTION(CoroutineCancelled,
     26                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
     27        coroutine_t * the_coroutine;
     28        exception_t * the_exception;
     29);
     30
     31forall(dtype T)
     32void mark_exception(CoroutineCancelled(T) *);
     33
     34forall(dtype T | sized(T))
     35void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
     36
     37forall(dtype T)
     38const char * msg(CoroutineCancelled(T) *);
    2039
    2140//-----------------------------------------------------------------------------
     
    2342// Anything that implements this trait can be resumed.
    2443// Anything that is resumed is a coroutine.
    25 trait is_coroutine(dtype T) {
    26       void main(T & this);
    27       $coroutine * get_coroutine(T & this);
     44trait is_coroutine(dtype T | sized(T)
     45                | is_resumption_exception(CoroutineCancelled(T))
     46                | VTABLE_ASSERTION(CoroutineCancelled, (T))) {
     47        void main(T & this);
     48        $coroutine * get_coroutine(T & this);
    2849};
    2950
     
    112133        }
    113134}
     135
     136forall(dtype T | is_coroutine(T))
     137void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc );
    114138
    115139// Resume implementation inlined for performance
     
    145169        // always done for performance testing
    146170        $ctx_switch( src, dst );
     171        if ( unlikely(dst->cancellation) ) {
     172                __cfaehm_cancelled_coroutine( cor, dst );
     173        }
    147174
    148175        return cor;
  • libcfa/src/concurrency/exception.cfa

    rae2c27a rc76bd34  
    5757
    5858STOP_AT_END_FUNCTION(coroutine_cancelstop,
    59         // TODO: Instead pass information to the last resumer.
     59        struct $coroutine * src = ($coroutine *)stop_param;
     60        struct $coroutine * dst = src->last;
     61
     62        $ctx_switch( src, dst );
    6063        abort();
    6164)
  • libcfa/src/concurrency/exception.hfa

    rae2c27a rc76bd34  
    1818#include "bits/defs.hfa"
    1919#include "invoke.h"
    20 struct _Unwind_Exception;
    21 
    22 // It must also be usable as a C header file.
    2320
    2421#ifdef __cforall
    2522extern "C" {
     23
     24#define HIDE_EXPORTS
    2625#endif
     26#include "unwind.h"
    2727
    2828struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD;
     
    3232
    3333#ifdef __cforall
     34#undef HIDE_EXPORTS
    3435}
    3536#endif
  • libcfa/src/concurrency/invoke.h

    rae2c27a rc76bd34  
    6868        };
    6969
    70         enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active };
     70        enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled };
    7171
    7272        struct $coroutine {
     
    9393
    9494        };
     95        // Wrapper for gdb
     96        struct cfathread_coroutine_t { struct $coroutine debug; };
    9597
    9698        static inline struct __stack_t * __get_stack( struct $coroutine * cor ) {
     
    129131                struct __condition_node_t * dtor_node;
    130132        };
     133        // Wrapper for gdb
     134        struct cfathread_monitor_t { struct $monitor debug; };
    131135
    132136        struct __monitor_group_t {
     
    186190                } node;
    187191
    188                 #ifdef __CFA_DEBUG__
    189                         // previous function to park/unpark the thread
    190                         const char * park_caller;
    191                         int park_result;
    192                         enum __Coroutine_State park_state;
    193                         bool park_stale;
    194                         const char * unpark_caller;
    195                         int unpark_result;
    196                         enum __Coroutine_State unpark_state;
    197                         bool unpark_stale;
     192                #if defined( __CFA_WITH_VERIFY__ )
     193                        unsigned long long canary;
    198194                #endif
    199195        };
     196        // Wrapper for gdb
     197        struct cfathread_thread_t { struct $thread debug; };
    200198
    201199        #ifdef __CFA_DEBUG__
  • libcfa/src/concurrency/io.cfa

    rae2c27a rc76bd34  
    6969                if( block ) {
    7070                        enable_interrupts( __cfaabi_dbg_ctx );
    71                         park( __cfaabi_dbg_ctx );
     71                        park();
    7272                        disable_interrupts();
    7373                }
     
    9797
    9898                if(nextt) {
    99                         unpark( nextt __cfaabi_dbg_ctx2 );
     99                        unpark( nextt );
    100100                        enable_interrupts( __cfaabi_dbg_ctx );
    101101                        return true;
     
    159159
    160160        static inline void process(struct io_uring_cqe & cqe ) {
    161                 struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data;
    162                 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", data, cqe.res, data->thrd );
    163 
    164                 data->result = cqe.res;
    165                 post( data->sem );
     161                struct io_future_t * future = (struct io_future_t *)(uintptr_t)cqe.user_data;
     162                __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", future, cqe.res, data->thrd );
     163
     164                fulfil( *future, cqe.res );
    166165        }
    167166
  • libcfa/src/concurrency/io/setup.cfa

    rae2c27a rc76bd34  
    147147        static void * iopoll_loop( __attribute__((unused)) void * args ) {
    148148                __processor_id_t id;
     149                id.full_proc = false;
    149150                id.id = doregister(&id);
    150151                __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" );
     
    246247                                        thrd.link.next = 0p;
    247248                                        thrd.link.prev = 0p;
    248                                         __cfaabi_dbg_debug_do( thrd.unpark_stale = true );
    249249
    250250                                        // Fixup the thread state
     
    266266
    267267                                // unpark the fast io_poller
    268                                 unpark( &thrd __cfaabi_dbg_ctx2 );
     268                                unpark( &thrd );
    269269                        }
    270270                        else {
     
    275275                        }
    276276                } else {
    277                         unpark( &thrd __cfaabi_dbg_ctx2 );
     277                        unpark( &thrd );
    278278                }
    279279
  • libcfa/src/concurrency/io/types.hfa

    rae2c27a rc76bd34  
    1616#pragma once
    1717
     18extern "C" {
     19        #include <linux/types.h>
     20}
     21
     22#include "bits/locks.hfa"
     23
    1824#if defined(CFA_HAVE_LINUX_IO_URING_H)
    19         extern "C" {
    20                 #include <linux/types.h>
    21         }
    22 
    23       #include "bits/locks.hfa"
    24 
    2525        #define LEADER_LOCK
    2626        struct __leaderlock_t {
     
    101101        };
    102102
    103 
    104         //-----------------------------------------------------------------------
    105         // IO user data
    106         struct __io_user_data_t {
    107                 __s32 result;
    108                 oneshot sem;
    109         };
    110 
    111103        //-----------------------------------------------------------------------
    112104        // Misc
     
    143135        void __ioctx_prepare_block($io_ctx_thread & ctx, struct epoll_event & ev);
    144136#endif
     137
     138//-----------------------------------------------------------------------
     139// IO user data
     140struct io_future_t {
     141        future_t self;
     142        __s32 result;
     143};
     144
     145static inline {
     146        bool fulfil( io_future_t & this, __s32 result ) {
     147                this.result = result;
     148                return fulfil(this.self);
     149        }
     150
     151        // Wait for the future to be fulfilled
     152        bool wait( io_future_t & this ) {
     153                return wait(this.self);
     154        }
     155}
  • libcfa/src/concurrency/iofwd.hfa

    rae2c27a rc76bd34  
    4040
    4141struct cluster;
     42struct io_future_t;
    4243struct io_context;
    4344struct io_cancellation;
     
    4849struct statx;
    4950
    50 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    51 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    52 extern int cfa_fsync(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    53 extern int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    54 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    55 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    56 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    57 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    58 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    59 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    60 extern int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    61 extern int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    62 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    63 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    64 extern int cfa_close(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    65 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    66 extern ssize_t cfa_read(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    67 extern ssize_t cfa_write(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    68 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
    69 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
     51//----------
     52// synchronous calls
     53#if defined(CFA_HAVE_PREADV2)
     54        extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     55#endif
     56#if defined(CFA_HAVE_PWRITEV2)
     57        extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     58#endif
     59extern int cfa_fsync(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     60extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     61extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     62extern  ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     63extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     64extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     65extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     66extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     67extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     68extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     69extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     70extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     71extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     72#if defined(CFA_HAVE_OPENAT2)
     73        extern int cfa_openat2(int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     74#endif
     75extern int cfa_close(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     76#if defined(CFA_HAVE_STATX)
     77        extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     78#endif
     79extern ssize_t cfa_read(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     80extern ssize_t cfa_write(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     81extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     82extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
     83
     84//----------
     85// asynchronous calls
     86#if defined(CFA_HAVE_PREADV2)
     87        extern void async_preadv2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     88#endif
     89#if defined(CFA_HAVE_PWRITEV2)
     90        extern void async_pwritev2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     91#endif
     92extern void async_fsync(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context);
     93extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event *event, int submit_flags, io_cancellation * cancellation, io_context * context);
     94extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     95extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     96extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     97extern void async_send(io_future_t & future, int sockfd, const void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     98extern void async_recv(io_future_t & future, int sockfd, void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     99extern void async_accept4(io_future_t & future, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     100extern void async_connect(io_future_t & future, int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, io_cancellation * cancellation, io_context * context);
     101extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, int submit_flags, io_cancellation * cancellation, io_context * context);
     102extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, int submit_flags, io_cancellation * cancellation, io_context * context);
     103extern void async_madvise(io_future_t & future, void *addr, size_t length, int advice, int submit_flags, io_cancellation * cancellation, io_context * context);
     104extern void async_openat(io_future_t & future, int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, io_cancellation * cancellation, io_context * context);
     105#if defined(CFA_HAVE_OPENAT2)
     106        extern void async_openat2(io_future_t & future, int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, io_cancellation * cancellation, io_context * context);
     107#endif
     108extern void async_close(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context);
     109#if defined(CFA_HAVE_STATX)
     110        extern void async_statx(io_future_t & future, int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, io_cancellation * cancellation, io_context * context);
     111#endif
     112void async_read(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context);
     113extern void async_write(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context);
     114extern void async_splice(io_future_t & future, int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     115extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context);
     116
    70117
    71118//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/kernel.cfa

    rae2c27a rc76bd34  
    237237        $coroutine * proc_cor = get_coroutine(this->runner);
    238238
    239         // Update global state
    240         kernelTLS.this_thread = thrd_dst;
    241 
    242239        // set state of processor coroutine to inactive
    243240        verify(proc_cor->state == Active);
     
    249246                thrd_dst->state = Active;
    250247
    251                 __cfaabi_dbg_debug_do(
    252                         thrd_dst->park_stale   = true;
    253                         thrd_dst->unpark_stale = true;
    254                 )
     248                // Update global state
     249                kernelTLS.this_thread = thrd_dst;
    255250
    256251                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    257252                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
     253                /* paranoid */ verify( thrd_dst->context.SP );
    258254                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    259255                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
     256                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary );
     257
     258
    260259
    261260                // set context switch to the thread that the processor is executing
    262                 verify( thrd_dst->context.SP );
    263261                __cfactx_switch( &proc_cor->context, &thrd_dst->context );
    264262                // when __cfactx_switch returns we are back in the processor coroutine
    265263
     264                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary );
    266265                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst );
    267266                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
     267                /* paranoid */ verify( thrd_dst->context.SP );
    268268                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    269269                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    270270
     271                // Reset global state
     272                kernelTLS.this_thread = 0p;
    271273
    272274                // We just finished running a thread, there are a few things that could have happened.
     
    286288                        // The thread has halted, it should never be scheduled/run again
    287289                        // We may need to wake someone up here since
    288                         unpark( this->destroyer __cfaabi_dbg_ctx2 );
     290                        unpark( this->destroyer );
    289291                        this->destroyer = 0p;
    290292                        break RUNNING;
     
    296298                // set state of processor coroutine to active and the thread to inactive
    297299                int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
    298                 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; )
    299300                switch(old_ticket) {
    300301                        case 1:
     
    313314        // Just before returning to the processor, set the processor coroutine to active
    314315        proc_cor->state = Active;
    315         kernelTLS.this_thread = 0p;
    316316
    317317        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    334334                        __x87_store;
    335335                #endif
    336                 verify( proc_cor->context.SP );
     336                /* paranoid */ verify( proc_cor->context.SP );
     337                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
    337338                __cfactx_switch( &thrd_src->context, &proc_cor->context );
     339                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
    338340                #if defined( __i386 ) || defined( __x86_64 )
    339341                        __x87_load;
     
    367369        /* paranoid */ #endif
    368370        /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next );
     371        /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd->canary );
     372
    369373
    370374        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
     
    403407
    404408// KERNEL ONLY unpark with out disabling interrupts
    405 void __unpark(  struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) {
    406         // record activity
    407         __cfaabi_dbg_record_thrd( *thrd, false, caller );
    408 
     409void __unpark(  struct __processor_id_t * id, $thread * thrd ) {
    409410        int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
    410         __cfaabi_dbg_debug_do( thrd->unpark_result = old_ticket; thrd->unpark_state = thrd->state; )
    411411        switch(old_ticket) {
    412412                case 1:
     
    426426}
    427427
    428 void unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) {
     428void unpark( $thread * thrd ) {
    429429        if( !thrd ) return;
    430430
    431431        disable_interrupts();
    432         __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 );
     432        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd );
    433433        enable_interrupts( __cfaabi_dbg_ctx );
    434434}
    435435
    436 void park( __cfaabi_dbg_ctx_param ) {
     436void park( void ) {
    437437        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    438438        disable_interrupts();
    439439        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    440440        /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION );
    441 
    442         // record activity
    443         __cfaabi_dbg_record_thrd( *kernelTLS.this_thread, true, caller );
    444441
    445442        returnToKernel();
     
    521518        disable_interrupts();
    522519                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    523                 bool ret = post( this->idle );
     520                post( this->idle );
    524521        enable_interrupts( __cfaabi_dbg_ctx );
    525522}
     
    649646                // atomically release spin lock and block
    650647                unlock( lock );
    651                 park( __cfaabi_dbg_ctx );
     648                park();
    652649                return true;
    653650        }
     
    670667
    671668        // make new owner
    672         unpark( thrd __cfaabi_dbg_ctx2 );
     669        unpark( thrd );
    673670
    674671        return thrd != 0p;
     
    681678        count += diff;
    682679        for(release) {
    683                 unpark( pop_head( waiting ) __cfaabi_dbg_ctx2 );
     680                unpark( pop_head( waiting ) );
    684681        }
    685682
     
    697694                        this.prev_thrd = kernelTLS.this_thread;
    698695                }
    699 
    700                 void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]) {
    701                         if(park) {
    702                                 this.park_caller   = prev_name;
    703                                 this.park_stale    = false;
    704                         }
    705                         else {
    706                                 this.unpark_caller = prev_name;
    707                                 this.unpark_stale  = false;
    708                         }
    709                 }
    710696        }
    711697)
  • libcfa/src/concurrency/kernel.hfa

    rae2c27a rc76bd34  
    2323
    2424extern "C" {
    25 #include <bits/pthreadtypes.h>
     25        #include <bits/pthreadtypes.h>
     26        #include <linux/types.h>
    2627}
    2728
     
    4748// Processor id, required for scheduling threads
    4849struct __processor_id_t {
    49         unsigned id;
     50        unsigned id:24;
     51        bool full_proc:1;
    5052
    5153        #if !defined(__CFA_NO_STATISTICS__)
     
    157159
    158160struct io_cancellation {
    159         uint32_t target;
     161        __u64 target;
    160162};
    161163
  • libcfa/src/concurrency/kernel/fwd.hfa

    rae2c27a rc76bd34  
    118118
    119119        extern "Cforall" {
    120                 extern void park( __cfaabi_dbg_ctx_param );
    121                 extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
     120                extern void park( void );
     121                extern void unpark( struct $thread * this );
    122122                static inline struct $thread * active_thread () { return TL_GET( this_thread ); }
    123123
  • libcfa/src/concurrency/kernel/startup.cfa

    rae2c27a rc76bd34  
    451451        link.next = 0p;
    452452        link.prev = 0p;
     453        #if defined( __CFA_WITH_VERIFY__ )
     454                canary = 0x0D15EA5E0D15EA5E;
     455        #endif
    453456
    454457        node.next = 0p;
     
    470473        this.name = name;
    471474        this.cltr = &_cltr;
    472         id = -1u;
     475        full_proc = true;
    473476        destroyer = 0p;
    474477        do_terminate = false;
  • libcfa/src/concurrency/kernel_private.hfa

    rae2c27a rc76bd34  
    6464
    6565// KERNEL ONLY unpark with out disabling interrupts
    66 void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 );
     66void __unpark( struct __processor_id_t *, $thread * thrd );
    6767
    6868static inline bool __post(single_sem & this, struct __processor_id_t * id) {
     
    7777                else {
    7878                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    79                                 __unpark( id, expected __cfaabi_dbg_ctx2 );
     79                                __unpark( id, expected );
    8080                                return true;
    8181                        }
  • libcfa/src/concurrency/monitor.cfa

    rae2c27a rc76bd34  
    8989        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    9090
    91         if( !this->owner ) {
     91        if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
     92                abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
     93        }
     94        else if( !this->owner ) {
    9295                // No one has the monitor, just take it
    9396                __set_owner( this, thrd );
     
    119122
    120123                unlock( this->lock );
    121                 park( __cfaabi_dbg_ctx );
     124                park();
    122125
    123126                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     
    137140}
    138141
    139 static void __dtor_enter( $monitor * this, fptr_t func ) {
     142static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
    140143        // Lock the monitor spinlock
    141144        lock( this->lock __cfaabi_dbg_ctx2 );
     
    157160                return;
    158161        }
    159         else if( this->owner == thrd) {
     162        else if( this->owner == thrd && !join) {
    160163                // We already have the monitor... but where about to destroy it so the nesting will fail
    161164                // Abort!
    162165                abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
     166        }
     167        // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check
     168        // to avoid that it sets the owner to the special value thrd | 1p before exiting
     169        else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) {
     170                // restore the owner and just return
     171                __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     172
     173                // No one has the monitor, just take it
     174                this->owner = thrd;
     175
     176                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     177
     178                unlock( this->lock );
     179                return;
    163180        }
    164181
     
    184201                // Release the next thread
    185202                /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    186                 unpark( urgent->owner->waiting_thread __cfaabi_dbg_ctx2 );
     203                unpark( urgent->owner->waiting_thread );
    187204
    188205                // Park current thread waiting
    189                 park( __cfaabi_dbg_ctx );
     206                park();
    190207
    191208                // Some one was waiting for us, enter
     
    205222
    206223                // Park current thread waiting
    207                 park( __cfaabi_dbg_ctx );
     224                park();
    208225
    209226                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     
    247264        //We need to wake-up the thread
    248265        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    249         unpark( new_owner __cfaabi_dbg_ctx2 );
     266        unpark( new_owner );
    250267}
    251268
    252269// Leave single monitor for the last time
    253 void __dtor_leave( $monitor * this ) {
     270void __dtor_leave( $monitor * this, bool join ) {
    254271        __cfaabi_dbg_debug_do(
    255272                if( TL_GET( this_thread ) != this->owner ) {
    256273                        abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
    257274                }
    258                 if( this->recursion != 1 ) {
     275                if( this->recursion != 1  && !join ) {
    259276                        abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    260277                }
    261278        )
     279
     280        this->owner = ($thread*)(1 | (uintptr_t)this->owner);
    262281}
    263282
     
    307326}
    308327
     328// Join a thread
     329forall( dtype T | is_thread(T) )
     330T & join( T & this ) {
     331        $monitor *    m = get_monitor(this);
     332        void (*dtor)(T& mutex this) = ^?{};
     333        monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
     334        {
     335                return this;
     336        }
     337}
     338
    309339// Enter multiple monitor
    310340// relies on the monitor array being sorted
     
    366396// Ctor for monitor guard
    367397// Sorts monitors before entering
    368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
     398void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
    369399        // optimization
    370400        $thread * thrd = TL_GET( this_thread );
     
    376406        this.prev = thrd->monitors;
    377407
     408        // Save whether we are in a join or not
     409        this.join = join;
     410
    378411        // Update thread context (needed for conditions)
    379412        (thrd->monitors){m, 1, func};
    380413
    381         __dtor_enter( this.m, func );
     414        __dtor_enter( this.m, func, join );
    382415}
    383416
     
    385418void ^?{}( monitor_dtor_guard_t & this ) {
    386419        // Leave the monitors in order
    387         __dtor_leave( this.m );
     420        __dtor_leave( this.m, this.join );
    388421
    389422        // Restore thread context
     
    460493        // Wake the threads
    461494        for(int i = 0; i < thread_count; i++) {
    462                 unpark( threads[i] __cfaabi_dbg_ctx2 );
     495                unpark( threads[i] );
    463496        }
    464497
    465498        // Everything is ready to go to sleep
    466         park( __cfaabi_dbg_ctx );
     499        park();
    467500
    468501        // We are back, restore the owners and recursions
     
    542575
    543576        // unpark the thread we signalled
    544         unpark( signallee __cfaabi_dbg_ctx2 );
     577        unpark( signallee );
    545578
    546579        //Everything is ready to go to sleep
    547         park( __cfaabi_dbg_ctx );
     580        park();
    548581
    549582
     
    646679
    647680                                // unpark the thread we signalled
    648                                 unpark( next __cfaabi_dbg_ctx2 );
     681                                unpark( next );
    649682
    650683                                //Everything is ready to go to sleep
    651                                 park( __cfaabi_dbg_ctx );
     684                                park();
    652685
    653686                                // We are back, restore the owners and recursions
     
    691724
    692725        //Everything is ready to go to sleep
    693         park( __cfaabi_dbg_ctx );
     726        park();
    694727
    695728
  • libcfa/src/concurrency/monitor.hfa

    rae2c27a rc76bd34  
    5353        $monitor *    m;
    5454        __monitor_group_t prev;
     55        bool join;
    5556};
    5657
    57 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );
     58void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join );
    5859void ^?{}( monitor_dtor_guard_t & this );
    5960
  • libcfa/src/concurrency/mutex.cfa

    rae2c27a rc76bd34  
    4242                append( blocked_threads, kernelTLS.this_thread );
    4343                unlock( lock );
    44                 park( __cfaabi_dbg_ctx );
     44                park();
    4545        }
    4646        else {
     
    6565        this.is_locked = (this.blocked_threads != 0);
    6666        unpark(
    67                 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
     67                pop_head( this.blocked_threads )
    6868        );
    6969        unlock( this.lock );
     
    9797                append( blocked_threads, kernelTLS.this_thread );
    9898                unlock( lock );
    99                 park( __cfaabi_dbg_ctx );
     99                park();
    100100        }
    101101}
     
    124124                owner = thrd;
    125125                recursion_count = (thrd ? 1 : 0);
    126                 unpark( thrd __cfaabi_dbg_ctx2 );
     126                unpark( thrd );
    127127        }
    128128        unlock( lock );
     
    142142        lock( lock __cfaabi_dbg_ctx2 );
    143143        unpark(
    144                 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
     144                pop_head( this.blocked_threads )
    145145        );
    146146        unlock( lock );
     
    151151        while(this.blocked_threads) {
    152152                unpark(
    153                         pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
     153                        pop_head( this.blocked_threads )
    154154                );
    155155        }
     
    161161        append( this.blocked_threads, kernelTLS.this_thread );
    162162        unlock( this.lock );
    163         park( __cfaabi_dbg_ctx );
     163        park();
    164164}
    165165
     
    170170        unlock(l);
    171171        unlock(this.lock);
    172         park( __cfaabi_dbg_ctx );
     172        park();
    173173        lock(l);
    174174}
  • libcfa/src/concurrency/preemption.cfa

    rae2c27a rc76bd34  
    274274                kernelTLS.this_stats = this->curr_cluster->stats;
    275275        #endif
    276         __unpark( id, this __cfaabi_dbg_ctx2 );
     276        __unpark( id, this );
    277277}
    278278
     
    411411static void * alarm_loop( __attribute__((unused)) void * args ) {
    412412        __processor_id_t id;
     413        id.full_proc = false;
    413414        id.id = doregister(&id);
    414415
  • libcfa/src/concurrency/thread.cfa

    rae2c27a rc76bd34  
    3939        link.prev = 0p;
    4040        link.preferred = -1;
     41        #if defined( __CFA_WITH_VERIFY__ )
     42                canary = 0x0D15EA5E0D15EA5E;
     43        #endif
    4144
    4245        node.next = 0p;
     
    4851
    4952void ^?{}($thread& this) with( this ) {
     53        #if defined( __CFA_WITH_VERIFY__ )
     54                canary = 0xDEADDEADDEADDEAD;
     55        #endif
    5056        unregister(curr_cluster, this);
    5157        ^self_cor{};
  • libcfa/src/concurrency/thread.hfa

    rae2c27a rc76bd34  
    8888//----------
    8989// Park thread: block until corresponding call to unpark, won't block if unpark is already called
    90 void park( __cfaabi_dbg_ctx_param );
     90void park( void );
    9191
    9292//----------
    9393// Unpark a thread, if the thread is already blocked, schedule it
    9494//                  if the thread is not yet block, signal that it should rerun immediately
    95 void unpark( $thread * this __cfaabi_dbg_ctx_param2 );
     95void unpark( $thread * this );
    9696
    9797forall( dtype T | is_thread(T) )
    98 static inline void unpark( T & this __cfaabi_dbg_ctx_param2 ) { if(!&this) return; unpark( get_thread( this ) __cfaabi_dbg_ctx_fwd2 );}
     98static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
    9999
    100100//----------
     
    106106void sleep( Duration duration );
    107107
     108//----------
     109// join
     110forall( dtype T | is_thread(T) )
     111T & join( T & this );
     112
    108113// Local Variables: //
    109114// mode: c //
  • libcfa/src/exception.h

    rae2c27a rc76bd34  
    7676// implemented in the .c file either so they all have to be inline.
    7777
    78 trait is_exception(dtype T) {
     78trait is_exception(dtype exceptT) {
    7979        /* The first field must be a pointer to a virtual table.
    8080         * That virtual table must be a decendent of the base exception virtual tab$
    8181         */
    82         void mark_exception(T *);
     82        void mark_exception(exceptT *);
    8383        // This is never used and should be a no-op.
    8484};
    8585
    86 trait is_termination_exception(dtype T | is_exception(T)) {
    87         void defaultTerminationHandler(T &);
     86trait is_termination_exception(dtype exceptT | is_exception(exceptT)) {
     87        void defaultTerminationHandler(exceptT &);
    8888};
    8989
    90 trait is_resumption_exception(dtype T | is_exception(T)) {
    91         void defaultResumptionHandler(T &);
     90trait is_resumption_exception(dtype exceptT | is_exception(exceptT)) {
     91        void defaultResumptionHandler(exceptT &);
    9292};
    9393
    94 forall(dtype T | is_termination_exception(T))
    95 static inline void $throw(T & except) {
     94forall(dtype exceptT | is_termination_exception(exceptT))
     95static inline void $throw(exceptT & except) {
    9696        __cfaehm_throw_terminate(
    9797                (exception_t *)&except,
     
    100100}
    101101
    102 forall(dtype T | is_resumption_exception(T))
    103 static inline void $throwResume(T & except) {
     102forall(dtype exceptT | is_resumption_exception(exceptT))
     103static inline void $throwResume(exceptT & except) {
    104104        __cfaehm_throw_resume(
    105105                (exception_t *)&except,
     
    108108}
    109109
    110 forall(dtype T | is_exception(T))
    111 static inline void cancel_stack(T & except) __attribute__((noreturn)) {
     110forall(dtype exceptT | is_exception(exceptT))
     111static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) {
    112112        __cfaehm_cancel_stack( (exception_t *)&except );
    113113}
    114114
    115 forall(dtype T | is_exception(T))
    116 static inline void defaultTerminationHandler(T & except) {
     115forall(dtype exceptT | is_exception(exceptT))
     116static inline void defaultTerminationHandler(exceptT & except) {
    117117        return cancel_stack( except );
    118118}
    119119
    120 forall(dtype T | is_exception(T))
    121 static inline void defaultResumptionHandler(T & except) {
     120forall(dtype exceptT | is_exception(exceptT))
     121static inline void defaultResumptionHandler(exceptT & except) {
    122122        throw except;
    123123}
  • libcfa/src/exception.hfa

    rae2c27a rc76bd34  
    192192                size_t size; \
    193193                void (*copy)(exception_name * this, exception_name * other); \
    194                 void (*free)(exception_name & this); \
     194                void (*^?{})(exception_name & this); \
    195195                const char * (*msg)(exception_name * this); \
    196196                _CLOSE
     
    213213                size_t size; \
    214214                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
    215                 void (*free)(exception_name parameters & this); \
     215                void (*^?{})(exception_name parameters & this); \
    216216                const char * (*msg)(exception_name parameters * this); \
    217217                _CLOSE
  • libcfa/src/heap.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Sep  3 16:22:54 2020
    13 // Update Count     : 943
     12// Last Modified On : Mon Sep  7 22:17:46 2020
     13// Update Count     : 957
    1414//
    1515
     
    889889                size_t bsize, oalign;
    890890                headers( "resize", oaddr, header, freeElem, bsize, oalign );
    891 
    892891                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     892
    893893                // same size, DO NOT preserve STICKY PROPERTIES.
    894                 if ( oalign <= libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
     894                if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
    895895                        header->kind.real.blockSize &= -2;                      // no alignment and turn off 0 fill
    896896                        header->kind.real.size = size;                          // reset allocation size
     
    931931                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    932932                size_t osize = header->kind.real.size;                  // old allocation size
    933                 bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled
    934           if ( unlikely( size <= odsize ) && size > odsize / 2 ) { // allow up to 50% wasted storage
     933                bool ozfill = (header->kind.real.blockSize & 2); // old allocation zero filled
     934          if ( unlikely( size <= odsize ) && odsize <= size * 2 ) { // allow up to 50% wasted storage
    935935                        header->kind.real.size = size;                          // reset allocation size
    936936                        if ( unlikely( ozfill ) && size > osize ) {     // previous request zero fill and larger ?
     
    947947
    948948                void * naddr;
    949                 if ( likely( oalign <= libAlign() ) ) {                 // previous request not aligned ?
     949                if ( likely( oalign == libAlign() ) ) {                 // previous request not aligned ?
    950950                        naddr = mallocNoStats( size );                          // create new area
    951951                } else {
     
    12311231        } // if
    12321232
    1233         // Attempt to reuse existing storage.
     1233        // Attempt to reuse existing alignment.
    12341234        HeapManager.Storage.Header * header = headerAddr( oaddr );
    1235         bool isFakeHeader = header->kind.fake.alignment & 1 == 1;       // old fake header ?
    1236         if ( unlikely ( ( isFakeHeader &&
    1237                                  (uintptr_t)oaddr % nalign == 0 &&                              // lucky match ?
    1238                                  header->kind.fake.alignment <= nalign &&               // ok to leave LSB at 1
    1239                                  nalign <= 128 )                                                                // not too much alignment storage wasted ?
    1240                         ||   ( (!isFakeHeader) &&                                                       // old real header ( aligned on libAlign ) ?
    1241                                  nalign == libAlign() ) ) ) {                                   // new alignment also on libAlign
    1242 
    1243                 HeapManager.FreeHeader * freeElem;
    1244                 size_t bsize, oalign;
    1245                 headers( "resize", oaddr, header, freeElem, bsize, oalign );
    1246                 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    1247 
    1248                 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage
    1249                         if ( isFakeHeader ) {
     1235        bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
     1236        size_t oalign;
     1237        if ( isFakeHeader ) {
     1238                oalign = header->kind.fake.alignment & -2;              // old alignment
     1239                if ( (uintptr_t)oaddr % nalign == 0                             // lucky match ?
     1240                         && ( oalign <= nalign                                          // going down
     1241                                  || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ?
     1242                        ) {
     1243                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
     1244                        HeapManager.FreeHeader * freeElem;
     1245                        size_t bsize, oalign;
     1246                        headers( "resize", oaddr, header, freeElem, bsize, oalign );
     1247                        size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1248
     1249                        if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage
    12501250                                headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1251                         }
    1252 
    1253                         header->kind.real.blockSize &= -2;              // turn off 0 fill
    1254                         header->kind.real.size = size;                  // reset allocation size
    1255                         return oaddr;
    1256                 } // if
     1251
     1252                                header->kind.real.blockSize &= -2;              // turn off 0 fill
     1253                                header->kind.real.size = size;                  // reset allocation size
     1254                                return oaddr;
     1255                        } // if
     1256                } // if
     1257        } else if ( ! isFakeHeader                                                      // old real header (aligned on libAlign) ?
     1258                                && nalign == libAlign() ) {                             // new alignment also on libAlign => no fake header needed
     1259                return resize( oaddr, size );                                   // duplicate special case checks
    12571260        } // if
    12581261
     
    12841287        } // if
    12851288
    1286         HeapManager.Storage.Header * header;
    1287         HeapManager.FreeHeader * freeElem;
    1288         size_t bsize, oalign;
    1289         headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    1290 
    1291         // Attempt to reuse existing storage.
    1292         bool isFakeHeader = header->kind.fake.alignment & 1 == 1;       // old fake header ?
    1293         if ( unlikely ( ( isFakeHeader &&
    1294                                  (uintptr_t)oaddr % nalign == 0 &&                              // lucky match ?
    1295                                  header->kind.fake.alignment <= nalign &&               // ok to leave LSB at 1
    1296                                  nalign <= 128 )                                                                // not too much alignment storage wasted ?
    1297                         ||   ( (!isFakeHeader) &&                                                       // old real header ( aligned on libAlign ) ?
    1298                                  nalign == libAlign() ) ) ) {                                   // new alignment also on libAlign
    1299 
    1300                 if ( isFakeHeader ) {
     1289        // Attempt to reuse existing alignment.
     1290        HeapManager.Storage.Header * header = headerAddr( oaddr );
     1291        bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
     1292        size_t oalign;
     1293        if ( isFakeHeader ) {
     1294                oalign = header->kind.fake.alignment & -2;              // old alignment
     1295                if ( (uintptr_t)oaddr % nalign == 0                             // lucky match ?
     1296                         && ( oalign <= nalign                                          // going down
     1297                                  || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ?
     1298                        ) {
    13011299                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1302                 }
    1303                 return realloc( oaddr, size );
    1304 
    1305         } // if
    1306 
    1307         // change size and copy old content to new storage
     1300                        return realloc( oaddr, size );                          // duplicate alignment and special case checks
     1301                } // if
     1302        } else if ( ! isFakeHeader                                                      // old real header (aligned on libAlign) ?
     1303                                && nalign == libAlign() )                               // new alignment also on libAlign => no fake header needed
     1304                return realloc( oaddr, size );                                  // duplicate alignment and special case checks
    13081305
    13091306        #ifdef __STATISTICS__
     
    13121309        #endif // __STATISTICS__
    13131310
     1311        HeapManager.FreeHeader * freeElem;
     1312        size_t bsize;
     1313        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     1314
     1315        // change size and copy old content to new storage
     1316
    13141317        size_t osize = header->kind.real.size;                          // old allocation size
    1315         bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled
     1318        bool ozfill = (header->kind.real.blockSize & 2);        // old allocation zero filled
    13161319
    13171320        void * naddr = memalignNoStats( nalign, size );         // create new aligned area
  • libcfa/src/limits.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Apr  6 18:06:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  1 16:22:51 2018
    13 // Update Count     : 74
     12// Last Modified On : Wed Sep 30 22:56:32 2020
     13// Update Count     : 76
    1414//
    1515
     
    2323// Integral Constants
    2424
    25 const signed char MIN = SCHAR_MIN;
    26 const unsigned char MIN = 0;
    27 const short int MIN = SHRT_MIN;
    28 const unsigned short int MIN = 0;
    29 const int MIN = INT_MIN;
    30 const unsigned int MIN = 0;
    31 const long int MIN = LONG_MIN;
    32 const unsigned long int MIN = 0;
    33 const long long int MIN = LLONG_MIN;
    34 const unsigned long long int MIN = 0;
     25signed char MIN = SCHAR_MIN;
     26unsigned char MIN = 0;
     27short int MIN = SHRT_MIN;
     28unsigned short int MIN = 0;
     29int MIN = INT_MIN;
     30unsigned int MIN = 0;
     31long int MIN = LONG_MIN;
     32unsigned long int MIN = 0;
     33long long int MIN = LLONG_MIN;
     34unsigned long long int MIN = 0;
    3535
    36 const signed char MAX = SCHAR_MAX;
    37 const unsigned char MAX = UCHAR_MAX;
    38 const short int MAX = SHRT_MAX;
    39 const unsigned short int MAX = USHRT_MAX;
    40 const int MAX = INT_MAX;
    41 const unsigned int MAX = UINT_MAX;
    42 const long int MAX = LONG_MAX;
    43 const unsigned long int MAX = ULONG_MAX;
    44 const long long int MAX = LLONG_MAX;
    45 const unsigned long long int MAX = ULLONG_MAX;
     36signed char MAX = SCHAR_MAX;
     37unsigned char MAX = UCHAR_MAX;
     38short int MAX = SHRT_MAX;
     39unsigned short int MAX = USHRT_MAX;
     40int MAX = INT_MAX;
     41unsigned int MAX = UINT_MAX;
     42long int MAX = LONG_MAX;
     43unsigned long int MAX = ULONG_MAX;
     44long long int MAX = LLONG_MAX;
     45unsigned long long int MAX = ULLONG_MAX;
    4646
    4747// Floating-Point Constants
    4848
    49 const float MIN = FLT_MIN;
    50 const double MIN = DBL_MIN;
    51 const long double MIN = LDBL_MIN;
    52 const float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;
    53 const double _Complex MIN = DBL_MIN +  DBL_MIN * I;
    54 const long double _Complex MIN = LDBL_MIN + LDBL_MIN * I;
     49float MIN = FLT_MIN;
     50double MIN = DBL_MIN;
     51long double MIN = LDBL_MIN;
     52float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;
     53double _Complex MIN = DBL_MIN +  DBL_MIN * I;
     54long double _Complex MIN = LDBL_MIN + LDBL_MIN * I;
    5555
    56 const float MAX = FLT_MAX;
    57 const double MAX = DBL_MAX;
    58 const long double MAX = LDBL_MAX;
    59 const float _Complex MAX = FLT_MAX + FLT_MAX * I;
    60 const double _Complex MAX = DBL_MAX + DBL_MAX * I;
    61 const long double _Complex MAX = LDBL_MAX + LDBL_MAX * I;
     56float MAX = FLT_MAX;
     57double MAX = DBL_MAX;
     58long double MAX = LDBL_MAX;
     59float _Complex MAX = FLT_MAX + FLT_MAX * I;
     60double _Complex MAX = DBL_MAX + DBL_MAX * I;
     61long double _Complex MAX = LDBL_MAX + LDBL_MAX * I;
    6262
    63 const float PI = (float)M_PI;                                                   // pi
    64 const float PI_2 = (float)M_PI_2;                                               // pi / 2
    65 const float PI_4 = (float)M_PI_4;                                               // pi / 4
    66 const float _1_PI = (float)M_1_PI;                                              // 1 / pi
    67 const float _2_PI = (float)M_2_PI;                                              // 2 / pi
    68 const float _2_SQRT_PI = (float)M_2_SQRTPI;                             // 2 / sqrt(pi)
     63float PI = (float)M_PI;                                                                 // pi
     64float PI_2 = (float)M_PI_2;                                                             // pi / 2
     65float PI_4 = (float)M_PI_4;                                                             // pi / 4
     66float _1_PI = (float)M_1_PI;                                                    // 1 / pi
     67float _2_PI = (float)M_2_PI;                                                    // 2 / pi
     68float _2_SQRT_PI = (float)M_2_SQRTPI;                                   // 2 / sqrt(pi)
    6969
    70 const double PI = M_PI;                                                                 // pi
    71 const double PI_2 = M_PI_2;                                                             // pi / 2
    72 const double PI_4 = M_PI_4;                                                             // pi / 4
    73 const double _1_PI = M_1_PI;                                                    // 1 / pi
    74 const double _2_PI = M_2_PI;                                                    // 2 / pi
    75 const double _2_SQRT_PI = M_2_SQRTPI;                                   // 2 / sqrt(pi)
     70double PI = M_PI;                                                                               // pi
     71double PI_2 = M_PI_2;                                                                   // pi / 2
     72double PI_4 = M_PI_4;                                                                   // pi / 4
     73double _1_PI = M_1_PI;                                                                  // 1 / pi
     74double _2_PI = M_2_PI;                                                                  // 2 / pi
     75double _2_SQRT_PI = M_2_SQRTPI;                                                 // 2 / sqrt(pi)
    7676
    77 const long double PI = M_PIl;                                                   // pi
    78 const long double PI_2 = M_PI_2l;                                               // pi / 2
    79 const long double PI_4 = M_PI_4l;                                               // pi / 4
    80 const long double _1_PI = M_1_PIl;                                              // 1 / pi
    81 const long double _2_PI = M_2_PIl;                                              // 2 / pi
    82 const long double _2_SQRT_PI = M_2_SQRTPIl;                             // 2 / sqrt(pi)
     77long double PI = M_PIl;                                                                 // pi
     78long double PI_2 = M_PI_2l;                                                             // pi / 2
     79long double PI_4 = M_PI_4l;                                                             // pi / 4
     80long double _1_PI = M_1_PIl;                                                    // 1 / pi
     81long double _2_PI = M_2_PIl;                                                    // 2 / pi
     82long double _2_SQRT_PI = M_2_SQRTPIl;                                   // 2 / sqrt(pi)
    8383
    84 const float _Complex PI = (float)M_PI + 0.0_iF;                 // pi
    85 const float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;             // pi / 2
    86 const float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;             // pi / 4
    87 const float _Complex _1_PI = (float)M_1_PI + 0.0_iF;    // 1 / pi
    88 const float _Complex _2_PI = (float)M_2_PI + 0.0_iF;    // 2 / pi
    89 const float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)
     84float _Complex PI = (float)M_PI + 0.0_iF;                               // pi
     85float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;                   // pi / 2
     86float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;                   // pi / 4
     87float _Complex _1_PI = (float)M_1_PI + 0.0_iF;                  // 1 / pi
     88float _Complex _2_PI = (float)M_2_PI + 0.0_iF;                  // 2 / pi
     89float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)
    9090
    91 const double _Complex PI = M_PI + 0.0_iD;                               // pi
    92 const double _Complex PI_2 = M_PI_2 + 0.0_iD;                   // pi / 2
    93 const double _Complex PI_4 = M_PI_4 + 0.0_iD;                   // pi / 4
    94 const double _Complex _1_PI = M_1_PI + 0.0_iD;                  // 1 / pi
    95 const double _Complex _2_PI = M_2_PI + 0.0_iD;                  // 2 / pi
    96 const double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD; // 2 / sqrt(pi)
     91double _Complex PI = M_PI + 0.0_iD;                                             // pi
     92double _Complex PI_2 = M_PI_2 + 0.0_iD;                                 // pi / 2
     93double _Complex PI_4 = M_PI_4 + 0.0_iD;                                 // pi / 4
     94double _Complex _1_PI = M_1_PI + 0.0_iD;                                // 1 / pi
     95double _Complex _2_PI = M_2_PI + 0.0_iD;                                // 2 / pi
     96double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD;               // 2 / sqrt(pi)
    9797
    98 const long double _Complex PI = M_PIl + 0.0_iL;                 // pi
    99 const long double _Complex PI_2 = M_PI_2l + 0.0_iL;             // pi / 2
    100 const long double _Complex PI_4 = M_PI_4l + 0.0_iL;             // pi / 4
    101 const long double _Complex _1_PI = M_1_PIl + 0.0_iL;    // 1 / pi
    102 const long double _Complex _2_PI = M_2_PIl + 0.0_iL;    // 2 / pi
    103 const long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)
     98long double _Complex PI = M_PIl + 0.0_iL;                               // pi
     99long double _Complex PI_2 = M_PI_2l + 0.0_iL;                   // pi / 2
     100long double _Complex PI_4 = M_PI_4l + 0.0_iL;                   // pi / 4
     101long double _Complex _1_PI = M_1_PIl + 0.0_iL;                  // 1 / pi
     102long double _Complex _2_PI = M_2_PIl + 0.0_iL;                  // 2 / pi
     103long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)
    104104
    105 const float E = (float)M_E;                                                             // e
    106 const float LOG2_E = (float)M_LOG2E;                                    // log_2(e)
    107 const float LOG10_E = (float)M_LOG10E;                                  // log_10(e)
    108 const float LN_2 = (float)M_LN2;                                                // log_e(2)
    109 const float LN_10 = (float)M_LN10;                                              // log_e(10)
    110 const float SQRT_2 = (float)M_SQRT2;                                    // sqrt(2)
    111 const float _1_SQRT_2 = (float)M_SQRT1_2;                               // 1 / sqrt(2)
     105float E = (float)M_E;                                                                   // e
     106float LOG2_E = (float)M_LOG2E;                                                  // log_2(e)
     107float LOG10_E = (float)M_LOG10E;                                                // log_10(e)
     108float LN_2 = (float)M_LN2;                                                              // log_e(2)
     109float LN_10 = (float)M_LN10;                                                    // log_e(10)
     110float SQRT_2 = (float)M_SQRT2;                                                  // sqrt(2)
     111float _1_SQRT_2 = (float)M_SQRT1_2;                                             // 1 / sqrt(2)
    112112
    113 const double E = M_E;                                                                   // e
    114 const double LOG2_E = M_LOG2E;                                                  // log_2(e)
    115 const double LOG10_E = M_LOG10E;                                                // log_10(e)
    116 const double LN_2 = M_LN2;                                                              // log_e(2)
    117 const double LN_10 = M_LN10;                                                    // log_e(10)
    118 const double SQRT_2 = M_SQRT2;                                                  // sqrt(2)
    119 const double _1_SQRT_2 = M_SQRT1_2;                                             // 1 / sqrt(2)
     113double E = M_E;                                                                                 // e
     114double LOG2_E = M_LOG2E;                                                                // log_2(e)
     115double LOG10_E = M_LOG10E;                                                              // log_10(e)
     116double LN_2 = M_LN2;                                                                    // log_e(2)
     117double LN_10 = M_LN10;                                                                  // log_e(10)
     118double SQRT_2 = M_SQRT2;                                                                // sqrt(2)
     119double _1_SQRT_2 = M_SQRT1_2;                                                   // 1 / sqrt(2)
    120120
    121 const long double E = M_El;                                                             // e
    122 const long double LOG2_E = M_LOG2El;                                    // log_2(e)
    123 const long double LOG10_E = M_LOG10El;                                  // log_10(e)
    124 const long double LN_2 = M_LN2l;                                                // log_e(2)
    125 const long double LN_10 = M_LN10l;                                              // log_e(10)
    126 const long double SQRT_2 = M_SQRT2l;                                    // sqrt(2)
    127 const long double _1_SQRT_2 = M_SQRT1_2l;                               // 1 / sqrt(2)
     121long double E = M_El;                                                                   // e
     122long double LOG2_E = M_LOG2El;                                                  // log_2(e)
     123long double LOG10_E = M_LOG10El;                                                // log_10(e)
     124long double LN_2 = M_LN2l;                                                              // log_e(2)
     125long double LN_10 = M_LN10l;                                                    // log_e(10)
     126long double SQRT_2 = M_SQRT2l;                                                  // sqrt(2)
     127long double _1_SQRT_2 = M_SQRT1_2l;                                             // 1 / sqrt(2)
    128128
    129 const float _Complex E = M_E + 0.0_iF;                                  // e
    130 const float _Complex LOG2_E = M_LOG2E + 0.0_iF;                 // log_2(e)
    131 const float _Complex LOG10_E = M_LOG10E + 0.0_iF;               // log_10(e)
    132 const float _Complex LN_2 = M_LN2 + 0.0_iF;                             // log_e(2)
    133 const float _Complex LN_10 = M_LN10 + 0.0_iF;                   // log_e(10)
    134 const float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;                 // sqrt(2)
    135 const float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;    // 1 / sqrt(2)
     129float _Complex E = M_E + 0.0_iF;                                                // e
     130float _Complex LOG2_E = M_LOG2E + 0.0_iF;                               // log_2(e)
     131float _Complex LOG10_E = M_LOG10E + 0.0_iF;                             // log_10(e)
     132float _Complex LN_2 = M_LN2 + 0.0_iF;                                   // log_e(2)
     133float _Complex LN_10 = M_LN10 + 0.0_iF;                                 // log_e(10)
     134float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;                               // sqrt(2)
     135float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;                  // 1 / sqrt(2)
    136136
    137 const double _Complex E = M_E + 0.0_iD;                                 // e
    138 const double _Complex LOG2_E = M_LOG2E + 0.0_iD;                // log_2(e)
    139 const double _Complex LOG10_E = M_LOG10E + 0.0_iD;              // log_10(e)
    140 const double _Complex LN_2 = M_LN2 + 0.0_iD;                    // log_e(2)
    141 const double _Complex LN_10 = M_LN10 + 0.0_iD;                  // log_e(10)
    142 const double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;                // sqrt(2)
    143 const double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;   // 1 / sqrt(2)
     137double _Complex E = M_E + 0.0_iD;                                               // e
     138double _Complex LOG2_E = M_LOG2E + 0.0_iD;                              // log_2(e)
     139double _Complex LOG10_E = M_LOG10E + 0.0_iD;                    // log_10(e)
     140double _Complex LN_2 = M_LN2 + 0.0_iD;                                  // log_e(2)
     141double _Complex LN_10 = M_LN10 + 0.0_iD;                                // log_e(10)
     142double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;                              // sqrt(2)
     143double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;                 // 1 / sqrt(2)
    144144
    145 const long double _Complex E = M_El + 0.0_iL;                   // e
    146 const long double _Complex LOG2_E = M_LOG2El + 0.0_iL;  // log_2(e)
    147 const long double _Complex LOG10_E = M_LOG10El + 0.0_iL; // log_10(e)
    148 const long double _Complex LN_2 = M_LN2l + 0.0_iL;              // log_e(2)
    149 const long double _Complex LN_10 = M_LN10l + 0.0_iL;    // log_e(10)
    150 const long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;  // sqrt(2)
    151 const long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL; // 1 / sqrt(2)
     145long double _Complex E = M_El + 0.0_iL;                                 // e
     146long double _Complex LOG2_E = M_LOG2El + 0.0_iL;                // log_2(e)
     147long double _Complex LOG10_E = M_LOG10El + 0.0_iL;              // log_10(e)
     148long double _Complex LN_2 = M_LN2l + 0.0_iL;                    // log_e(2)
     149long double _Complex LN_10 = M_LN10l + 0.0_iL;                  // log_e(10)
     150long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;                // sqrt(2)
     151long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL;   // 1 / sqrt(2)
    152152
    153153// Local Variables: //
  • libcfa/src/limits.hfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Apr  6 18:06:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  1 16:20:54 2018
    13 // Update Count     : 13
     12// Last Modified On : Wed Sep 30 22:56:35 2020
     13// Update Count     : 15
    1414//
    1515
     
    1818// Integral Constants
    1919
    20 extern const signed char MIN;
    21 extern const unsigned char MIN;
    22 extern const short int MIN;
    23 extern const unsigned short int MIN;
    24 extern const int MIN;
    25 extern const unsigned int MIN;
    26 extern const long int MIN;
    27 extern const unsigned long int MIN;
    28 extern const long long int MIN;
    29 extern const unsigned long long int MIN;
     20extern signed char MIN;
     21extern unsigned char MIN;
     22extern short int MIN;
     23extern unsigned short int MIN;
     24extern int MIN;
     25extern unsigned int MIN;
     26extern long int MIN;
     27extern unsigned long int MIN;
     28extern long long int MIN;
     29extern unsigned long long int MIN;
    3030
    31 extern const signed char MAX;
    32 extern const unsigned char MAX;
    33 extern const short int MAX;
    34 extern const unsigned short int MAX;
    35 extern const int MAX;
    36 extern const unsigned int MAX;
    37 extern const long int MAX;
    38 extern const unsigned long int MAX;
    39 extern const long long int MAX;
    40 extern const unsigned long long int MAX;
     31extern signed char MAX;
     32extern unsigned char MAX;
     33extern short int MAX;
     34extern unsigned short int MAX;
     35extern int MAX;
     36extern unsigned int MAX;
     37extern long int MAX;
     38extern unsigned long int MAX;
     39extern long long int MAX;
     40extern unsigned long long int MAX;
    4141
    4242// Floating-Point Constants
    4343
    44 extern const float MIN;
    45 extern const double MIN;
    46 extern const long double MIN;
    47 extern const float _Complex MIN;
    48 extern const double _Complex MIN;
    49 extern const long double _Complex MIN;
     44extern float MIN;
     45extern double MIN;
     46extern long double MIN;
     47extern float _Complex MIN;
     48extern double _Complex MIN;
     49extern long double _Complex MIN;
    5050
    51 extern const float MAX;
    52 extern const double MAX;
    53 extern const long double MAX;
    54 extern const float _Complex MAX;
    55 extern const double _Complex MAX;
    56 extern const long double _Complex MAX;
     51extern float MAX;
     52extern double MAX;
     53extern long double MAX;
     54extern float _Complex MAX;
     55extern double _Complex MAX;
     56extern long double _Complex MAX;
    5757
    58 extern const float PI;                                                                  // pi
    59 extern const float PI_2;                                                                // pi / 2
    60 extern const float PI_4;                                                                // pi / 4
    61 extern const float _1_PI;                                                               // 1 / pi
    62 extern const float _2_PI;                                                               // 2 / pi
    63 extern const float _2_SQRT_PI;                                                  // 2 / sqrt(pi)
     58extern float PI;                                                                                // pi
     59extern float PI_2;                                                                              // pi / 2
     60extern float PI_4;                                                                              // pi / 4
     61extern float _1_PI;                                                                             // 1 / pi
     62extern float _2_PI;                                                                             // 2 / pi
     63extern float _2_SQRT_PI;                                                                // 2 / sqrt(pi)
    6464
    65 extern const double PI;                                                                 // pi
    66 extern const double PI_2;                                                               // pi / 2
    67 extern const double PI_4;                                                               // pi / 4
    68 extern const double _1_PI;                                                              // 1 / pi
    69 extern const double _2_PI;                                                              // 2 / pi
    70 extern const double _2_SQRT_PI;                                                 // 2 / sqrt(pi)
     65extern double PI;                                                                               // pi
     66extern double PI_2;                                                                             // pi / 2
     67extern double PI_4;                                                                             // pi / 4
     68extern double _1_PI;                                                                    // 1 / pi
     69extern double _2_PI;                                                                    // 2 / pi
     70extern double _2_SQRT_PI;                                                               // 2 / sqrt(pi)
    7171
    72 extern const long double PI;                                                    // pi
    73 extern const long double PI_2;                                                  // pi / 2
    74 extern const long double PI_4;                                                  // pi / 4
    75 extern const long double _1_PI;                                                 // 1 / pi
    76 extern const long double _2_PI;                                                 // 2 / pi
    77 extern const long double _2_SQRT_PI;                                    // 2 / sqrt(pi)
     72extern long double PI;                                                                  // pi
     73extern long double PI_2;                                                                // pi / 2
     74extern long double PI_4;                                                                // pi / 4
     75extern long double _1_PI;                                                               // 1 / pi
     76extern long double _2_PI;                                                               // 2 / pi
     77extern long double _2_SQRT_PI;                                                  // 2 / sqrt(pi)
    7878
    79 extern const float _Complex PI;                                                 // pi
    80 extern const float _Complex PI_2;                                               // pi / 2
    81 extern const float _Complex PI_4;                                               // pi / 4
    82 extern const float _Complex _1_PI;                                              // 1 / pi
    83 extern const float _Complex _2_PI;                                              // 2 / pi
    84 extern const float _Complex _2_SQRT_PI;                                 // 2 / sqrt(pi)
     79extern float _Complex PI;                                                               // pi
     80extern float _Complex PI_2;                                                             // pi / 2
     81extern float _Complex PI_4;                                                             // pi / 4
     82extern float _Complex _1_PI;                                                    // 1 / pi
     83extern float _Complex _2_PI;                                                    // 2 / pi
     84extern float _Complex _2_SQRT_PI;                                               // 2 / sqrt(pi)
    8585
    86 extern const double _Complex PI;                                                // pi
    87 extern const double _Complex PI_2;                                              // pi / 2
    88 extern const double _Complex PI_4;                                              // pi / 4
    89 extern const double _Complex _1_PI;                                             // 1 / pi
    90 extern const double _Complex _2_PI;                                             // 2 / pi
    91 extern const double _Complex _2_SQRT_PI;                                // 2 / sqrt(pi)
     86extern double _Complex PI;                                                              // pi
     87extern double _Complex PI_2;                                                    // pi / 2
     88extern double _Complex PI_4;                                                    // pi / 4
     89extern double _Complex _1_PI;                                                   // 1 / pi
     90extern double _Complex _2_PI;                                                   // 2 / pi
     91extern double _Complex _2_SQRT_PI;                                              // 2 / sqrt(pi)
    9292
    93 extern const long double _Complex PI;                                   // pi
    94 extern const long double _Complex PI_2;                                 // pi / 2
    95 extern const long double _Complex PI_4;                                 // pi / 4
    96 extern const long double _Complex _1_PI;                                // 1 / pi
    97 extern const long double _Complex _2_PI;                                // 2 / pi
    98 extern const long double _Complex _2_SQRT_PI;                   // 2 / sqrt(pi)
     93extern long double _Complex PI;                                                 // pi
     94extern long double _Complex PI_2;                                               // pi / 2
     95extern long double _Complex PI_4;                                               // pi / 4
     96extern long double _Complex _1_PI;                                              // 1 / pi
     97extern long double _Complex _2_PI;                                              // 2 / pi
     98extern long double _Complex _2_SQRT_PI;                                 // 2 / sqrt(pi)
    9999
    100 extern const float E;                                                                   // e
    101 extern const float LOG2_E;                                                              // log_2(e)
    102 extern const float LOG10_E;                                                             // log_10(e)
    103 extern const float LN_2;                                                                // log_e(2)
    104 extern const float LN_10;                                                               // log_e(10)
    105 extern const float SQRT_2;                                                              // sqrt(2)
    106 extern const float _1_SQRT_2;                                                   // 1 / sqrt(2)
     100extern float E;                                                                                 // e
     101extern float LOG2_E;                                                                    // log_2(e)
     102extern float LOG10_E;                                                                   // log_10(e)
     103extern float LN_2;                                                                              // log_e(2)
     104extern float LN_10;                                                                             // log_e(10)
     105extern float SQRT_2;                                                                    // sqrt(2)
     106extern float _1_SQRT_2;                                                                 // 1 / sqrt(2)
    107107
    108 extern const double E;                                                                  // e
    109 extern const double LOG2_E;                                                             // log_2(e)
    110 extern const double LOG10_E;                                                    // log_10(e)
    111 extern const double LN_2;                                                               // log_e(2)
    112 extern const double LN_10;                                                              // log_e(10)
    113 extern const double SQRT_2;                                                             // sqrt(2)
    114 extern const double _1_SQRT_2;                                                  // 1 / sqrt(2)
     108extern double E;                                                                                // e
     109extern double LOG2_E;                                                                   // log_2(e)
     110extern double LOG10_E;                                                                  // log_10(e)
     111extern double LN_2;                                                                             // log_e(2)
     112extern double LN_10;                                                                    // log_e(10)
     113extern double SQRT_2;                                                                   // sqrt(2)
     114extern double _1_SQRT_2;                                                                // 1 / sqrt(2)
    115115
    116 extern const long double E;                                                             // e
    117 extern const long double LOG2_E;                                                // log_2(e)
    118 extern const long double LOG10_E;                                               // log_10(e)
    119 extern const long double LN_2;                                                  // log_e(2)
    120 extern const long double LN_10;                                                 // log_e(10)
    121 extern const long double SQRT_2;                                                // sqrt(2)
    122 extern const long double _1_SQRT_2;                                             // 1/sqrt(2)
     116extern long double E;                                                                   // e
     117extern long double LOG2_E;                                                              // log_2(e)
     118extern long double LOG10_E;                                                             // log_10(e)
     119extern long double LN_2;                                                                // log_e(2)
     120extern long double LN_10;                                                               // log_e(10)
     121extern long double SQRT_2;                                                              // sqrt(2)
     122extern long double _1_SQRT_2;                                                   // 1/sqrt(2)
    123123
    124 extern const float _Complex E;                                                  // e
    125 extern const float _Complex LOG2_E;                                             // log_2(e)
    126 extern const float _Complex LOG10_E;                                    // log_10(e)
    127 extern const float _Complex LN_2;                                               // log_e(2)
    128 extern const float _Complex LN_10;                                              // log_e(10)
    129 extern const float _Complex SQRT_2;                                             // sqrt(2)
    130 extern const float _Complex _1_SQRT_2;                                  // 1 / sqrt(2)
     124extern float _Complex E;                                                                // e
     125extern float _Complex LOG2_E;                                                   // log_2(e)
     126extern float _Complex LOG10_E;                                                  // log_10(e)
     127extern float _Complex LN_2;                                                             // log_e(2)
     128extern float _Complex LN_10;                                                    // log_e(10)
     129extern float _Complex SQRT_2;                                                   // sqrt(2)
     130extern float _Complex _1_SQRT_2;                                                // 1 / sqrt(2)
    131131
    132 extern const double _Complex E;                                                 // e
    133 extern const double _Complex LOG2_E;                                    // log_2(e)
    134 extern const double _Complex LOG10_E;                                   // log_10(e)
    135 extern const double _Complex LN_2;                                              // log_e(2)
    136 extern const double _Complex LN_10;                                             // log_e(10)
    137 extern const double _Complex SQRT_2;                                    // sqrt(2)
    138 extern const double _Complex _1_SQRT_2;                                 // 1 / sqrt(2)
     132extern double _Complex E;                                                               // e
     133extern double _Complex LOG2_E;                                                  // log_2(e)
     134extern double _Complex LOG10_E;                                                 // log_10(e)
     135extern double _Complex LN_2;                                                    // log_e(2)
     136extern double _Complex LN_10;                                                   // log_e(10)
     137extern double _Complex SQRT_2;                                                  // sqrt(2)
     138extern double _Complex _1_SQRT_2;                                               // 1 / sqrt(2)
    139139
    140 extern const long double _Complex E;                                    // e
    141 extern const long double _Complex LOG2_E;                               // log_2(e)
    142 extern const long double _Complex LOG10_E;                              // log_10(e)
    143 extern const long double _Complex LN_2;                                 // log_e(2)
    144 extern const long double _Complex LN_10;                                // log_e(10)
    145 extern const long double _Complex SQRT_2;                               // sqrt(2)
    146 extern const long double _Complex _1_SQRT_2;                    // 1 / sqrt(2)
     140extern long double _Complex E;                                                  // e
     141extern long double _Complex LOG2_E;                                             // log_2(e)
     142extern long double _Complex LOG10_E;                                    // log_10(e)
     143extern long double _Complex LN_2;                                               // log_e(2)
     144extern long double _Complex LN_10;                                              // log_e(10)
     145extern long double _Complex SQRT_2;                                             // sqrt(2)
     146extern long double _Complex _1_SQRT_2;                                  // 1 / sqrt(2)
    147147
    148148// Local Variables: //
  • libcfa/src/parseargs.cfa

    rae2c27a rc76bd34  
    2525#include "limits.hfa"
    2626
    27 extern int cfa_args_argc;
    28 extern char ** cfa_args_argv;
    29 extern char ** cfa_args_envp;
     27extern int cfa_args_argc __attribute__((weak));
     28extern char ** cfa_args_argv __attribute__((weak));
     29extern char ** cfa_args_envp __attribute__((weak));
    3030
    3131static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
    3232
    3333void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
    34         parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
     34        if( 0p != &cfa_args_argc ) {
     35                parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
     36        }
     37        else {
     38                char * temp = "";
     39                parse_args(0, &temp, options, opt_count, usage, left );
     40        }
    3541}
    3642
  • src/AST/Convert.cpp

    rae2c27a rc76bd34  
    177177        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
    178178                if ( inCache( node ) ) return nullptr;
     179
     180                // function decl contains real variables that the type must use.
     181                // the structural change means function type in and out of decl
     182                // must be handled **differently** on convert back to old.
     183                auto ftype = new FunctionType(
     184                        cv(node->type),
     185                        (bool)node->type->isVarArgs
     186                );
     187                ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
     188                ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
     189
     190                ftype->forall = get<TypeDecl>().acceptL( node->type->forall );
     191
     192                visitType(node->type, ftype);
     193
    179194                auto decl = new FunctionDecl(
    180195                        node->name,
    181196                        Type::StorageClasses( node->storage.val ),
    182197                        LinkageSpec::Spec( node->linkage.val ),
    183                         get<FunctionType>().accept1( node->type ),
     198                        ftype,
     199                        //get<FunctionType>().accept1( node->type ),
    184200                        {},
    185201                        get<Attribute>().acceptL( node->attributes ),
     
    11521168
    11531169        const ast::Type * visit( const ast::FunctionType * node ) override final {
     1170                static std::string dummy_paramvar_prefix = "__param_";
     1171                static std::string dummy_returnvar_prefix = "__retval_";
     1172
    11541173                auto ty = new FunctionType {
    11551174                        cv( node ),
    11561175                        (bool)node->isVarArgs
    11571176                };
    1158                 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1159                 ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     1177                auto returns = get<Type>().acceptL(node->returns);
     1178                auto params = get<Type>().acceptL(node->params);
     1179
     1180                int ret_index = 0;
     1181                for (auto t: returns) {
     1182                        // xxx - LinkageSpec shouldn't matter but needs to be something
     1183                        ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
     1184                        ty->returnVals.push_back(dummy);
     1185                }
     1186                int param_index = 0;
     1187                for (auto t: params) {
     1188                        ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
     1189                        ty->parameters.push_back(dummy);
     1190                }
     1191
     1192                // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
     1193                // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
    11601194                ty->forall = get<TypeDecl>().acceptL( node->forall );
    11611195                return visitType( node, ty );
    11621196        }
    11631197
    1164         const ast::Type * postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
     1198        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
    11651199                ty->forall = get<TypeDecl>().acceptL( old->forall );
    11661200                ty->parameters = get<Expression>().acceptL( old->params );
     
    13741408        ast::Node * node = nullptr;
    13751409        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1376         std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
     1410        /// in case that some nodes are dropped by conversion (due to possible structural change)
     1411        /// use smart pointers in cache value to prevent accidental invalidation.
     1412        /// at conversion stage, all created nodes are guaranteed to be unique, therefore
     1413        /// const_casting out of smart pointers is permitted.
     1414        std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {};
    13771415
    13781416        // Local Utilities:
     
    14471485                auto it = cache.find( old );
    14481486                if ( it == cache.end() ) return false;
    1449                 node = it->second;
     1487                node = const_cast<ast::Node *>(it->second.get());
    14501488                return true;
    14511489        }
     
    14861524        virtual void visit( const FunctionDecl * old ) override final {
    14871525                if ( inCache( old ) ) return;
     1526                auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
     1527                auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
     1528                auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
     1529
     1530                // function type is now derived from parameter decls instead of storing them
     1531                auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
     1532                ftype->params.reserve(paramVars.size());
     1533                ftype->returns.reserve(returnVars.size());
     1534
     1535                for (auto & v: paramVars) {
     1536                        ftype->params.emplace_back(v->get_type());
     1537                }
     1538                for (auto & v: returnVars) {
     1539                        ftype->returns.emplace_back(v->get_type());
     1540                }
     1541                ftype->forall = std::move(forall);
     1542                visitType(old->type, ftype);
     1543
    14881544                auto decl = new ast::FunctionDecl{
    14891545                        old->location,
    14901546                        old->name,
    1491                         GET_ACCEPT_1(type, FunctionType),
     1547                        // GET_ACCEPT_1(type, FunctionType),
     1548                        std::move(paramVars),
     1549                        std::move(returnVars),
    14921550                        {},
    14931551                        { old->storageClasses.val },
     
    14961554                        { old->get_funcSpec().val }
    14971555                };
     1556
     1557                decl->type = ftype;
    14981558                cache.emplace( old, decl );
     1559
    14991560                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15001561                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    25152576                        cv( old )
    25162577                };
    2517                 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2518                 ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     2578                auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
     2579                auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
     2580                // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
     2581                // ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     2582                for (auto & v: returnVars) {
     2583                        ty->returns.emplace_back(v->get_type());
     2584                }
     2585                for (auto & v: paramVars) {
     2586                        ty->params.emplace_back(v->get_type());
     2587                }
    25192588                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25202589                visitType( old, ty );
    25212590        }
    25222591
    2523         void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
     2592        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
    25242593                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25252594                ty->params = GET_ACCEPT_V( parameters, Expr );
  • src/AST/Decl.hpp

    rae2c27a rc76bd34  
    124124class FunctionDecl : public DeclWithType {
    125125public:
     126        std::vector<ptr<DeclWithType>> params;
     127        std::vector<ptr<DeclWithType>> returns;
     128        // declared type, derived from parameter declarations
    126129        ptr<FunctionType> type;
    127130        ptr<CompoundStmt> stmts;
    128131        std::vector< ptr<Expr> > withExprs;
    129132
    130         FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type,
     133        FunctionDecl( const CodeLocation & loc, const std::string & name,
     134                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    131135                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    132136                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
    133         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
     137        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
    134138          stmts( stmts ) {}
    135139
  • src/AST/ForallSubstitutor.hpp

    rae2c27a rc76bd34  
    3333        }
    3434
     35        template<typename node_t >
     36        std::vector<ptr<node_t>> operator() (const std::vector<ptr<node_t>> & o) {
     37                std::vector<ptr<node_t>> n;
     38                n.reserve(o.size());
     39                for (const node_t * d : o) { n.emplace_back(d->accept(*visitor)); }
     40                return n;
     41        }
     42       
     43        /*
     44
    3545        /// Substitute parameter/return type
    3646        std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
     
    4858                return n;
    4959        }
     60
     61        */
    5062};
    5163
  • src/AST/Fwd.hpp

    rae2c27a rc76bd34  
    107107class QualifiedType;
    108108class FunctionType;
    109 class ReferenceToType;
     109class BaseInstType;
    110110template<typename decl_t> class SueInstType;
    111111using StructInstType = SueInstType<StructDecl>;
  • src/AST/GenericSubstitution.cpp

    rae2c27a rc76bd34  
    4242        private:
    4343                // make substitution for generic type
    44                 void makeSub( const ReferenceToType * ty ) {
     44                void makeSub( const BaseInstType * ty ) {
    4545                        visit_children = false;
    4646                        const AggregateDecl * aggr = ty->aggr();
  • src/AST/Node.cpp

    rae2c27a rc76bd34  
    266266template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
    267267template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
    268 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
    269 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
     268template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >;
     269template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >;
    270270template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
    271271template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    rae2c27a rc76bd34  
    5050// | PureVisitor           - makes the visitor pure, it never modifies nodes in place and always
    5151//                           clones nodes it needs to make changes to
    52 // | WithTypeSubstitution  - provides polymorphic const TypeSubstitution * env for the
     52// | WithConstTypeSubstitution - provides polymorphic const TypeSubstitution * typeSubs for the
    5353//                           current expression
    5454// | WithStmtsToAdd        - provides the ability to insert statements before or after the current
     
    6767// | WithSymbolTable       - provides symbol table functionality
    6868// | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
     69//
     70// Other Special Members:
     71// | result                - Either a method that takes no parameters or a field. If a method (or
     72//                           callable field) get_result calls it, otherwise the value is returned.
    6973//-------------------------------------------------------------------------------------------------
    7074template< typename core_t >
     
    8993        virtual ~Pass() = default;
    9094
     95        /// Storage for the actual pass.
     96        core_t core;
     97
     98        /// If the core defines a result, call it if possible, otherwise return it.
     99        inline auto get_result() -> decltype( __pass::get_result( core, '0' ) ) {
     100                return __pass::get_result( core, '0' );
     101        }
     102
    91103        /// Construct and run a pass on a translation unit.
    92104        template< typename... Args >
     
    96108        }
    97109
     110        /// Contruct and run a pass on a pointer to extract a value.
     111        template< typename node_type, typename... Args >
     112        static auto read( node_type const * node, Args&&... args ) {
     113                Pass<core_t> visitor( std::forward<Args>( args )... );
     114                node_type const * temp = node->accept( visitor );
     115                assert( temp == node );
     116                return visitor.get_result();
     117        }
     118
     119        // Versions of the above for older compilers.
    98120        template< typename... Args >
    99121        static void run( std::list< ptr<Decl> > & decls ) {
     
    102124        }
    103125
    104         /// Storage for the actual pass
    105         core_t core;
     126        template< typename node_type, typename... Args >
     127        static auto read( node_type const * node ) {
     128                Pass<core_t> visitor;
     129                node_type const * temp = node->accept( visitor );
     130                assert( temp == node );
     131                return visitor.get_result();
     132        }
    106133
    107134        /// Visit function declarations
     
    267294//-------------------------------------------------------------------------------------------------
    268295
    269 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression
    270 
    271296/// If used the visitor will always clone nodes.
    272297struct PureVisitor {};
    273298
     299/// Keep track of the polymorphic const TypeSubstitution * typeSubs for the current expression.
    274300struct WithConstTypeSubstitution {
    275         const TypeSubstitution * env = nullptr;
     301        const TypeSubstitution * typeSubs = nullptr;
    276302};
    277303
  • src/AST/Pass.impl.hpp

    rae2c27a rc76bd34  
    154154                __pedantic_pass_assert( expr );
    155155
    156                 const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);
    157                 if ( env_ptr && expr->env ) {
    158                         *env_ptr = expr->env;
     156                const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
     157                if ( typeSubs_ptr && expr->env ) {
     158                        *typeSubs_ptr = expr->env;
    159159                }
    160160
     
    177177
    178178                // These may be modified by subnode but most be restored once we exit this statemnet.
    179                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( core, 0) );
     179                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
    180180                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    181181                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    465465                        __pass::symtab::addId( core, 0, func );
    466466                        VISIT(
     467                                // parameter declarations are now directly here
     468                                maybe_accept( node, &FunctionDecl::params );
     469                                maybe_accept( node, &FunctionDecl::returns );
     470                                // foralls are still in function type
    467471                                maybe_accept( node, &FunctionDecl::type );
    468472                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
     
    14881492
    14891493                // These may be modified by subnode but most be restored once we exit this statemnet.
    1490                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) );
     1494                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::typeSubs( core, 0 ) );
    14911495                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    14921496                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
  • src/AST/Pass.proto.hpp

    rae2c27a rc76bd34  
    236236
    237237        // List of fields and their expected types
    238         FIELD_PTR( env, const ast::TypeSubstitution * )
     238        FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
    239239        FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
    240240        FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
     
    421421
    422422        } // namespace forall
     423
     424        template<typename core_t>
     425        static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
     426                return core.result();
     427        }
     428
     429        template<typename core_t>
     430        static inline auto get_result( core_t & core, int ) -> decltype( core.result ) {
     431                return core.result;
     432        }
     433
     434        template<typename core_t>
     435        static inline void get_result( core_t &, long ) {}
    423436} // namespace __pass
    424437} // namespace ast
  • src/AST/Print.cpp

    rae2c27a rc76bd34  
    270270        }
    271271
    272         void preprint( const ast::ReferenceToType * node ) {
     272        void preprint( const ast::BaseInstType * node ) {
    273273                print( node->forall );
    274274                print( node->attributes );
  • src/AST/SymbolTable.cpp

    rae2c27a rc76bd34  
    313313                if ( ! expr->result ) continue;
    314314                const Type * resTy = expr->result->stripReferences();
    315                 auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );
     315                auto aggrType = dynamic_cast< const BaseInstType * >( resTy );
    316316                assertf( aggrType, "WithStmt expr has non-aggregate type: %s",
    317317                        toString( expr->result ).c_str() );
     
    335335}
    336336
     337/*
    337338void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    338339        addTypes( ftype->forall );
     
    340341        addIds( ftype->params );
    341342}
     343*/
    342344
    343345void SymbolTable::lazyInitScope() {
     
    368370                assert( ! params.empty() );
    369371                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    370                 const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     372                const Type * base = InitTweak::getPointerBase( params.front() );
    371373                assert( base );
    372374                return Mangle::mangle( base );
     
    654656                        if ( dwt->name == "" ) {
    655657                                const Type * t = dwt->get_type()->stripReferences();
    656                                 if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {
     658                                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    657659                                        if ( ! dynamic_cast<const StructInstType *>(rty)
    658660                                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
  • src/AST/SymbolTable.hpp

    rae2c27a rc76bd34  
    145145
    146146        /// convenience function for adding all of the declarations in a function type to the indexer
    147         void addFunctionType( const FunctionType * ftype );
     147        // void addFunctionType( const FunctionType * ftype );
    148148
    149149private:
  • src/AST/Type.cpp

    rae2c27a rc76bd34  
    102102// --- FunctionType
    103103
     104
    104105FunctionType::FunctionType( const FunctionType & o )
    105106: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     
    112113
    113114namespace {
    114         bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
     115        bool containsTtype( const std::vector<ptr<Type>> & l ) {
    115116                if ( ! l.empty() ) {
    116                         return Tuples::isTtype( l.back()->get_type() );
     117                        return Tuples::isTtype( l.back() );
    117118                }
    118119                return false;
     
    124125}
    125126
    126 // --- ReferenceToType
    127 
    128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     127// --- BaseInstType
     128
     129void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {
    129130        ParameterizedType::initWithSub( o, sub ); // initialize substitution
    130131        params = sub.core( o.params );            // apply to parameters
    131132}
    132133
    133 ReferenceToType::ReferenceToType( const ReferenceToType & o )
     134BaseInstType::BaseInstType( const BaseInstType & o )
    134135: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
    135136  hoistType( o.hoistType ) {
     
    138139}
    139140
    140 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
     141std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const {
    141142        assertf( aggr(), "Must have aggregate to perform lookup" );
    142143
     
    153154SueInstType<decl_t>::SueInstType(
    154155        const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    155 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     156: BaseInstType( b->name, q, move(as) ), base( b ) {}
    156157
    157158template<typename decl_t>
     
    168169TraitInstType::TraitInstType(
    169170        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     171: BaseInstType( b->name, q, move(as) ), base( b ) {}
    171172
    172173// --- TypeInstType
    173174
    174175TypeInstType::TypeInstType( const TypeInstType & o )
    175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
     176: BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
    176177        Pass< ForallSubstitutor > sub;
    177178        initWithSub( o, sub );      // initialize substitution
  • src/AST/Type.hpp

    rae2c27a rc76bd34  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304         std::vector<ptr<DeclWithType>> returns;
    305         std::vector<ptr<DeclWithType>> params;
     304//      std::vector<ptr<DeclWithType>> returns;
     305//      std::vector<ptr<DeclWithType>> params;
     306
     307        std::vector<ptr<Type>> returns;
     308        std::vector<ptr<Type>> params;
    306309
    307310        /// Does the function accept a variable number of arguments following the arguments specified
     
    329332
    330333/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    331 class ReferenceToType : public ParameterizedType {
     334class BaseInstType : public ParameterizedType {
    332335protected:
    333336        /// Initializes forall and parameters based on substitutor
    334         void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
     337        void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub );
    335338public:
    336339        std::vector<ptr<Expr>> params;
     
    338341        bool hoistType = false;
    339342
    340         ReferenceToType(
     343        BaseInstType(
    341344                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    342345        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    343346
    344         ReferenceToType( const ReferenceToType & o );
     347        BaseInstType( const BaseInstType & o );
    345348
    346349        /// Gets aggregate declaration this type refers to
     
    350353
    351354private:
    352         virtual ReferenceToType * clone() const override = 0;
     355        virtual BaseInstType * clone() const override = 0;
    353356        MUTATE_FRIEND
    354357};
     
    356359// Common implementation for the SUE instance types. Not to be used directly.
    357360template<typename decl_t>
    358 class SueInstType final : public ReferenceToType {
     361class SueInstType final : public BaseInstType {
    359362public:
    360363        using base_type = decl_t;
     
    363366        SueInstType(
    364367                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    365         : ReferenceToType( n, q, std::move(as) ), base() {}
     368        : BaseInstType( n, q, std::move(as) ), base() {}
    366369
    367370        SueInstType(
     
    388391
    389392/// An instance of a trait type.
    390 class TraitInstType final : public ReferenceToType {
     393class TraitInstType final : public BaseInstType {
    391394public:
    392395        readonly<TraitDecl> base;
     
    394397        TraitInstType(
    395398                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    396         : ReferenceToType( n, q, std::move(as) ), base() {}
     399        : BaseInstType( n, q, std::move(as) ), base() {}
    397400
    398401        TraitInstType(
     
    411414
    412415/// instance of named type alias (typedef or variable)
    413 class TypeInstType final : public ReferenceToType {
     416class TypeInstType final : public BaseInstType {
    414417public:
    415418        readonly<TypeDecl> base;
     
    419422                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    420423                std::vector<ptr<Attribute>> && as = {} )
    421         : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     424        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    422425        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
    423426                std::vector<ptr<Attribute>> && as = {} )
    424         : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     427        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
    425428
    426429        TypeInstType( const TypeInstType & o );
  • src/AST/TypeSubstitution.cpp

    rae2c27a rc76bd34  
    176176}
    177177
    178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
     178void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) {
    179179        GuardValue( boundVars );
    180180        // bind type variables from forall-qualifiers
  • src/AST/TypeSubstitution.hpp

    rae2c27a rc76bd34  
    169169                void previsit( const ParameterizedType * type );
    170170                /// Records type variable bindings from forall-statements and instantiations of generic types
    171                 void handleAggregateType( const ReferenceToType * type );
     171                void handleAggregateType( const BaseInstType * type );
    172172
    173173                void previsit( const StructInstType * aggregateUseType );
  • src/Common/Stats/Stats.cc

    rae2c27a rc76bd34  
    3535        }
    3636
     37        namespace ResolveTime {
     38                bool enabled = false;
     39        }
     40
    3741        struct {
    3842                const char * const opt;
     
    4347                { "heap"    , Heap::enabled },
    4448                { "time"    , Time::enabled },
     49                { "resolve" , ResolveTime::enabled },
    4550        };
    4651
  • src/Common/module.mk

    rae2c27a rc76bd34  
    2222      Common/ErrorObjects.h \
    2323      Common/Eval.cc \
     24      Common/Examine.cc \
     25      Common/Examine.h \
    2426      Common/FilterCombos.h \
    2527      Common/Indenter.h \
     
    3840      Common/Stats/Heap.cc \
    3941      Common/Stats/Heap.h \
     42      Common/Stats/ResolveTime.cc \
     43      Common/Stats/ResolveTime.h \
    4044      Common/Stats/Stats.cc \
    4145      Common/Stats/Time.cc \
  • src/Concurrency/Keywords.cc

    rae2c27a rc76bd34  
    1919#include <string>                         // for string, operator==
    2020
     21#include <iostream>
     22
     23#include "Common/Examine.h"               // for isMainFor
    2124#include "Common/PassVisitor.h"           // for PassVisitor
    2225#include "Common/SemanticError.h"         // for SemanticError
     
    3437#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
    3538#include "SynTree/Visitor.h"              // for Visitor, acceptAll
     39#include "Virtual/Tables.h"
    3640
    3741class Attribute;
    3842
    3943namespace Concurrency {
     44        inline static std::string getVTableName( std::string const & exception_name ) {
     45                return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
     46        }
     47
    4048        //=============================================================================================
    4149        // Pass declarations
     
    5462          public:
    5563
    56                 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) :
    57                   type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {}
     64                ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name,
     65                        std::string&& getter_name, std::string&& context_error, std::string&& exception_name,
     66                        bool needs_main, AggregateDecl::Aggregate cast_target ) :
     67                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
     68                  context_error( context_error ), vtable_name( getVTableName( exception_name ) ),
     69                  needs_main( needs_main ), cast_target( cast_target ) {}
    5870
    5971                virtual ~ConcurrentSueKeyword() {}
     
    6375
    6476                void handle( StructDecl * );
     77                void addVtableForward( StructDecl * );
    6578                FunctionDecl * forwardDeclare( StructDecl * );
    6679                ObjectDecl * addField( StructDecl * );
     
    7689                const std::string getter_name;
    7790                const std::string context_error;
     91                const std::string vtable_name;
    7892                bool needs_main;
    7993                AggregateDecl::Aggregate cast_target;
     
    8195                StructDecl   * type_decl = nullptr;
    8296                FunctionDecl * dtor_decl = nullptr;
     97                StructDecl * vtable_decl = nullptr;
    8398        };
    8499
     
    101116                        "get_thread",
    102117                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
     118                        "",
    103119                        true,
    104120                        AggregateDecl::Thread
     
    133149                        "get_coroutine",
    134150                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
     151                        "CoroutineCancelled",
    135152                        true,
    136153                        AggregateDecl::Coroutine
     
    167184                        "get_monitor",
    168185                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
     186                        "",
    169187                        false,
    170188                        AggregateDecl::Monitor
     
    198216                        "get_generator",
    199217                        "Unable to find builtin type $generator\n",
     218                        "",
    200219                        true,
    201220                        AggregateDecl::Generator
     
    231250
    232251        private:
    233                 DeclarationWithType * is_main( FunctionDecl * );
    234252                bool is_real_suspend( FunctionDecl * );
    235253
     
    359377                        handle( decl );
    360378                }
     379                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     380                        vtable_decl = decl;
     381                }
     382                // Might be able to get ride of is target.
     383                assert( is_target(decl) == (cast_target == decl->kind) );
    361384                return decl;
    362385        }
    363386
    364387        DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
    365                 if( !type_decl ) return decl;
    366                 if( !CodeGen::isDestructor( decl->name ) ) return decl;
    367 
    368                 auto params = decl->type->parameters;
    369                 if( params.size() != 1 ) return decl;
    370 
    371                 auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() );
    372                 if( !type ) return decl;
    373 
    374                 auto stype = dynamic_cast<StructInstType*>( type->base );
    375                 if( !stype ) return decl;
    376                 if( stype->baseStruct != type_decl ) return decl;
    377 
    378                 if( !dtor_decl ) dtor_decl = decl;
     388                if ( type_decl && isDestructorFor( decl, type_decl ) )
     389                        dtor_decl = decl;
     390                else if ( vtable_name.empty() )
     391                        ;
     392                else if ( auto param = isMainFor( decl, cast_target ) ) {
     393                        // This should never trigger.
     394                        assert( vtable_decl );
     395                        // Should be safe because of isMainFor.
     396                        StructInstType * struct_type = static_cast<StructInstType *>(
     397                                static_cast<ReferenceType *>( param->get_type() )->base );
     398                        assert( struct_type );
     399
     400                        declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
     401                                new TypeExpr( struct_type->clone() ),
     402                        }, struct_type, nullptr ) );
     403                }
     404
    379405                return decl;
    380406        }
     
    400426                if( !dtor_decl ) SemanticError( decl, context_error );
    401427
     428                addVtableForward( decl );
    402429                FunctionDecl * func = forwardDeclare( decl );
    403430                ObjectDecl * field = addField( decl );
    404431                addRoutines( field, func );
     432        }
     433
     434        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
     435                if ( vtable_decl ) {
     436                        declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
     437                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
     438                        } ) );
     439                // Its only an error if we want a vtable and don't have one.
     440                } else if ( ! vtable_name.empty() ) {
     441                        SemanticError( decl, context_error );
     442                }
    405443        }
    406444
     
    528566        // Suspend keyword implementation
    529567        //=============================================================================================
    530         DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) {
    531                 if(func->name != "main") return nullptr;
    532                 if(func->type->parameters.size() != 1) return nullptr;
    533 
    534                 auto param = func->type->parameters.front();
    535 
    536                 auto type  = dynamic_cast<ReferenceType * >(param->get_type());
    537                 if(!type) return nullptr;
    538 
    539                 auto obj   = dynamic_cast<StructInstType *>(type->base);
    540                 if(!obj) return nullptr;
    541 
    542                 if(!obj->baseStruct->is_generator()) return nullptr;
    543 
    544                 return param;
    545         }
    546 
    547568        bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
    548569                if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
     
    565586
    566587                // Is this the main of a generator?
    567                 auto param = is_main( func );
     588                auto param = isMainFor( func, AggregateDecl::Aggregate::Generator );
    568589                if(!param) return;
    569590
     
    910931                                        {
    911932                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
    912                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
     933                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
     934                                                new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
    913935                                        },
    914936                                        noDesignators,
     
    10331055// tab-width: 4 //
    10341056// End: //
     1057
  • src/GenPoly/InstantiateGeneric.cc

    rae2c27a rc76bd34  
    172172                InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
    173173                /// Set of types which are dtype-only generic (and therefore have static layout)
    174                 ScopedSet< AggregateDecl* > dtypeStatics;
     174                std::set<AggregateDecl *> dtypeStatics;
    175175                /// Namer for concrete types
    176176                UniqueName typeNamer;
     
    505505        void GenericInstantiator::beginScope() {
    506506                instantiations.beginScope();
    507                 dtypeStatics.beginScope();
    508507        }
    509508
    510509        void GenericInstantiator::endScope() {
    511510                instantiations.endScope();
    512                 dtypeStatics.endScope();
    513511        }
    514512
  • src/InitTweak/InitTweak.cc

    rae2c27a rc76bd34  
    10261026                if ( ftype->params.size() != 2 ) return false;
    10271027
    1028                 const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
     1028                const ast::Type * t1 = getPointerBase( ftype->params.front() );
    10291029                if ( ! t1 ) return false;
    1030                 const ast::Type * t2 = ftype->params.back()->get_type();
     1030                const ast::Type * t2 = ftype->params.back();
    10311031
    10321032                return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
  • src/Parser/lex.ll

    rae2c27a rc76bd34  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sat Feb 15 11:05:50 2020
    13  * Update Count     : 737
     12 * Last Modified On : Tue Oct  6 18:15:41 2020
     13 * Update Count     : 743
    1414 */
    1515
     
    6262#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    6363
    64 #ifdef HAVE_KEYWORDS_FLOATXX                                                            // GCC >= 7 => keyword, otherwise typedef
     64#ifdef HAVE_KEYWORDS_FLOATXX                                                    // GCC >= 7 => keyword, otherwise typedef
    6565#define FLOATXX(v) KEYWORD_RETURN(v);
    6666#else
     
    292292__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    293293return                  { KEYWORD_RETURN(RETURN); }
    294         /* resume                       { KEYWORD_RETURN(RESUME); }                             // CFA */
     294 /* resume                      { KEYWORD_RETURN(RESUME); }                             // CFA */
    295295short                   { KEYWORD_RETURN(SHORT); }
    296296signed                  { KEYWORD_RETURN(SIGNED); }
  • src/Parser/parser.yy

    rae2c27a rc76bd34  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 28 12:11:45 2020
    13 // Update Count     : 4500
     12// Last Modified On : Tue Oct  6 18:24:18 2020
     13// Update Count     : 4610
    1414//
    1515
     
    278278%token OTYPE FTYPE DTYPE TTYPE TRAIT                                    // CFA
    279279%token SIZEOF OFFSETOF
    280 // %token RESUME                                                                        // CFA
    281 %token SUSPEND                                                                  // CFA
     280// %token RESUME                                                                                        // CFA
     281%token SUSPEND                                                                                  // CFA
    282282%token ATTRIBUTE EXTENSION                                                              // GCC
    283283%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
     
    329329%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    330330%type<en> comma_expression                              comma_expression_opt
    331 %type<en> argument_expression_list_opt          argument_expression                     default_initialize_opt
     331%type<en> argument_expression_list_opt  argument_expression                     default_initialize_opt
    332332%type<ifctl> if_control_expression
    333333%type<fctl> for_control_expression              for_control_expression_list
     
    370370%type<decl> assertion assertion_list assertion_list_opt
    371371
    372 %type<en>   bit_subrange_size_opt bit_subrange_size
     372%type<en> bit_subrange_size_opt bit_subrange_size
    373373
    374374%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
     
    793793        | '(' aggregate_control '&' ')' cast_expression         // CFA
    794794                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
    795                 // VIRTUAL cannot be opt because of look ahead issues
    796795        | '(' VIRTUAL ')' cast_expression                                       // CFA
    797796                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild< Expression >( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     
    920919        | unary_expression assignment_operator assignment_expression
    921920                {
    922                         if ( $2 == OperKinds::AtAssn ) {
    923                                 SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    924                         } else {
     921//                      if ( $2 == OperKinds::AtAssn ) {
     922//                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
     923//                      } else {
    925924                                $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
    926                         } // if
     925//                      } // if
    927926                }
    928927        | unary_expression '=' '{' initializer_list_opt comma_opt '}'
     
    16761675
    16771676typedef_expression:
    1678                 // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
     1677                // deprecated GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    16791678        TYPEDEF identifier '=' assignment_expression
    16801679                {
    1681                         // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    1682                         SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
     1680                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    16831681                }
    16841682        | typedef_expression pop ',' push identifier '=' assignment_expression
    16851683                {
    1686                         // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    1687                         SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
    1688                 }
    1689         ;
    1690 
    1691 //c_declaration:
    1692 //      declaring_list pop ';'
    1693 //      | typedef_declaration pop ';'
    1694 //      | typedef_expression pop ';'                                            // GCC, naming expression type
    1695 //      | sue_declaration_specifier pop ';'
    1696 //      ;
    1697 //
    1698 //declaring_list:
    1699 //              // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
    1700 //              // storage-class
    1701 //       declarator asm_name_opt initializer_opt
    1702 //              {
    1703 //                      typedefTable.addToEnclosingScope( IDENTIFIER );
    1704 //                      $$ = ( $2->addType( $1 ))->addAsmName( $3 )->addInitializer( $4 );
    1705 //              }
    1706 //      | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    1707 //              {
    1708 //                      typedefTable.addToEnclosingScope( IDENTIFIER );
    1709 //                      $$ = $1->appendList( $1->cloneBaseType( $4->addAsmName( $5 )->addInitializer( $6 ) ) );
    1710 //              }
    1711 //      ;
     1684                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     1685                }
     1686        ;
    17121687
    17131688c_declaration:
     
    17151690                { $$ = distAttr( $1, $2 ); }
    17161691        | typedef_declaration
    1717         | typedef_expression                                                            // GCC, naming expression type
     1692        | typedef_expression                                                            // deprecated GCC, naming expression type
    17181693        | sue_declaration_specifier
    17191694        ;
     
    20942069                { yyy = true; $$ = AggregateDecl::Union; }
    20952070        | EXCEPTION                                                                                     // CFA
    2096                 { yyy = true; $$ = AggregateDecl::Exception; }
     2071                // { yyy = true; $$ = AggregateDecl::Exception; }
     2072                { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    20972073        ;
    20982074
  • src/ResolvExpr/CandidateFinder.cpp

    rae2c27a rc76bd34  
    188188
    189189                        // mark conversion cost and also specialization cost of param type
    190                         const ast::Type * paramType = (*param)->get_type();
     190                        // const ast::Type * paramType = (*param)->get_type();
    191191                        cand->expr = ast::mutate_field_index(
    192192                                appExpr, &ast::ApplicationExpr::args, i,
    193193                                computeExpressionConversionCost(
    194                                         args[i], paramType, symtab, cand->env, convCost ) );
    195                         convCost.decSpec( specCost( paramType ) );
     194                                        args[i], *param, symtab, cand->env, convCost ) );
     195                        convCost.decSpec( specCost( *param ) );
    196196                        ++param;  // can't be in for-loop update because of the continue
    197197                }
     
    698698                        if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
    699699                                // attempt to narrow based on expected target type
    700                                 const ast::Type * returnType = funcType->returns.front()->get_type();
     700                                const ast::Type * returnType = funcType->returns.front();
    701701                                if ( ! unify(
    702702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     
    712712                        std::size_t genStart = 0;
    713713
    714                         for ( const ast::DeclWithType * param : funcType->params ) {
    715                                 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
     714                        // xxx - how to handle default arg after change to ftype representation?
     715                        if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
     716                                if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
     717                                        // function may have default args only if directly calling by name
     718                                        // must use types on candidate however, due to RenameVars substitution
     719                                        auto nParams = funcType->params.size();
     720
     721                                        for (size_t i=0; i<nParams; ++i) {
     722                                                auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
     723                                                if (!instantiateArgument(
     724                                                        funcType->params[i], obj->init, args, results, genStart, symtab)) return;
     725                                        }
     726                                        goto endMatch;
     727                                }
     728                        }
     729                        for ( const auto & param : funcType->params ) {
    716730                                // Try adding the arguments corresponding to the current parameter to the existing
    717731                                // matches
     732                                // no default args for indirect calls
    718733                                if ( ! instantiateArgument(
    719                                         obj->type, obj->init, args, results, genStart, symtab ) ) return;
    720                         }
    721 
     734                                        param, nullptr, args, results, genStart, symtab ) ) return;
     735                        }
     736
     737                        endMatch:
    722738                        if ( funcType->isVarArgs ) {
    723739                                // append any unused arguments to vararg pack
     
    816832                /// Adds aggregate member interpretations
    817833                void addAggMembers(
    818                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     834                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    819835                        const Candidate & cand, const Cost & addedCost, const std::string & name
    820836                ) {
     
    12631279
    12641280                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    1265                         const ast::ReferenceToType * aggInst;
     1281                        const ast::BaseInstType * aggInst;
    12661282                        if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
    12671283                        else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
  • src/ResolvExpr/ConversionCost.cc

    rae2c27a rc76bd34  
    520520                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
    521521        } else {
    522                 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    523                 src->accept( converter );
    524                 return converter.core.cost;
     522                return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
    525523        }
    526524}
     
    563561                        }
    564562                } else {
    565                         ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    566                         src->accept( converter );
    567                         return converter.core.cost;
     563                        return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
    568564                }
    569565        } else {
  • src/ResolvExpr/ConversionCost.h

    rae2c27a rc76bd34  
    8888        static size_t traceId;
    8989        Cost cost;
     90        Cost result() { return cost; }
    9091
    9192        ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
  • src/ResolvExpr/CurrentObject.cc

    rae2c27a rc76bd34  
    594594        class SimpleIterator final : public MemberIterator {
    595595                CodeLocation location;
    596                 readonly< Type > type = nullptr;
     596                const Type * type = nullptr;
    597597        public:
    598598                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
     
    630630        class ArrayIterator final : public MemberIterator {
    631631                CodeLocation location;
    632                 readonly< ArrayType > array = nullptr;
    633                 readonly< Type > base = nullptr;
     632                const ArrayType * array = nullptr;
     633                const Type * base = nullptr;
    634634                size_t index = 0;
    635635                size_t size = 0;
     
    923923
    924924        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    925                 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
     925                if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
    926926                        if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    927927                                return new StructIterator{ loc, sit };
     
    932932                                        dynamic_cast< const EnumInstType * >( type )
    933933                                                || dynamic_cast< const TypeInstType * >( type ),
    934                                         "Encountered unhandled ReferenceToType in createMemberIterator: %s",
     934                                        "Encountered unhandled BaseInstType in createMemberIterator: %s",
    935935                                                toString( type ).c_str() );
    936936                                return new SimpleIterator{ loc, type };
     
    965965                                        DesignatorChain & d = *dit;
    966966                                        PRINT( std::cerr << "____actual: " << t << std::endl; )
    967                                         if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
     967                                        if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
    968968                                                // concatenate identical field names
    969969                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
  • src/ResolvExpr/Resolver.cc

    rae2c27a rc76bd34  
    3838#include "Common/PassVisitor.h"          // for PassVisitor
    3939#include "Common/SemanticError.h"        // for SemanticError
     40#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4041#include "Common/utility.h"              // for ValueGuard, group_iterate
    4142#include "InitTweak/GenInit.h"
     
    965966                /// Finds deleted expressions in an expression tree
    966967                struct DeleteFinder_new final : public ast::WithShortCircuiting {
    967                         const ast::DeletedExpr * delExpr = nullptr;
     968                        const ast::DeletedExpr * result = nullptr;
    968969
    969970                        void previsit( const ast::DeletedExpr * expr ) {
    970                                 if ( delExpr ) { visit_children = false; }
    971                                 else { delExpr = expr; }
     971                                if ( result ) { visit_children = false; }
     972                                else { result = expr; }
    972973                        }
    973974
    974975                        void previsit( const ast::Expr * ) {
    975                                 if ( delExpr ) { visit_children = false; }
     976                                if ( result ) { visit_children = false; }
    976977                        }
    977978                };
     
    980981        /// Check if this expression is or includes a deleted expression
    981982        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    982                 ast::Pass<DeleteFinder_new> finder;
    983                 expr->accept( finder );
    984                 return finder.core.delExpr;
     983                return ast::Pass<DeleteFinder_new>::read( expr );
    985984        }
    986985
     
    11711170                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11721171                ) {
    1173                         return findKindExpression( untyped, symtab );
     1172                        Stats::ResolveTime::start( untyped );
     1173                        auto res = findKindExpression( untyped, symtab );
     1174                        Stats::ResolveTime::stop();
     1175                        return res;
    11741176                }
    11751177        } // anonymous namespace
     
    12211223                template<typename Iter>
    12221224                inline bool nextMutex( Iter & it, const Iter & end ) {
    1223                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
     1225                        while ( it != end && ! (*it)->is_mutex() ) { ++it; }
    12241226                        return it != end;
    12251227                }
     
    12611263                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    12621264                const ast::CatchStmt *       previsit( const ast::CatchStmt * );
     1265                const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
    12631266                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    12641267
     
    14931496
    14941497        const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1495                 // TODO: This will need a fix for the decl/cond scoping problem.
     1498                // Until we are very sure this invarent (ifs that move between passes have thenPart)
     1499                // holds, check it. This allows a check for when to decode the mangling.
     1500                if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
     1501                        assert( ifStmt->thenPart );
     1502                }
     1503                // Encode the catchStmt so the condition can see the declaration.
    14961504                if ( catchStmt->cond ) {
    1497                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1498                         catchStmt = ast::mutate_field(
    1499                                 catchStmt, &ast::CatchStmt::cond,
    1500                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
     1505                        ast::CatchStmt * stmt = mutate( catchStmt );
     1506                        stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );
     1507                        stmt->cond = nullptr;
     1508                        return stmt;
     1509                }
     1510                return catchStmt;
     1511        }
     1512
     1513        const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) {
     1514                // Decode the catchStmt so everything is stored properly.
     1515                const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
     1516                if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
     1517                        assert( ifStmt->cond );
     1518                        assert( ifStmt->elsePart );
     1519                        ast::CatchStmt * stmt = ast::mutate( catchStmt );
     1520                        stmt->cond = ifStmt->cond;
     1521                        stmt->body = ifStmt->elsePart;
     1522                        // ifStmt should be implicately deleted here.
     1523                        return stmt;
    15011524                }
    15021525                return catchStmt;
     
    16151638                                                                // Check if the argument matches the parameter type in the current
    16161639                                                                // scope
    1617                                                                 ast::ptr< ast::Type > paramType = (*param)->get_type();
     1640                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
    16181641                                                                if (
    16191642                                                                        ! unify(
    1620                                                                                 arg->expr->result, paramType, resultEnv, need, have, open,
     1643                                                                                arg->expr->result, *param, resultEnv, need, have, open,
    16211644                                                                                symtab )
    16221645                                                                ) {
     
    16251648                                                                        ss << "candidate function not viable: no known conversion "
    16261649                                                                                "from '";
    1627                                                                         ast::print( ss, (*param)->get_type() );
     1650                                                                        ast::print( ss, *param );
    16281651                                                                        ss << "' to '";
    16291652                                                                        ast::print( ss, arg->expr->result );
  • src/ResolvExpr/SatisfyAssertions.cpp

    rae2c27a rc76bd34  
    318318                                        if ( ! func ) continue;
    319319
    320                                         for ( const ast::DeclWithType * param : func->params ) {
    321                                                 cost.decSpec( specCost( param->get_type() ) );
     320                                        for ( const auto & param : func->params ) {
     321                                                cost.decSpec( specCost( param ) );
    322322                                        }
    323323
  • src/ResolvExpr/SpecCost.cc

    rae2c27a rc76bd34  
    178178                void previsit( const ast::FunctionType * fty ) {
    179179                        int minCount = std::numeric_limits<int>::max();
    180                         updateMinimumPresent( minCount, fty->params, decl_type );
    181                         updateMinimumPresent( minCount, fty->returns, decl_type );
     180                        updateMinimumPresent( minCount, fty->params, type_deref );
     181                        updateMinimumPresent( minCount, fty->returns, type_deref );
    182182                        // Add another level to minCount if set.
    183183                        count = toNoneOrInc( minCount );
  • src/ResolvExpr/Unify.cc

    rae2c27a rc76bd34  
    395395
    396396        template< typename Iterator1, typename Iterator2 >
    397         bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    398398                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    399399                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    489489                                        || flatOther->isTtype()
    490490                        ) {
    491                                 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    492                                         if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     491                                if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     492                                        if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    493493
    494494                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    784784
    785785                /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
    787                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::Type > > flattenList(
     787                        const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    788788                ) {
    789                         std::vector< ast::ptr< ast::DeclWithType > > dst;
     789                        std::vector< ast::ptr< ast::Type > > dst;
    790790                        dst.reserve( src.size() );
    791                         for ( const ast::DeclWithType * d : src ) {
     791                        for ( const auto & d : src ) {
    792792                                ast::Pass<TtypeExpander_new> expander{ env };
    793793                                // TtypeExpander pass is impure (may mutate nodes in place)
    794794                                // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::DeclWithType> dc = d->accept(expander);
    796                                 auto types = flatten( dc->get_type() );
     795                                ast::ptr<ast::Type> dc = d->accept(expander);
     796                                auto types = flatten( dc );
    797797                                for ( ast::ptr< ast::Type > & t : types ) {
    798798                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    803803                                        // requirements than a non-mutex function
    804804                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t } );
     805                                        dst.emplace_back( t );
    806806                                }
    807807                        }
     
    811811                /// Creates a tuple type based on a list of DeclWithType
    812812                template< typename Iter >
    813                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     813                static ast::ptr< ast::Type > tupleFromTypes( Iter crnt, Iter end ) {
    814814                        std::vector< ast::ptr< ast::Type > > types;
    815815                        while ( crnt != end ) {
    816816                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817817                                // that this results in a flat tuple
    818                                 flatten( (*crnt)->get_type(), types );
     818                                flatten( *crnt, types );
    819819
    820820                                ++crnt;
     
    825825
    826826                template< typename Iter >
    827                 static bool unifyDeclList(
     827                static bool unifyTypeList(
    828828                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    829829                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    831831                ) {
    832832                        while ( crnt1 != end1 && crnt2 != end2 ) {
    833                                 const ast::Type * t1 = (*crnt1)->get_type();
    834                                 const ast::Type * t2 = (*crnt2)->get_type();
     833                                const ast::Type * t1 = *crnt1;
     834                                const ast::Type * t2 = *crnt2;
    835835                                bool isTuple1 = Tuples::isTtype( t1 );
    836836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840840                                        // combine remainder of list2, then unify
    841841                                        return unifyExact(
    842                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    843843                                                noWiden(), symtab );
    844844                                } else if ( ! isTuple1 && isTuple2 ) {
    845845                                        // combine remainder of list1, then unify
    846846                                        return unifyExact(
    847                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    848848                                                noWiden(), symtab );
    849849                                }
     
    860860                        if ( crnt1 != end1 ) {
    861861                                // try unifying empty tuple with ttype
    862                                 const ast::Type * t1 = (*crnt1)->get_type();
     862                                const ast::Type * t1 = *crnt1;
    863863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864864                                return unifyExact(
    865                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    866866                                        noWiden(), symtab );
    867867                        } else if ( crnt2 != end2 ) {
    868868                                // try unifying empty tuple with ttype
    869                                 const ast::Type * t2 = (*crnt2)->get_type();
     869                                const ast::Type * t2 = *crnt2;
    870870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871871                                return unifyExact(
    872                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    873873                                        noWiden(), symtab );
    874874                        }
     
    877877                }
    878878
    879                 static bool unifyDeclList(
    880                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    881                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     879                static bool unifyTypeList(
     880                        const std::vector< ast::ptr< ast::Type > > & list1,
     881                        const std::vector< ast::ptr< ast::Type > > & list2,
    882882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884884                ) {
    885                         return unifyDeclList(
     885                        return unifyTypeList(
    886886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887887                                symtab );
     
    928928                        ) return;
    929929
    930                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    931                         if ( ! unifyDeclList(
     930                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     931                        if ( ! unifyTypeList(
    932932                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    933933
     
    12321232        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12331233                if ( func->returns.empty() ) return new ast::VoidType{};
    1234                 if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
     1234                if ( func->returns.size() == 1 ) return func->returns[0];
    12351235
    12361236                std::vector<ast::ptr<ast::Type>> tys;
    1237                 for ( const ast::DeclWithType * decl : func->returns ) {
    1238                         tys.emplace_back( decl->get_type() );
     1237                for ( const auto & decl : func->returns ) {
     1238                        tys.emplace_back( decl );
    12391239                }
    12401240                return new ast::TupleType{ std::move(tys) };
  • src/SymTab/Mangler.cc

    rae2c27a rc76bd34  
    437437                  private:
    438438                        void mangleDecl( const ast::DeclWithType *declaration );
    439                         void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
     439                        void mangleRef( const ast::BaseInstType *refType, std::string prefix );
    440440
    441441                        void printQualifiers( const ast::Type *type );
     
    551551                        GuardValue( inFunctionType );
    552552                        inFunctionType = true;
    553                         std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
    554                         if (returnTypes.empty()) mangleName << Encoding::void_t;
    555                         else accept_each( returnTypes, *visitor );
     553                        if (functionType->returns.empty()) mangleName << Encoding::void_t;
     554                        else accept_each( functionType->returns, *visitor );
    556555                        mangleName << "_";
    557                         std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
    558                         accept_each( paramTypes, *visitor );
     556                        accept_each( functionType->params, *visitor );
    559557                        mangleName << "_";
    560558                }
    561559
    562                 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
     560                void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) {
    563561                        printQualifiers( refType );
    564562
  • src/SymTab/Validate.cc

    rae2c27a rc76bd34  
    960960        }
    961961
     962        static bool isNonParameterAttribute( Attribute * attr ) {
     963                static const std::vector<std::string> bad_names = {
     964                        "aligned", "__aligned__",
     965                };
     966                for ( auto name : bad_names ) {
     967                        if ( name == attr->name ) {
     968                                return true;
     969                        }
     970                }
     971                return false;
     972        }
     973
    962974        Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
    963975                // instances of typedef types will come here. If it is an instance
     
    968980                        ret->location = typeInst->location;
    969981                        ret->get_qualifiers() |= typeInst->get_qualifiers();
    970                         // attributes are not carried over from typedef to function parameters/return values
    971                         if ( ! inFunctionType ) {
    972                                 ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
    973                         } else {
    974                                 deleteAll( ret->attributes );
    975                                 ret->attributes.clear();
    976                         }
     982                        // GCC ignores certain attributes if they arrive by typedef, this mimics that.
     983                        if ( inFunctionType ) {
     984                                ret->attributes.remove_if( isNonParameterAttribute );
     985                        }
     986                        ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
    977987                        // place instance parameters on the typedef'd type
    978988                        if ( ! typeInst->parameters.empty() ) {
     
    13741384        /// Replaces enum types by int, and function/array types in function parameter and return
    13751385        /// lists by appropriate pointers
     1386        /*
    13761387        struct EnumAndPointerDecay_new {
    13771388                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     
    14241435                }
    14251436        };
     1437        */
    14261438
    14271439        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     
    15081520                }
    15091521
    1510                 void checkGenericParameters( const ast::ReferenceToType * inst ) {
     1522                void checkGenericParameters( const ast::BaseInstType * inst ) {
    15111523                        for ( const ast::Expr * param : inst->params ) {
    15121524                                if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
     
    18271839const ast::Type * validateType(
    18281840                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1829         ast::Pass< EnumAndPointerDecay_new > epc;
     1841        // ast::Pass< EnumAndPointerDecay_new > epc;
    18301842        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    18311843        ast::Pass< ForallPointerDecay_new > fpd{ loc };
    18321844
    1833         return type->accept( epc )->accept( lrt )->accept( fpd );
     1845        return type->accept( lrt )->accept( fpd );
    18341846}
    18351847
  • src/Virtual/module.mk

    rae2c27a rc76bd34  
    1515###############################################################################
    1616
    17 SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h
     17SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h \
     18        Virtual/Tables.cc Virtual/Tables.h
     19
     20SRCDEMANGLE += Virtual/Tables.cc
  • tests/.expect/array.txt

    rae2c27a rc76bd34  
     1array.cfa: In function '_X4mainFi___1':
     2array.cfa:55:9: note: #pragma message: Compiled
  • tests/.expect/cast.txt

    rae2c27a rc76bd34  
     1cast.cfa: In function '_X4mainFi_iPPKc__1':
     2cast.cfa:18:9: note: #pragma message: Compiled
  • tests/.expect/enum.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/expression.txt

    rae2c27a rc76bd34  
     1expression.cfa: In function '_X4mainFi___1':
     2expression.cfa:89:9: note: #pragma message: Compiled
  • tests/.expect/forall.txt

    rae2c27a rc76bd34  
     1forall.cfa: In function '_X4mainFi___1':
     2forall.cfa:218:9: note: #pragma message: Compiled
  • tests/.expect/heap.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/identFuncDeclarator.txt

    rae2c27a rc76bd34  
     1identFuncDeclarator.cfa: In function '_X4mainFi___1':
     2identFuncDeclarator.cfa:116:9: note: #pragma message: Compiled
  • tests/.expect/identParamDeclarator.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/labelledExit.txt

    rae2c27a rc76bd34  
     1labelledExit.cfa: In function '_X4mainFi_iPPKc__1':
     2labelledExit.cfa:183:9: note: #pragma message: Compiled
  • tests/.expect/limits.txt

    rae2c27a rc76bd34  
     1limits.cfa: In function '_X4mainFi_iPPKc__1':
     2limits.cfa:151:9: note: #pragma message: Compiled
  • tests/.expect/maybe.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/nested-types.txt

    rae2c27a rc76bd34  
     1nested-types.cfa: In function '_X4mainFi___1':
     2nested-types.cfa:102:9: note: #pragma message: Compiled
  • tests/.expect/numericConstants.txt

    rae2c27a rc76bd34  
     1numericConstants.cfa: In function '_X4mainFi___1':
     2numericConstants.cfa:68:9: note: #pragma message: Compiled
  • tests/.expect/operators.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/result.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/stdincludes.txt

    rae2c27a rc76bd34  
     1stdincludes.cfa: In function '_X4mainFi___1':
     2stdincludes.cfa:52:9: note: #pragma message: Compiled
  • tests/.expect/switch.txt

    rae2c27a rc76bd34  
     1switch.cfa: In function '_X4mainFi___1':
     2switch.cfa:105:9: note: #pragma message: Compiled
  • tests/.expect/typedefRedef-ERR1.txt

    rae2c27a rc76bd34  
    11typedefRedef.cfa:4:1 error: Cannot redefine typedef: Foo
    2 typedefRedef.cfa:60:1 error: Cannot redefine typedef: ARR
     2typedefRedef.cfa:59:1 error: Cannot redefine typedef: ARR
  • tests/.expect/typedefRedef.txt

    rae2c27a rc76bd34  
     1typedefRedef.cfa: In function '_X4mainFi___1':
     2typedefRedef.cfa:71:9: note: #pragma message: Compiled
  • tests/.expect/typeof.txt

    rae2c27a rc76bd34  
     1done
  • tests/.expect/variableDeclarator.txt

    rae2c27a rc76bd34  
     1variableDeclarator.cfa: In function '_X4mainFi_iPPKc__1':
     2variableDeclarator.cfa:182:9: note: #pragma message: Compiled
  • tests/.expect/voidPtr.txt

    rae2c27a rc76bd34  
     1done
  • tests/Makefile.am

    rae2c27a rc76bd34  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Tue Nov 20 11:18:51 2018
    14 ## Update Count     : 68
     13## Last Modified On : Sun Sep 27 19:01:41 2020
     14## Update Count     : 84
    1515###############################################################################
    1616
     
    3838# since automake doesn't have support for CFA we have to
    3939AM_CFLAGS = $(if $(test), 2> $(test), ) \
     40        -fdebug-prefix-map=$(abspath ${abs_srcdir})= \
     41        -fdebug-prefix-map=/tmp= \
     42        -fno-diagnostics-show-caret \
    4043        -g \
    4144        -Wall \
     
    5053
    5154# adjust CC to current flags
    52 CC = $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     55CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
    5356CFACC = $(CC)
    5457
     
    5861# adjusted CC but without the actual distcc call
    5962CFACCLOCAL = $(if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     63CFACCLINK = $(CFACCLOCAL) -quiet $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'))
    6064
    6165PRETTY_PATH=mkdir -p $(dir $(abspath ${@})) && cd ${srcdir} &&
     
    110114% : %.cfa $(CFACCBIN)
    111115        $(CFACOMPILETEST) -c -o $(abspath ${@}).o
    112         $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})
     116        $(CFACCLINK) ${@}.o -o $(abspath ${@})
     117        rm $(abspath ${@}).o
    113118
    114119# implicit rule for c++ test
     
    129134        $(CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@})
    130135
    131 # Use for tests where the make command is expected to succeed but the expected.txt should be compared to stderr
    132 EXPECT_STDERR = builtins/sync warnings/self-assignment
    133 $(EXPECT_STDERR): % : %.cfa $(CFACCBIN)
    134         $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
    135 
    136136#------------------------------------------------------------------------------
    137137# CUSTOM TARGET
    138138#------------------------------------------------------------------------------
     139# tests that just validate syntax and compiler output should be compared to stderr
     140CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})
     141
     142SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \
     143        limits nested-types stdincludes cast labelledExit array builtins/sync warnings/self-assignment
     144$(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)
     145        $(CFACOMPILE_SYNTAX)
     146        $(if $(test), cp $(test) $(abspath ${@}), )
     147
    139148# expected failures
    140 # use custom target since they require a custom define and custom dependencies
     149# use custom target since they require a custom define *and* have a name that doesn't match the file
    141150alloc-ERROR : alloc.cfa $(CFACCBIN)
    142         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     151        $(CFACOMPILE_SYNTAX) -DERR1
     152        -cp $(test) $(abspath ${@})
    143153
    144154typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN)
    145         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     155        $(CFACOMPILE_SYNTAX) -DERR1
     156        -cp $(test) $(abspath ${@})
    146157
    147158nested-types-ERR1 : nested-types.cfa $(CFACCBIN)
    148         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     159        $(CFACOMPILE_SYNTAX) -DERR1
     160        -cp $(test) $(abspath ${@})
    149161
    150162nested-types-ERR2 : nested-types.cfa $(CFACCBIN)
    151         $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
     163        $(CFACOMPILE_SYNTAX) -DERR2
     164        -cp $(test) $(abspath ${@})
    152165
    153166raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN)
    154         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     167        $(CFACOMPILE_SYNTAX) -DERR1
     168        -cp $(test) $(abspath ${@})
    155169
    156170raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN)
    157         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     171        $(CFACOMPILE_SYNTAX) -DERR1
     172        -cp $(test) $(abspath ${@})
    158173
    159174raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN)
    160         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     175        $(CFACOMPILE_SYNTAX) -DERR1
     176        -cp $(test) $(abspath ${@})
    161177
    162178raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN)
    163         $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
     179        $(CFACOMPILE_SYNTAX) -DERR2
     180        -cp $(test) $(abspath ${@})
    164181
    165182# Exception Tests
     
    170187        $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})
    171188
     189# Linking tests
     190# Meta tests to make sure we see linking errors (can't compile with -O2 since it may multiply number of calls)
     191linking/linkerror : linking/linkerror.cfa $(CFACCBIN)
     192        $(CFACOMPILETEST) -O0 -c -o $(abspath ${@}).o
     193        $(CFACCLINK)  -O0 ${@}.o -o $(abspath ${@})
     194        rm $(abspath ${@}).o
     195
    172196#------------------------------------------------------------------------------
    173197# Other targets
  • tests/alloc2.cfa

    rae2c27a rc76bd34  
    1313void test_base( void * ip, size_t size, size_t align) {
    1414        tests_total += 1;
     15//      printf("DEBUG: starting test %d\n", tests_total);
    1516        bool passed = (malloc_size(ip) == size) && (malloc_usable_size(ip) >= size) && (malloc_alignment(ip) == align) && ((uintptr_t)ip % align  == 0);
    1617        if (!passed) {
     
    1819                tests_failed += 1;
    1920        }
     21//      printf("DEBUG: done test %d\n", tests_total);
    2022}
    2123
    2224void test_fill( void * ip_, size_t start, size_t end, char fill) {
    2325        tests_total += 1;
     26//      printf("DEBUG: starting test %d\n", tests_total);
    2427        bool passed = true;
    2528        char * ip = (char *) ip_;
     
    2932                tests_failed += 1;
    3033        }
     34//      printf("DEBUG: done test %d\n", tests_total);
    3135}
    3236
    3337void test_fill( void * ip_, size_t start, size_t end, int fill) {
    3438        tests_total += 1;
     39//      printf("DEBUG: starting test %d\n", tests_total);
    3540        bool passed = true;
    3641        int * ip = (int *) ip_;
     
    4045                tests_failed += 1;
    4146        }
     47//      printf("DEBUG: done test %d\n", tests_total);
    4248}
    4349
    4450void test_fill( void * ip_, size_t start, size_t end, int * fill) {
    4551        tests_total += 1;
     52//      printf("DEBUG: starting test %d\n", tests_total);
    4653        bool passed = (memcmp((void*)((uintptr_t)ip_ + start), (void*)fill, end) == 0);
    4754        if (!passed) {
     
    4956                tests_failed += 1;
    5057        }
     58//      printf("DEBUG: done test %d\n", tests_total);
    5159}
    5260
    5361void test_fill( void * ip_, size_t start, size_t end, T1 fill) {
    5462        tests_total += 1;
     63//      printf("DEBUG: starting test %d\n", tests_total);
    5564        bool passed = true;
    5665        T1 * ip = (T1 *) ip_;
     
    6069                tests_failed += 1;
    6170        }
     71//      printf("DEBUG: done test %d\n", tests_total);
    6272}
    6373
    6474void test_fill( void * ip_, size_t start, size_t end, T1 * fill) {
    6575        tests_total += 1;
     76//      printf("DEBUG: starting test %d\n", tests_total);
    6677        bool passed = (memcmp((void*)((uintptr_t)ip_ + start), (void*)fill, end) == 0);
    6778        if (!passed) {
     
    6980                tests_failed += 1;
    7081        }
     82//      printf("DEBUG: done test %d\n", tests_total);
    7183}
    7284
    7385void test_use( int * ip, size_t dim) {
    7486        tests_total += 1;
     87//      printf("DEBUG: starting test %d\n", tests_total);
    7588        bool passed = true;
    7689        for (i; 0 ~ dim) ip[i] = 0xdeadbeef;
     
    8093                tests_failed += 1;
    8194        }
     95//      printf("DEBUG: done test %d\n", tests_total);
    8296}
    8397
    8498void test_use( T1 * ip, size_t dim) {
    8599        tests_total += 1;
     100//      printf("DEBUG: starting test %d\n", tests_total);
    86101        bool passed = true;
    87102        for (i; 0 ~ dim) ip[i].data = 0xdeadbeef;
     
    91106                tests_failed += 1;
    92107        }
     108//      printf("DEBUG: done test %d\n", tests_total);
    93109}
    94110
  • tests/array.cfa

    rae2c27a rc76bd34  
    1 //                               -*- Mode: C -*- 
    2 // 
     1//                               -*- Mode: C -*-
     2//
    33// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    44//
    55// The contents of this file are covered under the licence agreement in the
    66// file "LICENCE" distributed with Cforall.
    7 // 
     7//
    88// array.cfa -- test array declarations
    9 // 
     9//
    1010// Author           : Peter A. Buhr
    1111// Created On       : Tue Feb 19 21:18:06 2019
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Tue Feb 19 21:18:46 2019
    14 // Update Count     : 1
    15 // 
     13// Last Modified On : Sun Sep 27 09:05:40 2020
     14// Update Count     : 4
     15//
    1616
    17 int a1[];
     17int a1[0];
    1818//int a2[*];
    1919//double a4[3.0];
    2020
    21 int m1[][3];
     21int m1[0][3];
    2222//int m2[*][*];
    2323int m4[3][3];
     
    4949}
    5050
    51 int main() {}
     51int main() {
     52        #if !defined(NO_COMPILED_PRAGMA)
     53                #pragma message( "Compiled" )   // force non-empty .expect file
     54        #endif
     55}
    5256
    5357// Local Variables: //
  • tests/builtins/.expect/sync.txt

    rae2c27a rc76bd34  
     1builtins/sync.cfa: In function '_X4mainFi___1':
     2builtins/sync.cfa:358:9: note: #pragma message: Compiled
  • tests/builtins/sync.cfa

    rae2c27a rc76bd34  
    6666        #if defined(__SIZEOF_INT128__)
    6767        { __int128 ret; ret = __sync_fetch_and_nand(vplll, vlll); }
    68         { __int128 ret; ret = __sync_fetch_and_nand_16(vplll, vlll); }
    6968        #endif
    7069
     
    355354
    356355int main() {
    357         return 0;
     356        #pragma message( "Compiled" )                   // force non-empty .expect file
    358357}
  • tests/cast.cfa

    rae2c27a rc76bd34  
    1313
    1414//Dummy main
    15 int main(int argc, char const *argv[])
    16 {
    17         return 0;
     15int main( int argc, char const * argv[] ) {
     16        #pragma message( "Compiled" )                   // force non-empty .expect file
    1817}
  • tests/concurrent/.expect/cluster.txt

    rae2c27a rc76bd34  
     1done
  • tests/concurrent/cluster.cfa

    rae2c27a rc76bd34  
    3232                }
    3333        }
    34         return 0;
     34        printf( "done\n" );                             // non-empty .expect file
    3535}
  • tests/concurrent/examples/.expect/datingService.txt

    rae2c27a rc76bd34  
     1done
  • tests/concurrent/examples/datingService.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Mon Oct 30 12:56:20 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 11:32:34 2019
    13 // Update Count     : 38
     12// Last Modified On : Sun Sep 27 15:42:25 2020
     13// Update Count     : 40
    1414//
    1515
     
    108108                if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort();
    109109        } // for
     110
     111        printf( "done\n" );                                                                     // non-empty .expect file
    110112} // main
    111113
  • tests/concurrent/futures/.expect/basic.txt

    rae2c27a rc76bd34  
     1done
  • tests/concurrent/futures/basic.cfa

    rae2c27a rc76bd34  
    9191                }
    9292        }
     93        printf( "done\n" );                             // non-empty .expect file
     94
    9395}
  • tests/concurrent/park/.expect/force_preempt.txt

    rae2c27a rc76bd34  
     1done
  • tests/concurrent/park/.expect/start_parked.txt

    rae2c27a rc76bd34  
     1done
  • tests/concurrent/park/contention.cfa

    rae2c27a rc76bd34  
    2121                if(blocked[idx]) {
    2222                        Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST);
    23                         unpark( *thrd __cfaabi_dbg_ctx2 );
     23                        unpark( *thrd );
    2424                } else {
    2525                        Thread * thrd = __atomic_exchange_n(&blocked[idx], &this, __ATOMIC_SEQ_CST);
    26                         unpark( *thrd __cfaabi_dbg_ctx2 );
    27                         park( __cfaabi_dbg_ctx );
     26                        unpark( *thrd );
     27                        park();
    2828                }
    2929        }
     
    4141                        int idx = myrand() % blocked_size;
    4242                        Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST);
    43                         unpark( *thrd __cfaabi_dbg_ctx2 );
     43                        unpark( *thrd );
    4444                        yield( myrand() % 20 );
    4545                }
  • tests/concurrent/park/force_preempt.cfa

    rae2c27a rc76bd34  
    3030
    3131                // Unpark this thread, don't force a yield
    32                 unpark( this __cfaabi_dbg_ctx2 );
     32                unpark( this );
    3333                assert(mask == 0xCAFEBABA);
    3434
     
    4343                // Park this thread,
    4444                assert(mask == (id_hash ^ 0xCAFEBABA));
    45                 park( __cfaabi_dbg_ctx );
     45                park();
    4646                assert(mask == (id_hash ^ 0xCAFEBABA));
    4747
     
    5757                Waiter waiters[5];
    5858        }
     59        printf( "done\n" );                             // non-empty .expect file
    5960}
  • tests/concurrent/park/start_parked.cfa

    rae2c27a rc76bd34  
    33thread Parker {};
    44void main( Parker & ) {
    5       park( __cfaabi_dbg_ctx );
     5        park();
    66}
    77
    88int main() {
    9       for(1000) {
    10             Parker parker;
    11             unpark( parker __cfaabi_dbg_ctx2 );
    12       }
     9        for(1000) {
     10                Parker parker;
     11                unpark( parker );
     12        }
     13        printf( "done\n" );                                                                     // non-empty .expect file
    1314}
  • tests/enum.cfa

    rae2c27a rc76bd34  
    2626//Dummy main
    2727int main(int argc, char const *argv[]) {
     28        printf( "done\n" );                             // non-empty .expect file
    2829}
  • tests/exceptions/.expect/virtual-cast.txt

    rae2c27a rc76bd34  
     1done
  • tests/exceptions/.expect/virtual-poly.txt

    rae2c27a rc76bd34  
     1done
  • tests/exceptions/virtual-cast.cfa

    rae2c27a rc76bd34  
    7474        free(tri);
    7575        free(top);
     76        printf( "done\n" );                             // non-empty .expect file
    7677}
  • tests/exceptions/virtual-poly.cfa

    rae2c27a rc76bd34  
    7777        mono_poly_test();
    7878        poly_poly_test();
     79        printf( "done\n" );                             // non-empty .expect file
    7980}
  • tests/expression.cfa

    rae2c27a rc76bd34  
    88
    99int main() {
    10     int a[3] = { 0, 0, 0 };
    11     S s = { 3 }, * ps = &s;
    12     [int] t = { 3 };
    13     * [int] pt = &t;
    14     int i = 1, j = 2;
     10        int a[3] = { 0, 0, 0 };
     11        S s = { 3 }, * ps = &s;
     12        [int] t = { 3 };
     13        * [int] pt = &t;
     14        int i = 1, j = 2;
    1515
    16     // operators
     16        // operators
    1717
    18     !i;
    19     ~i;
    20     +i;
    21     -i;
    22     *ps;
    23     ++ps;
    24     --ps;
    25     ps++;
    26     ps--;
     18        !i;
     19        ~i;
     20        +i;
     21        -i;
     22        *ps;
     23        ++ps;
     24        --ps;
     25        ps++;
     26        ps--;
    2727
    28     i + j;
    29     i - j;
    30     i * j;
     28        i + j;
     29        i - j;
     30        i * j;
    3131
    32     i / j;
    33     i % j;
    34     i ^ j;
    35     i & j;
    36     i | j;
    37     i < j;
    38     i > j;
    39     i = j;
     32        i / j;
     33        i % j;
     34        i ^ j;
     35        i & j;
     36        i | j;
     37        i < j;
     38        i > j;
     39        i = j;
    4040
    41     i == j;
    42     i != j;
    43     i << j;
    44     i >> j;
    45     i <= j;
    46     i >= j;
    47     i && j;
    48     i || j;
    49     ps->i;
     41        i == j;
     42        i != j;
     43        i << j;
     44        i >> j;
     45        i <= j;
     46        i >= j;
     47        i && j;
     48        i || j;
     49        ps->i;
    5050
    51     i *= j;
    52     i /= j;
    53     i %= j;
    54     i += j;
    55     i -= j;
    56     i &= j;
    57     i |= j;
    58     i ^= j;
    59     i <<= j;
    60     i >>= j;
     51        i *= j;
     52        i /= j;
     53        i %= j;
     54        i += j;
     55        i -= j;
     56        i &= j;
     57        i |= j;
     58        i ^= j;
     59        i <<= j;
     60        i >>= j;
    6161
    62     i ? i : j;
     62        i ? i : j;
    6363
    64     // postfix function call
     64        // postfix function call
    6565
    66     (3 + 4)`mary;
    67     ({3 + 4;})`mary;
    68     [3, 4]`mary;
    69     3`mary;
    70     a[0]`mary;
    71     a[0]`mary`mary;
    72     s{0}`mary;
    73     a[3]`jane++;
    74     jack(3)`mary;
    75     s.i`mary;
    76     t.0`mary;
    77     s.[i]`mary;
    78     ps->i`mary;
    79     pt->0`mary;
    80     ps->[i]`mary;
    81     i++`mary;
    82     i--`mary;
    83     (S){2}`mary;
    84     (S)@{2}`mary;
     66        (3 + 4)`mary;
     67        ({3 + 4;})`mary;
     68        [3, 4]`mary;
     69        3`mary;
     70        a[0]`mary;
     71        a[0]`mary`mary;
     72        s{0}`mary;
     73        a[3]`jane++;
     74        jack(3)`mary;
     75        s.i`mary;
     76        t.0`mary;
     77        s.[i]`mary;
     78        ps->i`mary;
     79        pt->0`mary;
     80        ps->[i]`mary;
     81        i++`mary;
     82        i--`mary;
     83        (S){2}`mary;
     84        (S)@{2}`mary;
     85
     86        #if !defined(NO_COMPILED_PRAGMA)
     87                #pragma message( "Compiled" )   // force non-empty .expect file
     88        #endif
    8589} // main
  • tests/forall.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed May  9 08:48:15 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 19 08:29:38 2019
    13 // Update Count     : 32
     12// Last Modified On : Sun Sep 27 08:43:20 2020
     13// Update Count     : 35
    1414//
    1515
     
    158158}
    159159forall( otype T ) inline static {
    160         int RT9( T ) { T t; }
     160        int RT9( T ) { T t; return 3; }
    161161}
    162162
     
    213213// w3 g3;
    214214
    215 int main( void ) {}
     215int main( void ) {
     216        #pragma message( "Compiled" )                   // force non-empty .expect file
     217}
    216218
    217219// Local Variables: //
  • tests/heap.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue Nov  6 17:54:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  9 08:05:16 2020
    13 // Update Count     : 57
     12// Last Modified On : Fri Sep 25 15:21:52 2020
     13// Update Count     : 73
    1414//
    1515
     
    205205                        free( area );
    206206                } // for
     207        } // for
     208
     209        // check malloc/resize/free (sbrk)
     210
     211        for ( i; 2 ~ NoOfAllocs ~ 12 ) {
     212                // initial N byte allocation
     213                char * area = (char *)malloc( i );
     214                area[0] = '\345'; area[i - 1] = '\345';                 // fill first/penultimate byte
     215
     216                // Do not start this loop index at 0 because resize of 0 bytes frees the storage.
     217                int prev = i;
     218                for ( s; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
     219                        if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/resize/free corrupt storage" );
     220                        area = (char *)resize( area, s );                       // attempt to reuse storage
     221                        area[0] = area[s - 1] = '\345';                         // fill last byte
     222                        prev = s;
     223                } // for
     224                free( area );
     225        } // for
     226
     227        // check malloc/resize/free (mmap)
     228
     229        for ( i; 2 ~ NoOfAllocs ~ 12 ) {
     230                // initial N byte allocation
     231                size_t s = i + default_mmap_start();                    // cross over point
     232                char * area = (char *)malloc( s );
     233                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/penultimate byte
     234
     235                // Do not start this loop index at 0 because resize of 0 bytes frees the storage.
     236                int prev = s;
     237                for ( r; s ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
     238                        if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/resize/free corrupt storage" );
     239                        area = (char *)resize( area, s );                       // attempt to reuse storage
     240                        area[0] = area[r - 1] = '\345';                         // fill last byte
     241                        prev = r;
     242                } // for
     243                free( area );
     244        } // for
     245
     246        // check malloc/realloc/free (sbrk)
     247
     248        for ( i; 2 ~ NoOfAllocs ~ 12 ) {
     249                // initial N byte allocation
     250                char * area = (char *)malloc( i );
     251                area[0] = '\345'; area[i - 1] = '\345';                 // fill first/penultimate byte
     252
     253                // Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
     254                int prev = i;
     255                for ( s; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
     256                        if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/realloc/free corrupt storage" );
     257                        area = (char *)realloc( area, s );                      // attempt to reuse storage
     258                        area[s - 1] = '\345';                                           // fill last byte
     259                        prev = s;
     260                } // for
     261                free( area );
     262        } // for
     263
     264        // check malloc/realloc/free (mmap)
     265
     266        for ( i; 2 ~ NoOfAllocs ~ 12 ) {
     267                // initial N byte allocation
     268                size_t s = i + default_mmap_start();                    // cross over point
     269                char * area = (char *)malloc( s );
     270                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/penultimate byte
     271
     272                // Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
     273                int prev = s;
     274                for ( r; s ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
     275                        if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/realloc/free corrupt storage" );
     276                        area = (char *)realloc( area, s );                      // attempt to reuse storage
     277                        area[r - 1] = '\345';                                           // fill last byte
     278                        prev = r;
     279                } // for
     280                free( area );
    207281        } // for
    208282
     
    320394        } // for
    321395
     396        // check memalign/resize with align/free
     397
     398        amount = 2;
     399        for ( a; libAlign() ~= limit ~ a ) {                            // generate powers of 2
     400                // initial N byte allocation
     401                char * area = (char *)memalign( a, amount );    // aligned N-byte allocation
     402                //sout | alignments[a] | area | endl;
     403                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     404                        abort( "memalign/resize with align/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)amount, area );
     405                } // if
     406                area[0] = '\345'; area[amount - 2] = '\345';    // fill first/penultimate byte
     407
     408                // Do not start this loop index at 0 because resize of 0 bytes frees the storage.
     409                for ( s; amount ~ 256 * 1024 ) {                                // start at initial memory request
     410                        area = (char *)resize( area, a * 2, s );        // attempt to reuse storage
     411                        //sout | i | area | endl;
     412                        if ( (size_t)area % a * 2 != 0 ) {                      // check for initial alignment
     413                                abort( "memalign/resize with align/free bad alignment %p", area );
     414                        } // if
     415                        area[s - 1] = '\345';                                           // fill last byte
     416                } // for
     417                free( area );
     418        } // for
     419
    322420        // check memalign/realloc with align/free
    323421
     
    387485        // checkFreeOn();
    388486        // malloc_stats();
     487        printf( "done\n" );                                                                     // non-empty .expect file
    389488}
    390489
  • tests/identFuncDeclarator.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Aug 17 08:36:34 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 17:56:33 2018
    13 // Update Count     : 3
     12// Last Modified On : Sun Sep 27 08:20:46 2020
     13// Update Count     : 5
    1414//
    1515
     
    111111        int (* (* const f80)(int))();
    112112        int (* const(* const f81)(int))();
     113
     114        #pragma message( "Compiled" )                   // force non-empty .expect file
    113115}
    114116
  • tests/identParamDeclarator.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Aug 17 08:37:56 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 17:56:44 2018
    13 // Update Count     : 3
     12// Last Modified On : Fri Sep 25 14:31:08 2020
     13// Update Count     : 4
    1414//
    1515
     
    158158
    159159int main( int argc, char const *argv[] ) {                              // dummy main
    160         return 0;
     160        printf( "done\n" );                                                                     // non-empty .expect file
    161161}
    162162
  • tests/labelledExit.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Aug 10 07:29:39 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  5 16:49:48 2020
    13 // Update Count     : 9
     12// Last Modified On : Sun Sep 27 09:01:34 2020
     13// Update Count     : 12
    1414//
    1515
     
    179179
    180180int main( int argc, char const *argv[] ) {
    181         /* code */
     181        #pragma message( "Compiled" )                                           // force non-empty .expect file
    182182}
    183183
  • tests/limits.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue May 10 20:44:20 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 17:57:55 2018
    13 // Update Count     : 8
     12// Last Modified On : Sun Sep 27 08:45:43 2020
     13// Update Count     : 10
    1414//
    1515
     
    147147
    148148int main(int argc, char const *argv[]) {
    149         //DUMMY
    150         return 0;
     149        #pragma message( "Compiled" )                                           // force non-empty .expect file
    151150}
    152151
  • tests/maybe.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Thr May 25 16:02:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:24:07 2017
    13 // Update Count     : 1
     12// Last Modified On : Fri Sep 25 15:13:28 2020
     13// Update Count     : 2
    1414//
    1515
     
    6565        //checkNamedConstructors();
    6666        checkSetters();
     67        printf( "done\n" );                             // non-empty .expect file
    6768}
  • tests/nested-types.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Mon Jul 9 10:20:03 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 12 18:21:15 2020
    13 // Update Count     : 3
     12// Last Modified On : Sun Sep 27 08:48:59 2020
     13// Update Count     : 6
    1414//
    1515
    1616typedef int N;
    1717struct A {
    18   forall(otype T)
    19   struct N {
    20     T x;
    21   };
     18        forall(otype T)
     19        struct N {
     20                T x;
     21        };
    2222};
    2323
    2424struct S {
    25   struct T {
    26     int i;
    27     typedef int Bar;
    28   };
    29   T x;
     25        struct T {
     26                int i;
     27                typedef int Bar;
     28        };
     29        T x;
    3030
    31   // struct U;
    32   typedef T Bar;
    33   typedef int Baz;
     31        // struct U;
     32        typedef T Bar;
     33        typedef int Baz;
    3434};
    3535
     
    6565
    6666int main() {
    67   // access nested struct
    68   S.T x;
     67        // access nested struct
     68        S.T x;
    6969
    70   {
    71     struct S {
    72       int i;
    73       struct Z {
    74         double d;
    75       };
    76     };
     70        {
     71                struct S {
     72                  int i;
     73                  struct Z {
     74                    double d;
     75                  };
     76                };
    7777
    78     S.Z z;   // gets local S
    79     .S.T y;  // lookup at global scope only
     78                S.Z z;                                                                                  // gets local S
     79                .S.T y;                                                                                 // lookup at global scope only
    8080
    81     const volatile .S.T q;
     81                const volatile .S.T q;
    8282#if ERR1
    83     T err1;           // error: no T in scope
     83                T err1;                                                                                 // error: no T in scope
    8484#endif
    8585#if ERR2
    86     .Z err2;          // error: no Z in global scope
    87     .S.Baz.Bar err3;  // error: .S.Baz => int, int is not aggregate and should not appear left of the dot
    88     .S.Z err4;        // error: no Z in global S
     86                .Z err2;                                                                                // error: no Z in global scope
     87                .S.Baz.Bar err3;                                                                // error: .S.Baz => int, int is not aggregate and should not appear left of the dot
     88                .S.Z err4;                                                                              // error: no Z in global S
    8989#endif
    90   }
     90        }
    9191
    92   // U.S un;
     92        // U.S un;
    9393
    94   S.Bar y;
    95   S.Baz x;
    96   S.T.Bar z;
     94        S.Bar y;
     95        S.Baz x;
     96        S.T.Bar z;
    9797
    98   // A.N(int) x;  // xxx - should not be an error, but currently is.
     98        // A.N(int) x;  // xxx - should not be an error, but currently is.
     99
     100        #pragma message( "Compiled" )                   // force non-empty .expect file
    99101}
    100102
  • tests/numericConstants.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed May 24 22:10:36 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  5 08:58:16 2019
    13 // Update Count     : 5
     12// Last Modified On : Sun Sep 27 07:55:22 2020
     13// Update Count     : 7
    1414//
    1515
     
    6363        0x_ff.ffp0;                                     // hex real
    6464        0x_1.ffff_ffff_p_128_l;
     65
     66        #pragma message( "Compiled" )   // force non-empty .expect file
    6567} // main
    6668
  • tests/operators.cfa

    rae2c27a rc76bd34  
    3131int main(int argc, char const *argv[]) {
    3232        /* code */
    33         return 0;
     33        printf( "done\n" );                             // non-empty .expect file
    3434}
    3535
  • tests/poly-o-cycle.cfa

    rae2c27a rc76bd34  
    1 // Check that a cycle of polymorphic data structures can be instancated.
     1// Check that a cycle of polymorphic otype structures can be instancated.
    22
    33#include <stdio.h>
  • tests/pybin/tools.py

    rae2c27a rc76bd34  
    8888                raise
    8989
     90def is_empty(fname):
     91        if not os.path.isfile(fname):
     92                return True
     93
     94        if os.stat(fname).st_size == 0:
     95                return True
     96
     97        return False
     98
    9099def is_ascii(fname):
    91100        if settings.dry_run:
    92101                print("is_ascii: %s" % fname)
    93                 return True
     102                return (True, "")
    94103
    95104        if not os.path.isfile(fname):
    96                 return False
    97 
    98         code, out = sh("file %s" % fname, output_file=subprocess.PIPE)
     105                return (False, "No file")
     106
     107        code, out = sh("file", fname, output_file=subprocess.PIPE)
    99108        if code != 0:
    100                 return False
     109                return (False, "'file EXPECT' failed with code {}".format(code))
    101110
    102111        match = re.search(".*: (.*)", out)
    103112
    104113        if not match:
    105                 return False
    106 
    107         return match.group(1).startswith("ASCII text")
     114                return (False, "Unreadable file type: '{}'".format(out))
     115
     116        if "ASCII text" in match.group(1):
     117                return (True, "")
     118
     119        return (False, "File type should be 'ASCII text', was '{}'".format(match.group(1)))
    108120
    109121def is_exe(fname):
     
    120132                return None
    121133
    122         file = open(file, mode)
     134        file = open(file, mode, encoding="latin-1") # use latin-1 so all chars mean something.
    123135        exitstack.push(file)
    124136        return file
  • tests/raii/.expect/ctor-autogen.txt

    rae2c27a rc76bd34  
     1done
  • tests/raii/.expect/init_once.txt

    rae2c27a rc76bd34  
     1done
  • tests/raii/ctor-autogen.cfa

    rae2c27a rc76bd34  
    151151        identity(gcs);
    152152        identity(gcu);
     153        printf( "done\n" );                             // non-empty .expect file
    153154}
  • tests/raii/init_once.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue Jun 14 15:43:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 22 13:41:26 2019
    13 // Update Count     : 4
     12// Last Modified On : Fri Sep 25 15:36:39 2020
     13// Update Count     : 5
    1414//
    1515
     
    188188                static_variable();
    189189        }
     190        printf( "done\n" );                                                                     // non-empty .expect file
    190191}
    191192
  • tests/result.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Thr May 25 16:50:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:24:12 2017
    13 // Update Count     : 1
     12// Last Modified On : Fri Sep 25 15:22:59 2020
     13// Update Count     : 2
    1414//
    1515
     
    6666        checkGetters();
    6767        checkSetters();
     68        printf( "done\n" );                             // non-empty .expect file
    6869}
  • tests/stdincludes.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue Aug 29 08:26:14 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 18:00:53 2018
    13 // Update Count     : 6
     12// Last Modified On : Sun Sep 27 08:51:38 2020
     13// Update Count     : 8
    1414//
    1515
     
    4747#include <wctype.h>
    4848
    49 int main() {}
     49int main() {
     50        #pragma message( "Compiled" )                   // force non-empty .expect file
     51}
    5052
    5153// Local Variables: //
  • tests/switch.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Tue Jul 12 06:50:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 18:01:34 2018
    13 // Update Count     : 37
     12// Last Modified On : Sun Sep 27 08:35:02 2020
     13// Update Count     : 43
    1414//
    1515
     
    100100                j = 5;
    101101        } // choose
     102
     103        #pragma message( "Compiled" )                                           // force non-empty .expect file
    102104} // main
    103105
  • tests/test.py

    rae2c27a rc76bd34  
    173173        test.prepare()
    174174
     175        # ----------
     176        # MAKE
     177        # ----------
    175178        # build, skipping to next test on error
    176179        with Timed() as comp_dur:
    177180                make_ret, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file )
    178181
     182        # ----------
     183        # RUN
     184        # ----------
     185        # run everything in a temp directory to make sure core file are handled properly
    179186        run_dur = None
    180         # run everything in a temp directory to make sure core file are handled properly
    181187        with tempdir():
    182188                # if the make command succeeds continue otherwise skip to diff
     
    207213                else:
    208214                        if os.stat(out_file).st_size < 1048576:
    209                                 with open (out_file, "r") as myfile:
     215                                with open (out_file, "r", encoding='latin-1') as myfile:  # use latin-1 so all chars mean something.
    210216                                        error = myfile.read()
    211217                        else:
     
    256262        make('clean', output_file=subprocess.DEVNULL, error=subprocess.DEVNULL)
    257263
    258         # since python prints stacks by default on a interrupt, redo the interrupt handling to be silent
    259         def worker_init():
    260                 def sig_int(signal_num, frame):
    261                         pass
    262 
    263                 signal.signal(signal.SIGINT, sig_int)
    264 
    265         # create the executor for our jobs and handle the signal properly
    266         pool = multiprocessing.Pool(jobs, worker_init)
     264        # create the executor for our jobs
     265        pool = multiprocessing.Pool(jobs)
    267266
    268267        failed = False
    269 
    270         def stop(x, y):
    271                 print("Tests interrupted by user", file=sys.stderr)
    272                 sys.exit(1)
    273         signal.signal(signal.SIGINT, stop)
    274268
    275269        # for each test to run
     
    360354                failed = 0
    361355
     356                # check if the expected files aren't empty
     357                if not options.regenerate_expected:
     358                        for t in tests:
     359                                if is_empty(t.expect()):
     360                                        print('WARNING: test "{}" has empty .expect file'.format(t.target()), file=sys.stderr)
     361
    362362                # for each build configurations, run the test
    363363                with Timed() as total_dur:
  • tests/typedefRedef.cfa

    rae2c27a rc76bd34  
    2727typedef int ARR[];
    2828typedef int ARR[];
    29 // #ifdef ERR1
    30 // if a typedef has an array dimension,
    31 // it can only be redefined to the same dimension
     29#ifdef ERR1
     30// if a typedef has an array dimension, it can only be redefined to the same dimension
    3231typedef int ARR[2];
    33 // #endif
     32#endif
    3433
    3534typedef int X;
     
    5453
    5554int main() {
    56   typedef int ARR[sz];
     55        typedef int ARR[sz];
    5756
    58   // can't redefine typedef which is VLA
     57        // can't redefine typedef which is VLA
    5958#if ERR1
    60   typedef int ARR[sz];
     59        typedef int ARR[sz];
    6160#endif
    6261
    63   Foo *x;
     62        Foo * x;
    6463
    65   typedef struct Bar Foo;
    66   Foo *y;
     64        typedef struct Bar Foo;
     65        Foo * y;
    6766
    68   typedef int *** pt;
     67        typedef int *** pt;
     68
     69        #pragma message( "Compiled" )                   // force non-empty .expect file
    6970}
  • tests/typeof.cfa

    rae2c27a rc76bd34  
    11int main() {
    2     int *v1;
    3     typeof(v1) v2;
    4     typeof(*v1) v3[4];
    5     char *v4[4];
    6     typeof(typeof(char *)[4]) v5;
    7     typeof (int *) v6;
    8     typeof( int ( int, int p ) ) *v7;
    9     typeof( [int] ( int, int p ) ) *v8;
    10     (typeof(v1)) v2; // cast with typeof
     2        int *v1;
     3        typeof(v1) v2;
     4        typeof(*v1) v3[4];
     5        char *v4[4];
     6        typeof(typeof(char *)[4]) v5;
     7        typeof (int *) v6;
     8        typeof( int ( int, int p ) ) *v7;
     9        typeof( [int] ( int, int p ) ) *v8;
     10        (typeof(v1)) v2; // cast with typeof
     11        printf( "done\n" );                             // non-empty .expect file
    1112}
  • tests/variableDeclarator.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Wed Aug 17 08:41:42 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 18:02:16 2018
    13 // Update Count     : 2
     12// Last Modified On : Sun Sep 27 07:46:17 2020
     13// Update Count     : 13
    1414//
    1515
     
    1818int (f2);
    1919
    20 int *f3;
    21 int **f4;
    22 int * const *f5;
     20int * f3;
     21int ** f4;
     22int * const * f5;
    2323int * const * const f6;
    2424
    25 int *(f7);
    26 int **(f8);
    27 int * const *(f9);
     25int * (f7);
     26int ** (f8);
     27int * const * (f9);
    2828int * const * const (f10);
    2929
    30 int (*f11);
    31 int (**f12);
    32 int (* const *f13);
     30int (* f11);
     31int (** f12);
     32int (* const * f13);
    3333int (* const * const f14);
    3434
    35 int f15[];
     35int f15[0];
    3636int f16[10];
    37 int (f17[]);
     37int (f17[0]);
    3838int (f18[10]);
    3939
    40 int *f19[];
    41 int *f20[10];
    42 int **f21[];
    43 int **f22[10];
    44 int * const *f23[];
    45 int * const *f24[10];
    46 int * const * const f25[];
     40int * f19[0];
     41int * f20[10];
     42int ** f21[0];
     43int ** f22[10];
     44int * const * f23[0];
     45int * const * f24[10];
     46int * const * const f25[0];
    4747int * const * const f26[10];
    4848
    49 int *(f27[]);
     49int *(f27[0]);
    5050int *(f28[10]);
    51 int **(f29[]);
     51int **(f29[0]);
    5252int **(f30[10]);
    53 int * const *(f31[]);
     53int * const *(f31[0]);
    5454int * const *(f32[10]);
    55 int * const * const (f33[]);
     55int * const * const (f33[0]);
    5656int * const * const (f34[10]);
    5757
    58 int (*f35)[];
    59 int (*f36)[10];
    60 int (**f37)[];
    61 int (**f38)[10];
    62 int (* const *f39)[];
    63 int (* const *f40)[10];
     58int (* f35)[];
     59int (* f36)[10];
     60int (** f37)[];
     61int (** f38)[10];
     62int (* const * f39)[];
     63int (* const * f40)[10];
    6464int (* const * const f41)[];
    6565int (* const * const f42)[10];
    6666
    67 int f43[][3];
     67int f43[0][3];
    6868int f44[3][3];
    69 int (f45[])[3];
     69int (f45[0])[3];
    7070int (f46[3])[3];
    71 int ((f47[]))[3];
     71int ((f47[0]))[3];
    7272int ((f48[3]))[3];
    7373
    74 int *f49[][3];
    75 int *f50[3][3];
    76 int **f51[][3];
    77 int **f52[3][3];
    78 int * const *f53[][3];
    79 int * const *f54[3][3];
    80 int * const * const f55[][3];
     74int * f49[0][3];
     75int * f50[3][3];
     76int ** f51[0][3];
     77int ** f52[3][3];
     78int * const * f53[0][3];
     79int * const * f54[3][3];
     80int * const * const f55[0][3];
    8181int * const * const f56[3][3];
    8282
    83 int (*f57[][3]);
    84 int (*f58[3][3]);
    85 int (**f59[][3]);
    86 int (**f60[3][3]);
    87 int (* const *f61[][3]);
    88 int (* const *f62[3][3]);
    89 int (* const * const f63[][3]);
     83int (* f57[0][3]);
     84int (* f58[3][3]);
     85int (** f59[0][3]);
     86int (** f60[3][3]);
     87int (* const * f61[0][3]);
     88int (* const * f62[3][3]);
     89int (* const * const f63[0][3]);
    9090int (* const * const f64[3][3]);
    9191
     
    9393int (f66)(int);
    9494
    95 int *f67(int);
    96 int **f68(int);
    97 int * const *f69(int);
     95int * f67(int);
     96int ** f68(int);
     97int * const * f69(int);
    9898int * const * const f70(int);
    9999
     
    104104int * const * const (f74)(int);
    105105
    106 int (*f75)(int);
    107 int (**f76)(int);
    108 int (* const *f77)(int);
     106int (* f75)(int);
     107int (** f76)(int);
     108int (* const * f77)(int);
    109109int (* const * const f78)(int);
    110110
    111 int (*(*f79)(int))();
     111int (*(* f79)(int))();
    112112int (*(* const f80)(int))();
    113113int (* const(* const f81)(int))();
     
    119119//int fe2()[];                          // returning an array
    120120//int fe3()();                          // returning a function
    121 //int (*fe4)()();                               // returning a function
    122 //int ((*fe5())())[];                   // returning an array
     121//int (* fe4)()();                              // returning a function
     122//int ((* fe5())())[];                  // returning an array
    123123
     124#ifdef __CFA__
    124125// Cforall extensions
    125126
     
    129130const * const * int cf6;
    130131
    131 [] int cf15;
     132[0] int cf15;
    132133[10] int cf16;
    133134
    134 [] * int cf19;
     135[0] * int cf19;
    135136[10] * int cf20;
    136 int **cf21[];
     137int ** cf21[0];
    137138[10] * * int cf22;
    138 [] * const * int cf23;
     139[0] * const * int cf23;
    139140[10] * const * int cf24;
    140 [] const * const * int cf25;
     141[0] const * const * int cf25;
    141142[10] const * const * int cf26;
    142143
     
    150151const * const * [10] int cf42;
    151152
    152 [][3] int cf43;
     153[0][3] int cf43;
    153154[3][3] int cf44;
    154155
    155 [][3] * int cf49;
     156[0][3] * int cf49;
    156157[3][3] * int cf50;
    157 [][3] * * int cf51;
     158[0][3] * * int cf51;
    158159[3][3] * * int cf52;
    159 [][3] const * int cf53;
     160[0][3] const * int cf53;
    160161[3][3] * const * int cf54;
    161 [][3] const * const * int cf55;
     162[0][3] const * const * int cf55;
    162163[3][3] const * const * int cf56;
    163164
     
    173174
    174175*[]*[]* [ *[]*[] int ]( *[]*[] int, *[]*[] int ) v3;
     176#endif // __CFA__
    175177
    176178//Dummy main
    177 int main(int argc, char const *argv[])
    178 {
    179         return 0;
     179int main( int argc, char const * argv[] ) {
     180        #pragma message( "Compiled" )                                           // force non-empty .expect file
    180181}
    181182
  • tests/voidPtr.cfa

    rae2c27a rc76bd34  
    1313        if ( ! a ) {
    1414                abort();
    15         }       
     15        }
     16        printf( "done\n" );                             // non-empty .expect file
    1617}
    1718
  • tests/warnings/.expect/self-assignment.txt

    rae2c27a rc76bd34  
    2424... to:
    2525  reference to signed int
     26warnings/self-assignment.cfa: In function '_X4mainFi___1':
     27warnings/self-assignment.cfa:36:9: note: #pragma message: Compiled
  • tests/warnings/self-assignment.cfa

    rae2c27a rc76bd34  
    1010// Created On       : Thu Mar 1 13:53:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 20 07:56:17 2019
    13 // Update Count     : 3
     12// Last Modified On : Sun Sep 27 09:24:34 2020
     13// Update Count     : 6
    1414//
    1515
     
    3131        s.i = s.i;
    3232        t.s.i = t.s.i;
     33
     34        #pragma message( "Compiled" )                   // force non-empty .expect file
    3335}
    3436
    3537// Local Variables: //
    3638// tab-width: 4 //
    37 // compile-command: "cfa dtor-early-exit" //
     39// compile-command: "cfa self-assignment.cfa" //
    3840// End: //
  • tests/zombies/Rank2.c

    rae2c27a rc76bd34  
    1 int ?=?( int *, int );
    2 forall(dtype DT) DT * ?=?( DT **, DT * );
     1int ?=?( int &, int );
     2forall(dtype DT) DT * ?=?( DT *&, DT * );
    33
    44void a() {
     
    1111        void h( int *null );
    1212        forall( otype T ) T id( T );
    13         forall( dtype T ) T *0;
    14         int 0;
     13//      forall( dtype T ) T *0;
     14//      int 0;
    1515        h( id( id( id( 0 ) ) ) );
    1616}
  • tests/zombies/Tuple.c

    rae2c27a rc76bd34  
    4646        [ 3, 5 ];
    4747        [ a, b ] = 3;
    48 //      [ a, b ] = [ 4.6 ];
     48        [ a, b ] = [ 4.6 ];
    4949        [ a, b ] = 4.6;
    5050        [ a, b ] = [ c, d ] = [ 3, 5 ];
     
    5959        [ a, b ] = t1 = [ c, d ];
    6060        [ a, b ] = t1 = t2 = [ c, d ];
    61 //      t1 = [ 3, 4 ] = [ 3, 4 ] = t1 = [ 3, 4 ];
     61        t1 = [ 3, 4 ] = [ 3, 4 ] = t1 = [ 3, 4 ];
    6262
    6363        s.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ];
     
    6565//      [ a, , b, ] = h( 3, 3, 0, "abc" );                      /* ignore some results */
    6666        sp->[ f4, f1 ] = sp->[ f1, f4 ];
    67         printf( "expecting 3, 17, 23, 4; got %d, %d, %d, %d\n", s.[ f4, i.[ f3, f2 ], f1 ] );
     67        printf( "expecting 3, 17, 23, 4; got %g, %d, %d, %d\n", s.[ f4, i.[ f3, f2 ], f1 ] );
    6868        rc = 0;
    6969}
  • tests/zombies/abstype.c

    rae2c27a rc76bd34  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun 14 14:27:48 2016
    13 // Update Count     : 9
     12// Last Modified On : Wed Sep 30 13:55:47 2020
     13// Update Count     : 10
    1414//
    1515
     
    2121}
    2222
    23 forall( otype T ) lvalue T *?( T * );
     23forall( otype T ) T *?( T * );
    2424int ?++( int * );
    2525int ?=?( int *, int );
  • tests/zombies/includes.c

    rae2c27a rc76bd34  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov 15 23:06:24 2017
    13 // Update Count     : 597
     12// Last Modified On : Wed Sep 30 13:59:18 2020
     13// Update Count     : 598
    1414//
    1515
     
    2424#if 1
    2525#define _GNU_SOURCE
    26 #include <a.out.h>
    27 #include <aio.h>
    28 #include <aliases.h>
    29 #include <alloca.h>
    30 #include <ansidecl.h>
    31 #include <ar.h>
    32 #include <argp.h>
    33 #include <argz.h>
    34 #include <assert.h>
    35 //#include <bfd.h>
    36 // #include <bfdlink.h>                         // keyword with
    37 #include <byteswap.h>
    38 #include <bzlib.h>
    39 #include <cblas.h>
    40 #include <cblas_f77.h>
    41 #include <complex.h>
    42 #include <com_err.h>
    43 #include <cpio.h>
    44 #include <crypt.h>
    45 #include <ctype.h>
    46 #include <curses.h>
    47 #include <dialog.h>
    48 #include <dirent.h>
    49 #include <dis-asm.h>
    50 #include <dlfcn.h>
    51 #include <dlg_colors.h>
    52 #include <dlg_config.h>
    53 #include <dlg_keys.h>
    54 #include <elf.h>
    55 #include <endian.h>
    56 #include <envz.h>
    57 #include <err.h>
    58 #include <errno.h>
    59 #include <error.h>
    60 #include <eti.h>
    61 #include <evdns.h>
    62 #include <event.h>
     26// #include <a.out.h>
     27// #include <aio.h>
     28// #include <aliases.h>
     29// #include <alloca.h>
     30// #include <ansidecl.h>
     31// #include <ar.h>
     32// #include <argp.h>
     33// #include <argz.h>
     34// #include <assert.h>
     35// #include <bfd.h>
     36// #include <bfdlink.h>                                                                 // keyword with
     37// #include <byteswap.h>
     38// #include <bzlib.h>
     39// #include <cblas.h>
     40// #include <cblas_f77.h>
     41// #include <complex.h>
     42// #include <com_err.h>
     43// #include <cpio.h>
     44
     45// #include <crypt.h>
     46// #include <ctype.h>
     47// #include <curses.h>
     48// #include <dialog.h>
     49// #include <dirent.h>
     50// #include <dis-asm.h>
     51// #include <dlfcn.h>
     52// #include <dlg_colors.h>
     53// #include <dlg_config.h>
     54// #include <dlg_keys.h>
     55// #include <elf.h>
     56// #include <endian.h>
     57// #include <envz.h>
     58// #include <err.h>
     59// #include <errno.h>
     60// #include <error.h>
     61// #include <eti.h>
     62// #include <evdns.h>
     63// #include <event.h>
    6364
    6465// #include <evhttp.h>
    6566// #include <sys/queue.h>
    66 // #include <evrpc.h>                                   // evrpc.h depends on sys/queue.h
     67// #include <evrpc.h>                                                                           // evrpc.h depends on sys/queue.h
    6768// #include <evutil.h>
    6869// #include <execinfo.h>
     
    8081// #include <fts.h>
    8182// #include <ftw.h>
     83
    8284// #include <gconv.h>
    8385// #include <getopt.h>
     
    8991// #include <gshadow.h>
    9092// #include <gssapi.h>
    91 // #include <hwloc.h>                                   // keyword thread (setjmp)
     93#include <hwloc.h>                                                                              // keyword thread (setjmp)
    9294// #include <iconv.h>
    9395// #include <idna.h>
  • tests/zombies/structMember.cfa

    rae2c27a rc76bd34  
    5353// C useless declarations
    5454
     55#ifdef ERROR
    5556        int;
    5657        TD;
     
    7071        W(int);
    7172        W(int).X;
     73#endif // ERROR
    7274};
    7375
  • tools/gdb/utils-gdb.py

    rae2c27a rc76bd34  
    4444STACK = []
    4545
    46 # A global variable to keep all system task name
    47 SysTask_Name = ["uLocalDebuggerReader", "uLocalDebugger", "uProcessorTask", "uBootTask", "uSystemTask",
    48 "uProcessorTask", "uPthread", "uProfiler"]
    49 
    5046not_supported_error_msg = "Not a supported command for this language"
    5147
     
    10197        return cluster_root
    10298
     99def get_sched_lock():
     100        """
     101        Return: gdb.Value of __scheduler_lock
     102        """
     103        lock = gdb.parse_and_eval('_X16__scheduler_lockPS20__scheduler_RWLock_t_1')
     104        if lock.address == 0x0:
     105                print('No scheduler lock, program terminated')
     106        return lock
     107
     108def all_clusters():
     109        if not is_cforall():
     110                return None
     111
     112        cluster_root = get_cluster_root()
     113        if cluster_root.address == 0x0:
     114                return
     115
     116        curr = cluster_root
     117        ret = [curr]
     118
     119        while True:
     120                curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']
     121                if curr == cluster_root:
     122                        break
     123
     124                ret.append(curr)
     125
     126        return ret
     127
     128def all_processors():
     129        if not is_cforall():
     130                return None
     131
     132        cfa_t = get_cfa_types()
     133
     134        # get processors from registration to the RWlock
     135        lock = get_sched_lock()
     136
     137        #get number of elements
     138        count = lock['_X5readyVj_1']
     139
     140        #find all the procs
     141        raw_procs = [lock['_X4dataPS21__scheduler_lock_id_t_1'][i]['_X6handleVPS16__processor_id_t_1'] for i in range(count)]
     142
     143        # pre cast full procs
     144        procs = [p.cast(cfa_t.processor_ptr) for p in raw_procs if p['_X9full_procb_1']]
     145
     146        # sort procs by clusters
     147        return sorted(procs, key=lambda p: p['_X4cltrPS7cluster_1'])
     148
     149def tls_for_pthread(pthrd):
     150        prev = gdb.selected_thread()
     151        inf = gdb.selected_inferior()
     152
     153        thrd = inf.thread_from_thread_handle( pthrd )
     154        thrd.switch()
     155        tls = gdb.parse_and_eval('&_X9kernelTLSS16KernelThreadData_1')
     156
     157        prev.switch()
     158        return tls
     159
     160def tls_for_proc(proc):
     161        return tls_for_pthread(proc['_X13kernel_threadm_1'])
     162
     163def thread_for_pthread(pthrd):
     164        return tls_for_pthread(pthrd)['_X11this_threadVPS7$thread_1']
     165
     166def thread_for_proc(proc):
     167        return tls_for_proc(proc)['_X11this_threadVPS7$thread_1']
     168
     169
     170
    103171def find_curr_thread():
    104172        # btstr = gdb.execute('bt', to_string = True).splitlines()
     
    108176        # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0]
    109177        return None
    110 
    111 def all_clusters():
    112         if not is_cforall():
    113                 return None
    114 
    115         cluster_root = get_cluster_root()
    116         if cluster_root.address == 0x0:
    117                 return
    118 
    119         curr = cluster_root
    120         ret = [curr]
    121 
    122         while True:
    123                 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']
    124                 if curr == cluster_root:
    125                         break
    126 
    127                 ret.append(curr)
    128 
    129         return ret
    130 
    131178
    132179def lookup_cluster(name = None):
     
    239286        """Cforall: Display currently known processors
    240287Usage:
    241         info processors                 : print out all the processors in the Main Cluster
    242         info processors all             : print out all processors in all clusters
     288        info processors                 : print out all the processors
    243289        info processors <cluster_name>  : print out all processors in a given cluster
    244290"""
     
    247293                super(Processors, self).__init__('info processors', gdb.COMMAND_USER)
    248294
    249         def print_processor(self, name, status, pending, address):
    250                 print('{:>20}  {:>11}  {:>13}  {:>20}'.format(name, status, pending, address))
    251 
    252         def iterate_procs(self, root, active):
    253                 if root == 0x0:
    254                         return
    255 
    256                 cfa_t = get_cfa_types()
    257                 curr = root
    258 
    259                 while True:
    260                         processor = curr
    261                         should_stop = processor['_X12do_terminateVb_1']
     295        def print_processor(self, processor):
     296                should_stop = processor['_X12do_terminateVb_1']
     297                if not should_stop:
     298                        midle = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X4elemPY13__tE_generic__1'] != 0x0
     299                        end   = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X10terminatorPv_1'] != 0x0
     300
     301                        status = 'Idle' if midle or end else 'Active'
     302                else:
    262303                        stop_count  = processor['_X10terminatedS9semaphore_1']['_X5counti_1']
    263                         if not should_stop:
    264                                 status = 'Active' if active else 'Idle'
    265                         else:
    266                                 status_str  = 'Last Thread' if stop_count >= 0 else 'Terminating'
    267                                 status      = '{}({},{})'.format(status_str, should_stop, stop_count)
    268 
    269                         self.print_processor(processor['_X4namePKc_1'].string(),
    270                                         status, str(processor['_X18pending_preemptionb_1']), str(processor)
    271                                 )
    272 
    273                         curr = curr['_X4nodeS28__processor____dbg_node_proc_1']['_X4nextPS9processor_1']
    274 
    275                         if curr == root or curr == 0x0:
    276                                 break
     304                        status_str  = 'Last Thread' if stop_count >= 0 else 'Terminating'
     305                        status      = '{}({},{})'.format(status_str, should_stop, stop_count)
     306
     307                print('{:>20}  {:>11}  {:<7}  {:<}'.format(
     308                        processor['_X4namePKc_1'].string(),
     309                        status,
     310                        str(processor['_X18pending_preemptionb_1']),
     311                        str(processor)
     312                ))
     313                tls = tls_for_proc( processor )
     314                thrd = tls['_X11this_threadVPS7$thread_1']
     315                if thrd != 0x0:
     316                        tname = '{} {}'.format(thrd['self_cor']['name'].string(), str(thrd))
     317                else:
     318                        tname = None
     319
     320                print('{:>20}  {}'.format('Thread', tname))
     321                print('{:>20}  {}'.format('TLS', tls))
    277322
    278323        #entry point from gdb
     
    282327
    283328                if not arg:
    284                         clusters = [lookup_cluster(None)]
    285                 elif arg == "all":
    286329                        clusters = all_clusters()
    287330                else:
     
    292335                        return
    293336
    294                 cfa_t = get_cfa_types()
    295                 for cluster in clusters:
    296                         print('Cluster: "{}"({})'.format(cluster['_X4namePKc_1'].string(), cluster.cast(cfa_t.cluster_ptr)))
    297 
    298                         active_root = cluster.cast(cfa_t.cluster_ptr) \
    299                                         ['_X5procsS8__dllist_S9processor__1'] \
    300                                         ['_X4headPY15__TYPE_generic__1'] \
    301                                         .cast(cfa_t.processor_ptr)
    302 
    303                         idle_root = cluster.cast(cfa_t.cluster_ptr) \
    304                                         ['_X5idlesS8__dllist_S9processor__1'] \
    305                                         ['_X4headPY15__TYPE_generic__1'] \
    306                                         .cast(cfa_t.processor_ptr)
    307 
    308                         if idle_root != 0x0 or active_root != 0x0:
    309                                 self.print_processor('Name', 'Status', 'Pending Yield', 'Address')
    310                                 self.iterate_procs(active_root, True)
    311                                 self.iterate_procs(idle_root, False)
    312                         else:
    313                                 print("No processors on cluster")
     337                procs = all_processors()
     338
     339                print('{:>20}  {:>11}  {:<7}  {}'.format('Processor', '', 'Pending', 'Object'))
     340                print('{:>20}  {:>11}  {:<7}  {}'.format('Name', 'Status', 'Yield', 'Address'))
     341                cl = None
     342                for p in procs:
     343                        # if this is a different cluster print it
     344                        if cl != p['_X4cltrPS7cluster_1']:
     345                                if cl:
     346                                        print()
     347                                cl = p['_X4cltrPS7cluster_1']
     348                                print('Cluster {}'.format(cl['_X4namePKc_1'].string()))
     349
     350                        # print the processor information
     351                        self.print_processor(p)
    314352
    315353                print()
Note: See TracChangeset for help on using the changeset viewer.