Changes in / [74ec742:29d8c02]


Ignore:
Files:
4 added
36 deleted
137 edited

Legend:

Unmodified
Added
Removed
  • benchmark/Cargo.toml.in

    r74ec742 r29d8c02  
    44authors = ["Cforall"]
    55edition = "2018"
    6 
    7 [[bin]]
    8 name = "rdq-churn-tokio"
    9 path = "@abs_srcdir@/readyQ/churn.rs"
    106
    117[[bin]]
  • benchmark/Makefile.am

    r74ec742 r29d8c02  
    614614RDQBENCHES = \
    615615        rdq-churn-cfa \
    616         rdq-churn-tokio \
    617         rdq-churn-go \
    618         rdq-churn-fibre \
    619616        rdq-cycle-cfa \
    620617        rdq-cycle-tokio \
  • benchmark/plot.py

    r74ec742 r29d8c02  
    2222
    2323class Field:
    24         def __init__(self, unit, _min, _log, _name=None):
     24        def __init__(self, unit, _min, _log):
    2525                self.unit = unit
    2626                self.min  = _min
    2727                self.log  = _log
    28                 self.name = _name
    2928
    3029field_names = {
     
    3332        "Ops per procs"         : Field('Ops'   , 0, False),
    3433        "Ops per threads"       : Field('Ops'   , 0, False),
    35         "ns per ops/procs"      : Field(''    , 0, False, _name = "Latency (ns $/$ (Processor $\\times$ Operation))" ),
    36         "Number of threads"     : Field(''      , 1, False),
     34        "ns per ops/procs"      : Field('ns'    , 0, False),
     35        "Number of threads"     : Field('thrd'  , 1, False),
    3736        "Total Operations(ops)" : Field('Ops'   , 0, False),
    3837        "Ops/sec/procs"         : Field('Ops'   , 0, False),
    3938        "Total blocks"          : Field('Blocks', 0, False),
    40         "Ops per second"        : Field(''   , 0, False),
     39        "Ops per second"        : Field('Ops'   , 0, False),
    4140        "Cycle size (# thrds)"  : Field('thrd'  , 1, False),
    4241        "Duration (ms)"         : Field('ms'    , 0, False),
    43         "Target QPS"            : Field(''      , 0, False),
    44         "Actual QPS"            : Field(''      , 0, False),
    45         "Average Read Latency"  : Field('us'    , 0, True),
     42        "Target QPS"            : Field('QPS'   , 0, False),
     43        "Actual QPS"            : Field('QPS'   , 0, False),
    4644        "Median Read Latency"   : Field('us'    , 0, True),
    4745        "Tail Read Latency"     : Field('us'    , 0, True),
    48         "Average Update Latency": Field('us'    , 0, True),
    4946        "Median Update Latency" : Field('us'    , 0, True),
    5047        "Tail Update Latency"   : Field('us'    , 0, True),
    51         "Update Ratio"          : Field('\%'    , 0, False),
    5248}
    5349
    54 def plot(in_data, x, y, options):
     50def plot(in_data, x, y, out):
    5551        fig, ax = plt.subplots()
    5652        colors = itertools.cycle(['#0095e3','#006cb4','#69df00','#0aa000','#fb0300','#e30002','#fd8f00','#ff7f00','#8f00d6','#4b009a','#ffff00','#b13f00'])
     
    9692        print("Making Plots")
    9793
    98         for name, data in sorted(series.items()):
     94        for name, data in series.items():
    9995                _col = next(colors)
    10096                plt.scatter(data['x'], data['y'], color=_col, label=name, marker='x')
     
    110106        print("Finishing Plots")
    111107
    112         plt.ylabel(field_names[y].name if field_names[y].name else y)
     108        plt.ylabel(y)
    113109        # plt.xticks(range(1, math.ceil(mx) + 1))
    114         plt.xlabel(field_names[x].name if field_names[x].name else x)
     110        plt.xlabel(x)
    115111        plt.grid(b = True)
    116112        ax.xaxis.set_major_formatter( EngFormatter(unit=field_names[x].unit) )
    117         if options.logx:
    118                 ax.set_xscale('log')
    119         elif field_names[x].log:
     113        if field_names[x].log:
    120114                ax.set_xscale('log')
    121115        else:
     
    123117
    124118        ax.yaxis.set_major_formatter( EngFormatter(unit=field_names[y].unit) )
    125         if options.logy:
    126                 ax.set_yscale('log')
    127         elif field_names[y].log:
     119        if field_names[y].log:
    128120                ax.set_yscale('log')
    129121        else:
    130                 plt.ylim(field_names[y].min, options.MaxY if options.MaxY else my*1.2)
     122                plt.ylim(field_names[y].min, my*1.2)
    131123
    132124        plt.legend(loc='upper left')
    133125
    134126        print("Results Ready")
    135         if options.out:
    136                 plt.savefig(options.out, bbox_inches='tight')
     127        if out:
     128                plt.savefig(out)
    137129        else:
    138130                plt.show()
     
    147139        parser.add_argument('-y', nargs='?', type=str, default="", help="Which field to use as the Y axis")
    148140        parser.add_argument('-x', nargs='?', type=str, default="", help="Which field to use as the X axis")
    149         parser.add_argument('--logx', action='store_true', help="if set, makes the x-axis logscale")
    150         parser.add_argument('--logy', action='store_true', help="if set, makes the y-axis logscale")
    151         parser.add_argument('--MaxY', nargs='?', type=int, help="maximum value of the y-axis")
    152141
    153142        options =  parser.parse_args()
     
    193182
    194183
    195         plot(data, wantx, wanty, options)
     184        plot(data, wantx, wanty, options.out)
  • benchmark/process-mutilate.py

    r74ec742 r29d8c02  
    1414parser = argparse.ArgumentParser(description='Python Script to convert output from mutilate to rmit like output')
    1515parser.add_argument('--out', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
    16 parser.add_argument('--var', nargs='?', type=str, default='Target QPS')
    1716try:
    1817        options =  parser.parse_args()
     
    3231
    3332        try:
    34                 latAvs = fields[1]
    3533                lat50s = fields[6]
    3634                lat99s = fields[9]
     
    3937
    4038        try:
    41                 latAv = locale.atof(latAvs)
    4239                lat50 = locale.atof(lat50s)
    4340                lat99 = locale.atof(lat99s)
     
    4542                raise Warning("Warning: \"{}\" \"{}\"! can't convert to float".format(lat50s, lat99s))
    4643
    47         return latAv, lat50, lat99
     44        return lat50, lat99
    4845
    4946def want0(line):
     
    6158                try:
    6259                        if   line.startswith("read"):
    63                                 rlatAv, rlat50, rlat99 = precentile(line)
     60                                rlat50, rlat99 = precentile(line)
    6461
    6562                        elif line.startswith("update"):
    66                                 ulatAv, ulat50, ulat99 = precentile(line)
     63                                ulat50, ulat99 = precentile(line)
    6764
    6865                        elif line.startswith("Total QPS"):
     
    8784
    8885        try:
    89                 out['Average Read Latency'] = rlatAv
    9086                out['Median Read Latency'] = rlat50
    9187                out['Tail Read Latency'] = rlat99
     
    9490
    9591        try:
    96                 out['Average Update Latency'] = ulatAv
    9792                out['Median Update Latency'] = ulat50
    9893                out['Tail Update Latency'] = ulat99
     
    117112                        continue
    118113
    119                 d = { options.var : int(rate) }
     114                d = { 'Target QPS': int(rate) }
    120115
    121116                w = extract( f, d )
  • benchmark/readyQ/bench.go

    r74ec742 r29d8c02  
    7171                duration = 5
    7272                clock_mode = true
    73                 fmt.Printf("Running for %f seconds (default)\n", duration)
     73                fmt.Printf("Running for %f seconds\n", duration)
    7474        }
    7575
  • benchmark/readyQ/churn.cfa

    r74ec742 r29d8c02  
    11#include "rq_bench.hfa"
    22
    3 #include <locks.hfa>
    4 
    53unsigned spot_cnt = 2;
    6 semaphore * spots;
     4bench_sem * volatile * spots;
    75
    86thread BThrd {
    97        unsigned long long count;
    108        unsigned long long blocks;
    11         bool skip;
     9        bench_sem sem;
    1210};
    1311
     
    1614        this.count  = 0;
    1715        this.blocks = 0;
    18         this.skip = false;
    1916}
    2017
     
    2219
    2320void main( BThrd & this ) with( this ) {
    24         park();
     21        wait( sem );
    2522        for() {
    26                 uint32_t r = prng(this);
    27                 semaphore & sem = spots[r % spot_cnt];
    28                 if(!skip) V( sem );
    29                 blocks += P( sem );
    30                 skip = false;
    31 
     23                uint32_t r = prng();
     24                bench_sem * next = __atomic_exchange_n(&spots[r % spot_cnt], &sem, __ATOMIC_SEQ_CST);
     25                if(next) post( *next );
     26                blocks += wait( sem );
    3227                count ++;
    3328                if( clock_mode && stop) break;
     
    4439                { 's', "spots", "Number of spots in the system", spot_cnt }
    4540        };
    46         BENCH_OPT_PARSE("cforall churn benchmark");
     41        BENCH_OPT_PARSE("cforall cycle benchmark");
    4742
    4843        {
     
    5449                        spots = aalloc(spot_cnt);
    5550                        for(i; spot_cnt) {
    56                                 (spots[i]){ 0 };
     51                                spots[i] = 0p;
    5752                        }
    5853
     
    6055                        BThrd * threads[nthreads];
    6156                        for(i; nthreads ) {
    62                                 BThrd & t = *(threads[i] = malloc());
    63                                 (t){};
    64                                 t.skip = i < spot_cnt;
     57                                threads[i] = malloc();
     58                                (*threads[i]){};
    6559                        }
    6660                        printf("Starting\n");
     
    7064
    7165                        for(i; nthreads) {
    72                                 unpark( *threads[i] );
     66                                post( threads[i]->sem );
    7367                        }
    7468                        wait(start, is_tty);
     
    7872                        printf("\nDone\n");
    7973
    80                         for(i; spot_cnt) {
    81                                 for(10000) V( spots[i] );
    82                         }
    83 
    8474                        for(i; nthreads) {
     75                                post( threads[i]->sem );
    8576                                BThrd & thrd = join( *threads[i] );
    8677                                global_counter += thrd.count;
  • benchmark/readyQ/cycle.cpp

    r74ec742 r29d8c02  
    4646                        }
    4747                        for(unsigned i = 0; i < tthreads; i++) {
    48                                 threads[i] = new Fibre();
    49                                 threads[i]->run( partner_main, &thddata[i] );
     48                                threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(partner_main), &thddata[i] );
    5049                        }
    5150                        printf("Starting\n");
  • benchmark/readyQ/rq_bench.hpp

    r74ec742 r29d8c02  
    143143        }
    144144
    145         if(strcmp(arg, "Y") == 0) {
    146                 value = true;
    147                 return true;
    148         }
    149 
    150         if(strcmp(arg, "y") == 0) {
    151                 value = true;
    152                 return true;
    153         }
    154 
    155145        if(strcmp(arg, "no") == 0) {
    156                 value = false;
    157                 return true;
    158         }
    159 
    160         if(strcmp(arg, "N") == 0) {
    161                 value = false;
    162                 return true;
    163         }
    164 
    165         if(strcmp(arg, "n") == 0) {
    166146                value = false;
    167147                return true;
  • benchmark/readyQ/transfer.cfa

    r74ec742 r29d8c02  
    1414
    1515bool exhaust = false;
    16 volatile bool estop = false;
    17 
    1816
    1917thread$ * the_main;
     
    3735static void waitgroup() {
    3836        Time start = timeHiRes();
    39         OUTER: for(i; nthreads) {
     37        for(i; nthreads) {
    4038                PRINT( sout | "Waiting for :" | i | "(" | threads[i]->idx | ")"; )
    4139                while( threads[i]->idx != lead_idx ) {
     
    4442                                print_stats_now( bench_cluster, CFA_STATS_READY_Q | CFA_STATS_IO );
    4543                                serr | "Programs has been blocked for more than 5 secs";
    46                                 estop = true;
    47                                 unpark( the_main );
    48                                 break OUTER;
     44                                exit(1);
    4945                        }
    5046                }
     
    6359static void lead(MyThread & this) {
    6460        this.idx = ++lead_idx;
    65         if(lead_idx > stop_count || estop) {
     61        if(lead_idx > stop_count) {
    6662                PRINT( sout | "Leader" | this.id | "done"; )
    6763                unpark( the_main );
     
    104100                        wait( this );
    105101                }
    106                 if(lead_idx > stop_count || estop) break;
     102                if(lead_idx > stop_count) break;
    107103        }
    108104}
     
    176172        sout | "Number of processors    : " | nprocs;
    177173        sout | "Number of threads       : " | nthreads;
    178         sout | "Total Operations(ops)   : " | lead_idx - 1;
     174        sout | "Total Operations(ops)   : " | stop_count;
    179175        sout | "Threads parking on wait : " | (exhaust ? "yes" : "no");
    180176        sout | "Rechecking              : " | rechecks;
    181         sout | "ns per transfer         : " | (end - start)`dms / lead_idx;
    182177
    183178
  • benchmark/readyQ/transfer.cpp

    r74ec742 r29d8c02  
    1212
    1313bool exhaust = false;
    14 volatile bool estop = false;
    1514
    1615bench_sem the_main;
     
    4342                                if( to_miliseconds(timeHiRes() - start) > 5'000 ) {
    4443                                        std::cerr << "Programs has been blocked for more than 5 secs" << std::endl;
    45                                         estop = true;
    46                                         the_main.post();
    47                                         goto END;
     44                                        std::exit(1);
    4845                                }
    4946                        }
    5047                }
    51                 END:;
    5248                PRINT( std::cout | "Waiting done"; )
    5349        }
     
    6359        void lead() {
    6460                this->idx = ++lead_idx;
    65                 if(lead_idx > stop_count || estop) {
     61                if(lead_idx > stop_count) {
    6662                        PRINT( std::cout << "Leader " << this->id << " done" << std::endl; )
    6763                        the_main.post();
     
    9288        }
    9389
    94         static void main(MyThread * arg) {
    95                 MyThread & self = *arg;
     90        static void main(void * arg) {
     91                MyThread & self = *reinterpret_cast<MyThread*>(arg);
    9692                self.park();
    9793
     
    105101                                self.wait();
    106102                        }
    107                         if(lead_idx > stop_count || estop) break;
     103                        if(lead_idx > stop_count) break;
    108104                }
    109105        }
     
    148144                        for(size_t i = 0; i < nthreads; i++) {
    149145                                threads[i] = new MyThread( i );
    150                                 handles[i] = new Fibre();
    151                                 handles[i]->run( MyThread::main, threads[i] );
     146                                handles[i] = new Fibre( MyThread::main, threads[i] );
    152147                        }
    153148
     
    169164                                PRINT( std::cout << i << " joined" << std::endl; )
    170165                                rechecks += thrd.rechecks;
     166                                // delete( handles[i] );
    171167                                delete( threads[i] );
    172168                        }
     
    180176        std::cout << "Number of processors    : " << nprocs << std::endl;
    181177        std::cout << "Number of threads       : " << nthreads << std::endl;
    182         std::cout << "Total Operations(ops)   : " << (lead_idx - 1) << std::endl;
     178        std::cout << "Total Operations(ops)   : " << stop_count << std::endl;
    183179        std::cout << "Threads parking on wait : " << (exhaust ? "yes" : "no") << std::endl;
    184180        std::cout << "Rechecking              : " << rechecks << std::endl;
    185         std::cout << "ns per transfer         : " << std::fixed << (((double)(end - start)) / (lead_idx)) << std::endl;
    186181
    187182
  • benchmark/readyQ/transfer.go

    r74ec742 r29d8c02  
    66        "math/rand"
    77        "os"
    8         "regexp"
    98        "runtime"
    109        "sync/atomic"
     
    1716        id uint64
    1817        idx uint64
    19         estop uint64
    2018        seed uint64
    2119}
     
    3634
    3735func NewLeader(size uint64) (*LeaderInfo) {
    38         this := &LeaderInfo{0, 0, 0, uint64(os.Getpid())}
     36        this := &LeaderInfo{0, 0, uint64(os.Getpid())}
    3937
    4038        r := rand.Intn(10)
     
    5351}
    5452
    55 func waitgroup(leader * LeaderInfo, idx uint64, threads [] MyThread, main_sem chan struct {}) {
     53func waitgroup(idx uint64, threads [] MyThread) {
    5654        start := time.Now()
    57         Outer:
    5855        for i := 0; i < len(threads); i++ {
    5956                // fmt.Fprintf(os.Stderr, "Waiting for :%d (%d)\n", threads[i].id, atomic.LoadUint64(&threads[i].idx) );
     
    6461                        if delta.Seconds() > 5 {
    6562                                fmt.Fprintf(os.Stderr, "Programs has been blocked for more than 5 secs")
    66                                 atomic.StoreUint64(&leader.estop, 1);
    67                                 main_sem <- (struct {}{})
    68                                 break Outer
     63                                os.Exit(1)
    6964                        }
    7065                }
     
    7974                if i != me {
    8075                        // debug!( "Leader waking {}", i);
    81                         defer func() {
    82                                 if err := recover(); err != nil {
    83                                         fmt.Fprintf(os.Stderr, "Panic occurred: %s\n", err)
    84                                 }
    85                         }()
    8676                        threads[i].sem <- (struct {}{})
    8777                }
     
    9484        atomic.StoreUint64(&leader.idx, nidx);
    9585
    96         if nidx > stop_count || atomic.LoadUint64(&leader.estop) != 0 {
     86        if nidx > stop_count {
    9787                // debug!( "Leader {} done", this.id);
    9888                main_sem <- (struct {}{})
     
    10292        // debug!( "====================\nLeader no {} : {}", nidx, this.id);
    10393
    104         waitgroup(leader, nidx, threads, main_sem);
     94        waitgroup(nidx, threads);
    10595
    10696        leader.next( uint64(len(threads)) );
     
    156146                        waitleader( exhaust, leader, &threads[me], &r )
    157147                }
    158                 if atomic.LoadUint64(&leader.idx) > stop_count || atomic.LoadUint64(&leader.estop) != 0 { break; }
     148                if atomic.LoadUint64(&leader.idx) > stop_count { break; }
    159149        }
    160150
     
    165155func main() {
    166156        // Benchmark specific command line arguments
    167         exhaustOpt := flag.String("e", "no", "Whether or not threads that have seen the new epoch should park instead of yielding.")
     157        exhaustOpt := flag.Bool("e", false, "Whether or not threads that have seen the new epoch should park instead of yielding.")
    168158
    169159        // General benchmark initialization and deinitialization
    170         bench_init()
    171 
    172         exhaustVal := *exhaustOpt;
    173 
    174         var exhaust bool
    175         re_yes := regexp.MustCompile("[Yy]|[Yy][Ee][Ss]")
    176         re_no  := regexp.MustCompile("[Nn]|[Nn][Oo]")
    177         if re_yes.Match([]byte(exhaustVal)) {
    178                 exhaust = true
    179         } else if re_no.Match([]byte(exhaustVal)) {
    180                 exhaust = false
    181         } else {
    182                 fmt.Fprintf(os.Stderr, "Unrecognized exhaust(-e) option '%s'\n", exhaustVal)
    183                 os.Exit(1)
    184         }
    185 
     160        defer bench_init()()
     161
     162        exhaust := *exhaustOpt;
    186163        if clock_mode {
    187                 fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode\n")
     164                fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode")
    188165                os.Exit(1)
    189166        }
     
    238215                ws = "no"
    239216        }
    240         p.Printf("Duration (ms)           : %d\n", delta.Milliseconds() )
     217        p.Printf("Duration (ms)           : %f\n", delta.Milliseconds() )
    241218        p.Printf("Number of processors    : %d\n", nprocs )
    242219        p.Printf("Number of threads       : %d\n", nthreads )
    243         p.Printf("Total Operations(ops)   : %15d\n", (leader.idx - 1) )
     220        p.Printf("Total Operations(ops)   : %15d\n", stop_count )
    244221        p.Printf("Threads parking on wait : %s\n", ws)
    245222        p.Printf("Rechecking              : %d\n", rechecks )
    246         p.Printf("ns per transfer         : %f\n", float64(delta.Nanoseconds()) / float64(leader.idx) )
    247 }
     223}
  • benchmark/readyQ/transfer.rs

    r74ec742 r29d8c02  
    66use std::hint;
    77use std::sync::Arc;
    8 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
     8use std::sync::atomic::{AtomicUsize, Ordering};
    99use std::time::{Instant,Duration};
    1010
     
    4444                        match val {
    4545                                "yes" => true,
    46                                 "Y" => true,
    47                                 "y" => true,
    4846                                "no"  => false,
    49                                 "N"  => false,
    50                                 "n"  => false,
    5147                                "maybe" | "I don't know" | "Can you repeat the question?" => {
    5248                                        eprintln!("Lines for 'Malcolm in the Middle' are not acceptable values of parameter 'exhaust'");
     
    6864        id: AtomicUsize,
    6965        idx: AtomicUsize,
    70         estop: AtomicBool,
    7166        seed: u128,
    7267}
     
    7772                        id: AtomicUsize::new(nthreads),
    7873                        idx: AtomicUsize::new(0),
    79                         estop: AtomicBool::new(false),
    8074                        seed: process::id() as u128
    8175                };
     
    106100}
    107101
    108 fn waitgroup(leader: &LeaderInfo, idx: usize, threads: &Vec<Arc<MyThread>>, main_sem: &sync::Semaphore) {
     102fn waitgroup(idx: usize, threads: &Vec<Arc<MyThread>>) {
    109103        let start = Instant::now();
    110         'outer: for t in threads {
     104        for t in threads {
    111105                debug!( "Waiting for :{} ({})", t.id, t.idx.load(Ordering::Relaxed) );
    112106                while t.idx.load(Ordering::Relaxed) != idx {
     
    114108                        if start.elapsed() > Duration::from_secs(5) {
    115109                                eprintln!("Programs has been blocked for more than 5 secs");
    116                                 leader.estop.store(true, Ordering::Relaxed);
    117                                 main_sem.add_permits(1);
    118                                 break 'outer;
     110                                std::process::exit(1);
    119111                        }
    120112                }
     
    139131        leader.idx.store(nidx, Ordering::Relaxed);
    140132
    141         if nidx as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) {
     133        if nidx as u64 > exp.stop_count {
    142134                debug!( "Leader {} done", this.id);
    143135                main_sem.add_permits(1);
     
    147139        debug!( "====================\nLeader no {} : {}", nidx, this.id);
    148140
    149         waitgroup(leader, nidx, threads, main_sem);
     141        waitgroup(nidx, threads);
    150142
    151143        leader.next( threads.len() );
     
    200192                        wait( exhaust, &leader, &threads[me], &mut rechecks ).await;
    201193                }
    202                 if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) { break; }
     194                if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count { break; }
    203195        }
    204196
     
    281273        println!("Number of processors    : {}", (nprocs).to_formatted_string(&Locale::en));
    282274        println!("Number of threads       : {}", (nthreads).to_formatted_string(&Locale::en));
    283         println!("Total Operations(ops)   : {:>15}", (leader.idx.load(Ordering::Relaxed) - 1).to_formatted_string(&Locale::en));
     275        println!("Total Operations(ops)   : {:>15}", (exp.stop_count).to_formatted_string(&Locale::en));
    284276        println!("Threads parking on wait : {}", if exhaust { "yes" } else { "no" });
    285277        println!("Rechecking              : {}", rechecks );
    286         println!("ns per transfer         : {}", ((duration.as_nanos() as f64) / leader.idx.load(Ordering::Relaxed) as f64));
    287 
    288 }
     278}
  • benchmark/readyQ/yield.cfa

    r74ec742 r29d8c02  
    1 #include "rq_bench.hfa"
     1#include <stdlib.h>
     2#include <stdio.h>
     3#include <string.h>
     4#include <limits.h>
     5
     6extern "C" {
     7        #include <locale.h>
     8        #include <getopt.h>
     9}
     10
     11#include <unistd.h>
     12
     13#include <clock.hfa>
     14#include <time.hfa>
     15#include <stats.hfa>
     16
     17#include "../benchcltr.hfa"
     18
     19extern bool traceHeapOn();
     20
     21
     22volatile bool run = false;
     23volatile unsigned long long global_counter;
    224
    325thread __attribute__((aligned(128))) Yielder {
    4         unsigned long long count;
     26        unsigned long long counter;
    527};
    628void ?{}( Yielder & this ) {
    7         ((thread&)this){ "Yielder Thread", bench_cluster };
    8         this.count = 0;
     29        this.counter = 0;
     30        ((thread&)this){ "Yielder Thread", *the_benchmark_cluster };
    931}
    1032
    1133void main( Yielder & this ) {
    1234        park();
    13         for() {
     35        /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
     36
     37        while(__atomic_load_n(&run, __ATOMIC_RELAXED)) {
    1438                yield();
    15                 this.count++;
    16                 if( clock_mode && stop) break;
    17                 if(!clock_mode && this.count >= stop_count) break;
     39                this.counter++;
    1840        }
    19 
    20         __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST);
     41        __atomic_fetch_add(&global_counter, this.counter, __ATOMIC_SEQ_CST);
    2142}
    2243
    2344int main(int argc, char * argv[]) {
     45        unsigned num_io = 1;
     46        io_context_params params;
     47
    2448        cfa_option opt[] = {
    25                 BENCH_OPT
     49                BENCH_OPT_CFA
    2650        };
    27         BENCH_OPT_PARSE("cforall yield benchmark");
     51        int opt_cnt = sizeof(opt) / sizeof(cfa_option);
     52
     53        char **left;
     54        parse_args( argc, argv, opt, opt_cnt, "[OPTIONS]...\ncforall yield benchmark", left );
    2855
    2956        {
    30                 unsigned long long global_counter = 0;
     57                printf("Running %d threads on %d processors for %f seconds\n", nthreads, nprocs, duration);
    3158
    3259                Time start, end;
    33                 BenchCluster bc = { nprocs };
     60                BenchCluster cl = { num_io, params, CFA_STATS_READY_Q };
    3461                {
    35                         threads_left = nthreads;
    36                         Yielder threads[nthreads];
    37                         printf("Starting\n");
     62                        BenchProc procs[nprocs];
     63                        {
     64                                Yielder threads[nthreads];
     65                                printf("Starting\n");
    3866
    39                         bool is_tty = isatty(STDOUT_FILENO);
    40                         start = timeHiRes();
     67                                bool is_tty = isatty(STDOUT_FILENO);
     68                                start = timeHiRes();
     69                                run = true;
    4170
    42                         for(i; nthreads) {
    43                                 unpark( threads[i] );
    44                         }
    45                         wait(start, is_tty);
     71                                for(i; nthreads) {
     72                                        unpark( threads[i] );
     73                                }
     74                                wait(duration, start, end, is_tty);
    4675
    47                         stop = true;
    48                         end = timeHiRes();
    49                         printf("\nDone\n");
    50 
    51                         for(i; nthreads) {
    52                                 Yielder & y = join( threads[i] );
    53                                 global_counter += y.count;
     76                                run = false;
     77                                end = timeHiRes();
     78                                printf("\nDone\n");
    5479                        }
    5580                }
    5681
    57                 printf("Duration (ms)        : %'ld\n", (end - start)`dms);
    58                 printf("Number of processors : %'d\n", nprocs);
    59                 printf("Number of threads    : %'d\n", nthreads);
    60                 printf("Total Operations(ops): %'15llu\n", global_counter);
    61                 printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / (end - start)`s);
    62                 printf("ns per ops           : %'18.2lf\n", (end - start)`dns / global_counter);
    63                 printf("Ops per threads      : %'15llu\n", global_counter / nthreads);
    64                 printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
    65                 printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s);
    66                 printf("ns per ops/procs     : %'18.2lf\n", (end - start)`dns / (global_counter / nprocs));
     82                printf("Duration (ms)       : %'ld\n", (end - start)`dms);
     83                printf("Number of processors: %'d\n", nprocs);
     84                printf("Number of threads   : %'d\n", nthreads);
     85                printf("Total yields        : %'15llu\n", global_counter);
     86                printf("Yields per second   : %'18.2lf\n", ((double)global_counter) / (end - start)`s);
     87                printf("ns per yields       : %'18.2lf\n", ((double)(end - start)`ns) / global_counter);
     88                printf("Yields per procs    : %'15llu\n", global_counter / nprocs);
     89                printf("Yields/sec/procs    : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s);
     90                printf("ns per yields/procs : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs));
    6791                fflush(stdout);
    6892        }
  • benchmark/readyQ/yield.cpp

    r74ec742 r29d8c02  
    1 #include "rq_bench.hpp"
    2 #include <libfibre/fibre.h>
     1#include <cassert>
     2#include <cstdlib>
     3#include <cstdio>
     4#include <cstring>
     5#include <climits>
     6
     7extern "C" {
     8        #include <locale.h>
     9        #include <getopt.h>
     10}
     11
     12#include <unistd.h>
     13
     14#include <chrono>
     15
     16using Clock = std::chrono::high_resolution_clock;
     17using duration_t = std::chrono::duration<double>;
     18using std::chrono::nanoseconds;
     19
     20
     21template<typename Ratio, typename T>
     22T duration_cast(T seconds) {
     23        return std::chrono::duration_cast<std::chrono::duration<T, Ratio>>(std::chrono::duration<T>(seconds)).count();
     24}
    325
    426volatile bool run = false;
    527volatile unsigned long long global_counter;
    628
     29#include "libfibre/fibre.h"
    730
    8 void fibre_main() {
    9         fibre_park();
    10         unsigned long long count = 0;
    11         for(;;) {
    12                 Fibre::yield();
    13                 count++;
    14                 if( clock_mode && stop) break;
    15                 if(!clock_mode && count >= stop_count) break;
     31FredBarrier * barrier;
     32struct __attribute__((aligned(128))) counter_t {
     33        int value = 0;
     34};
     35
     36void fibre_main( counter_t * counter ) {
     37        barrier->wait();
     38        // /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
     39
     40        while(__atomic_load_n(&run, __ATOMIC_RELAXED)) {
     41                Fibre::forceYield();
     42                // fibre_yield();
     43                counter->value++;
    1644        }
    17 
    18         __atomic_fetch_add(&global_counter, count, __ATOMIC_SEQ_CST);
    19         __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST);
     45        __atomic_fetch_add(&global_counter, counter->value, __ATOMIC_SEQ_CST);
    2046}
    2147
    2248int main(int argc, char * argv[]) {
    23         option_t opt[] = {
    24                 BENCH_OPT
    25         };
    26         BENCH_OPT_PARSE("libfibre yield benchmark");
     49        double duration = 5;
     50        int nprocs = 1;
     51        int nthreads = 1;
     52
     53        std::cout.imbue(std::locale(""));
     54        setlocale(LC_ALL, "");
     55
     56        for(;;) {
     57                static struct option options[] = {
     58                        {"duration",  required_argument, 0, 'd'},
     59                        {"nprocs",    required_argument, 0, 'p'},
     60                        {"nthreads",  required_argument, 0, 't'},
     61                        {0, 0, 0, 0}
     62                };
     63
     64                int idx = 0;
     65                int opt = getopt_long(argc, argv, "d:p:t:", options, &idx);
     66
     67                const char * arg = optarg ? optarg : "";
     68                char * end;
     69                switch(opt) {
     70                        case -1:
     71                                goto run;
     72                        // Numeric Arguments
     73                        case 'd':
     74                                duration = strtod(arg, &end);
     75                                if(*end != '\0') {
     76                                        fprintf(stderr, "Duration must be a valid double, was %s\n", arg);
     77                                        goto usage;
     78                                }
     79                                break;
     80                        case 't':
     81                                nthreads = strtoul(arg, &end, 10);
     82                                if(*end != '\0' || nthreads < 1) {
     83                                        fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg);
     84                                        goto usage;
     85                                }
     86                                break;
     87                        case 'p':
     88                                nprocs = strtoul(arg, &end, 10);
     89                                if(*end != '\0' || nprocs < 1) {
     90                                        fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg);
     91                                        goto usage;
     92                                }
     93                                break;
     94                        // Other cases
     95                        default: /* ? */
     96                                fprintf( stderr, "Unkown option '%c'\n", opt);
     97                        usage:
     98                                fprintf( stderr, "Usage: %s [options]\n", argv[0]);
     99                                fprintf( stderr, "\n" );
     100                                fprintf( stderr, "  -d, --duration=DURATION  Duration of the experiment, in seconds\n" );
     101                                fprintf( stderr, "  -t, --nthreads=NTHREADS  Number of kernel threads\n" );
     102                                fprintf( stderr, "  -q, --nqueues=NQUEUES    Number of queues per threads\n" );
     103                                exit(1);
     104                }
     105        }
     106        run:
    27107
    28108        {
    29109                printf("Running %d threads on %d processors for %lf seconds\n", nthreads, nprocs, duration);
    30110
    31                 FibreInit(1, nprocs);
    32                 uint64_t start, end;
     111                FibreInit();
     112                barrier = new FredBarrier(nthreads + 1);
    33113                {
    34                         threads_left = nthreads;
    35                         Fibre * threads[nthreads];
    36                         for(unsigned i = 0; i < nthreads; i++) {
    37                                 threads[i] = new Fibre();
    38                                 threads[i]->run(fibre_main);
    39                         }
    40                         printf("Starting\n");
    41                         bool is_tty = isatty(STDOUT_FILENO);
    42                         start = timeHiRes();
     114                        Context::CurrCluster().addWorkers(nprocs);
     115                        {
     116                                counter_t counters[nthreads];
     117                                Fibre threads[nthreads];
     118                                for(int i = 0; i < nthreads; i++) {
     119                                        threads[i].run(fibre_main, &counters[i]);
     120                                }
     121                                printf("Starting\n");
     122                                bool is_tty = isatty(STDOUT_FILENO);
     123                                auto before = Clock::now();
     124                                run = true;
    43125
    44                         for(unsigned i = 0; i < nthreads; i++ ) {
    45                                 fibre_unpark( threads[i] );
    46                         }
    47                         wait<Fibre>(start, is_tty);
     126                                barrier->wait();
     127                                for(;;) {
     128                                        usleep(500'000);
     129                                        auto now = Clock::now();
     130                                        duration_t durr = now - before;
     131                                        if( durr.count() > duration ) {
     132                                                break;
     133                                        }
     134                                        if(is_tty) {
     135                                                std::cout << "\r" << std::setprecision(4) << durr.count();
     136                                                std::cout.flush();
     137                                        }
     138                                }
    48139
    49                         stop = true;
    50                         end = timeHiRes();
    51                         for(unsigned i = 0; i < nthreads; i++ ) {
    52                                 fibre_join( threads[i], nullptr );
     140                                auto after = Clock::now();
     141                                duration_t durr = after - before;
     142                                duration = durr.count();
     143                                run = false;
     144                                printf("\nDone\n");
     145                                for(auto & thread : threads) {
     146                                        thread.join();
     147                                }
     148
     149                                // for(const auto & counter : counters) {
     150                                //      std::cout << counter.value << std::endl;
     151                                // }
    53152                        }
    54153                }
    55154
    56                 printf("Duration (ms)        : %'ld\n", to_miliseconds(end - start));
    57                 printf("Number of processors : %'d\n", nprocs);
    58                 printf("Number of threads    : %'d\n", nthreads);
    59                 printf("Total Operations(ops): %'15llu\n", global_counter);
    60                 printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / to_fseconds(end - start));
    61                 printf("ns per ops           : %'18.2lf\n", ((double)(end - start)) / global_counter);
    62                 printf("Ops per threads      : %'15llu\n", global_counter / nthreads);
    63                 printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
    64                 printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / to_fseconds(end - start));
    65                 printf("ns per ops/procs     : %'18.2lf\n", ((double)(end - start)) / (global_counter / nprocs));
    66                 fflush(stdout);
     155                auto dur_nano = duration_cast<std::nano>(duration);
     156                auto dur_dms  = duration_cast<std::milli>(duration);
     157
     158                printf("Duration (ms)       : %'.2lf\n", dur_dms );
     159                printf("Total yields        : %'15llu\n", global_counter );
     160                printf("Yields per procs    : %'15llu\n", global_counter / nprocs );
     161                printf("Yields per second   : %'18.2lf\n", ((double)global_counter) / duration );
     162                printf("Yields/sec/procs    : %'18.2lf\n", (((double)global_counter) / nprocs) / duration );
     163                printf("ns per yields       : %'18.2lf\n", dur_nano / global_counter );
     164                printf("ns per yields/procs : %'18.2lf\n", dur_nano / (global_counter / nprocs) );
     165
    67166        }
    68167}
  • benchmark/readyQ/yield.rs

    r74ec742 r29d8c02  
    9090        });
    9191
    92         println!("Duration (ms)        : {}", (duration.as_millis()).to_formatted_string(&Locale::en));
    93         println!("Number of processors : {}", (nprocs).to_formatted_string(&Locale::en));
    94         println!("Number of threads    : {}", (nthreads).to_formatted_string(&Locale::en));
    95         println!("Total Operations(ops): {:>15}", (global_counter).to_formatted_string(&Locale::en));
    96         println!("Ops per second       : {:>15}", (((global_counter as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));
    97         println!("ns per ops           : {:>15}", ((duration.as_nanos() as f64 / global_counter as f64) as u64).to_formatted_string(&Locale::en));
    98         println!("Ops per threads      : {:>15}", (global_counter / nthreads as u64).to_formatted_string(&Locale::en));
    99         println!("Ops per procs        : {:>15}", (global_counter / nprocs as u64).to_formatted_string(&Locale::en));
    100         println!("Ops/sec/procs        : {:>15}", ((((global_counter as f64) / nprocs as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));
    101         println!("ns per ops/procs    : {:>15}", ((duration.as_nanos() as f64 / (global_counter as f64 / nprocs as f64)) as u64).to_formatted_string(&Locale::en));
     92        println!("Duration (ms)       : {}", (duration.as_millis()).to_formatted_string(&Locale::en));
     93        println!("Number of processors: {}", (nprocs).to_formatted_string(&Locale::en));
     94        println!("Number of threads   : {}", (nthreads).to_formatted_string(&Locale::en));
     95        println!("Total yields        : {:>15}", (global_counter).to_formatted_string(&Locale::en));
     96        println!("Yields per second   : {:>15}", (((global_counter as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));
     97        println!("ns per yields       : {:>15}", ((duration.as_nanos() as f64 / global_counter as f64) as u64).to_formatted_string(&Locale::en));
     98        println!("Yields per threads  : {:>15}", (global_counter / nthreads as u64).to_formatted_string(&Locale::en));
     99        println!("Yields per procs    : {:>15}", (global_counter / nprocs as u64).to_formatted_string(&Locale::en));
     100        println!("Yields/sec/procs    : {:>15}", ((((global_counter as f64) / nprocs as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));
     101        println!("ns per yields/procs : {:>15}", ((duration.as_nanos() as f64 / (global_counter as f64 / nprocs as f64)) as u64).to_formatted_string(&Locale::en));
    102102}
  • benchmark/rmit.py

    r74ec742 r29d8c02  
    4646                pass
    4747
    48         if values.startswith('\\'):
    49                 return key, values[1:].split(',')
    50         elif re.search("^[0-9-,]+$", values):
     48        if re.search("^[0-9-,]+$", values):
    5149                values = parse_range(values)
    5250                return key, [v for v in values]
     
    6563        return eval(fmt)
    6664
    67 # Evaluate all the options
    68 # options can be of the for key = val or key = some_math(other_key)
    69 # produce a list of all the options to replace some_math(other_key) with actual value
    7065def eval_options(opts):
    71         # Find all the options with dependencies
    7266        dependents = [d for d in opts.values() if type(d) is DependentOpt]
    73 
    74         # we need to find all the straglers
    7567        processed = []
    76 
    77         # extract all the necessary inputs
    78         input_keys = {}
     68        nopts = []
    7969        for d in dependents:
    80                 # Mark the dependent as seen
    8170                processed.append(d.key)
    82 
    83                 # process each of the dependencies
     71                lists = []
    8472                for dvar in d.vars:
    85                         # Check that it depends on something that exists
    8673                        if not dvar in opts.keys():
    8774                                print('ERROR: extra pattern option {}:{} uses unknown key {}'.format(d.key,d.value,dvar), file=sys.stderr)
    8875                                sys.exit(1)
    8976
    90                         # Check that it's not nested
    91                         if type(dvar) is DependentOpt:
    92                                 print('ERROR: dependent options cannot be nested {}:{} uses key {}'.format(d.key,d.value,dvar), file=sys.stderr)
    93                                 sys.exit(1)
    94 
    95                         # Add the values to the input keys
    96                         if dvar not in input_keys:
    97                                 input_keys[dvar] = opts[dvar]
    98                         else :
    99                                 if input_keys[dvar] != opts[dvar]:
    100                                         print('INTERNAL ERROR: repeat input do not match {}:{} vs {}'.format(dvar,opts[dvar],input_keys[dvar]), file=sys.stderr)
    101                                         sys.exit(1)
    102 
    103                         # Mark the input as seen
     77                        lists.append([(dvar, o) for o in opts[dvar]])
    10478                        processed.append(dvar)
    10579
    106         # add in all the straglers they should cause too many problems
    107         for k, v in opts.items():
    108                 if type(v) is DependentOpt:
    109                         continue
    110 
    111                 if k in processed:
    112                         # consistency check
    113                         if k not in input_keys:
    114                                 print('INTERNAL ERROR: key \'{}\' marked as processed but not in input_keys'.format(k), file=sys.stderr)
    115                                 sys.exit(1)
    116                         continue
    117 
    118                 # consistency check
    119                 if k in input_keys:
    120                         print('INTERNAL ERROR: key \'{}\' in input_keys but not marked as processed'.format(k), file=sys.stderr)
    121                         sys.exit(1)
    122 
    123                 # add the straggler
    124                 input_keys[k] = v
    125 
    126         # flatten the dict into a list of pairs so it's easier to work with
    127         input_list = []
    128         for k, v in input_keys.items():
    129                 input_list.append([(k, o) for o in v])
    130 
    131         # evaluate all the dependents
    132         # they are not allowed to produce new values so it's a one-to-one mapping from here
    133         evaluated = []
    134         for inputs in list(itertools.product(*input_list)):
    135                 this_eval = list(inputs)
    136                 for d in dependents:
    137                         this_eval.append((d.key, eval_one(d.value, inputs)))
    138 
    139                 evaluated.append(this_eval)
    140 
    141         # reformat everything to a list of arguments
    142         formated = []
    143         for o in evaluated:
    144                 inner = []
    145                 for k,v in o:
    146                         inner.append("-{}".format(k))
    147                         inner.append("{}".format(v))
    148 
    149                 # print(inner)
    150                 formated.append(inner)
    151 
    152         return formated
     80                kopt = []
     81                for vals in list(itertools.product(*lists)):
     82                        res = ['-{}'.format(d.key), "{}".format(eval_one(d.value, vals))]
     83                        for k, v in vals:
     84                                res.extend(['-{}'.format(k), "{}".format(v)])
     85                        kopt.append(res)
     86                nopts.append(kopt)
     87
     88
     89        for k, vals in opts.items():
     90                if k not in processed:
     91                        kopt = []
     92                        for v in vals:
     93                                kopt.append(['-{}'.format(k), "{}".format(v)])
     94                        nopts.append(kopt)
     95
     96        return nopts
    15397
    15498# returns the first option with key 'opt'
     
    178122        known_hosts = {
    179123                "jax": {
    180                         range(  1,  25) : "48-71",
    181                         range( 25,  49) : "48-71,144-167",
    182                         range( 49,  97) : "48-95,144-191",
    183                         range( 97, 145) : "24-95,120-191",
    184                         range(145, 193) : "0-95,96-191",
     124                        range(  1,  24) : "48-71",
     125                        range( 25,  48) : "48-71,144-167",
     126                        range( 49,  96) : "48-95,144-191",
     127                        range( 97, 144) : "24-95,120-191",
     128                        range(145, 192) : "0-95,96-191",
    185129                },
    186130        }
     
    240184
    241185        except:
     186                print('ERROR: invalid arguments', file=sys.stderr)
     187                parser.print_help(sys.stderr)
    242188                sys.exit(1)
    243189
     
    269215        # Figure out all the combinations to run
    270216        actions = []
    271         for p in itertools.product(range(options.trials), commands, opts):
     217        for p in itertools.product(range(options.trials), commands, *opts):
    272218                act = [p[1]]
    273219                for o in p[2:]:
     
    335281
    336282        if options.file != sys.stdout:
    337                 print("Done                                                                                ")
     283                print("Done");                                                                                ")
  • doc/theses/thierry_delisle_PhD/thesis/Makefile

    r74ec742 r29d8c02  
    3737        emptytree \
    3838        fairness \
    39         idle \
    40         idle1 \
    41         idle2 \
    42         idle_state \
    4339        io_uring \
    4440        pivot_ring \
     
    4642        cycle \
    4743        result.cycle.jax.ops \
    48         result.yield.jax.ops \
    49         result.churn.jax.ops \
    50         result.cycle.jax.ns \
    51         result.yield.jax.ns \
    52         result.churn.jax.ns \
    53         result.cycle.low.jax.ops \
    54         result.yield.low.jax.ops \
    55         result.churn.low.jax.ops \
    56         result.cycle.low.jax.ns \
    57         result.yield.low.jax.ns \
    58         result.churn.low.jax.ns \
    59         result.memcd.updt.qps \
    60         result.memcd.updt.lat \
    61         result.memcd.rate.qps \
    62         result.memcd.rate.99th \
    6344}
    6445
     
    135116        python3 $< $@
    136117
    137 cycle_jax_ops_FLAGS = --MaxY=120000000
    138 cycle_low_jax_ops_FLAGS = --MaxY=120000000
    139 cycle_jax_ns_FLAGS = --MaxY=2000
    140 cycle_low_jax_ns_FLAGS = --MaxY=2000
     118build/result.%.ns.svg : data/% | ${Build}
     119        ../../../../benchmark/plot.py -f $< -o $@ -y "ns per ops"
    141120
    142 yield_jax_ops_FLAGS = --MaxY=150000000
    143 yield_low_jax_ops_FLAGS = --MaxY=150000000
    144 yield_jax_ns_FLAGS = --MaxY=1500
    145 yield_low_jax_ns_FLAGS = --MaxY=1500
    146 
    147 build/result.%.ns.svg : data/% Makefile | ${Build}
    148         ../../../../benchmark/plot.py -f $< -o $@ -y "ns per ops/procs" $($(subst .,_,$*)_ns_FLAGS)
    149 
    150 build/result.%.ops.svg : data/% Makefile | ${Build}
    151         ../../../../benchmark/plot.py -f $< -o $@ -y "Ops per second" $($(subst .,_,$*)_ops_FLAGS)
    152 
    153 build/result.memcd.updt.qps.svg : data/memcd.updt Makefile | ${Build}
    154         ../../../../benchmark/plot.py -f $< -o $@ -y "Actual QPS" -x "Update Ratio"
    155 
    156 build/result.memcd.updt.lat.svg : data/memcd.updt Makefile | ${Build}
    157         ../../../../benchmark/plot.py -f $< -o $@ -y "Average Read Latency" -x "Update Ratio"
    158 
    159 build/result.memcd.rate.qps.svg : data/memcd.rate Makefile | ${Build}
    160         ../../../../benchmark/plot.py -f $< -o $@ -y "Actual QPS" -x "Target QPS"
    161 
    162 build/result.memcd.rate.99th.svg : data/memcd.rate Makefile | ${Build}
    163         ../../../../benchmark/plot.py -f $< -o $@ -y "Tail Read Latency" -x "Target QPS"
     121build/result.%.ops.svg : data/% | ${Build}
     122        ../../../../benchmark/plot.py -f $< -o $@ -y "Ops per second"
    164123
    165124## pstex with inverted colors
  • doc/theses/thierry_delisle_PhD/thesis/data/cycle.jax

    r74ec742 r29d8c02  
    1 [["rdq-cycle-go", "./rdq-cycle-go -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10001.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 1138076440.0, "Ops per second": 113792094.48, "ns per ops": 8.79, "Ops per threads": 94839.0, "Ops per procs": 47419851.0, "Ops/sec/procs": 4741337.27, "ns per ops/procs": 210.91}],["rdq-cycle-go", "./rdq-cycle-go -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 200285.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 17638575791.0, "Ops per second": 88067238.72, "ns per ops": 11.35, "Ops per threads": 2204821.0, "Ops per procs": 1102410986.0, "Ops/sec/procs": 5504202.42, "ns per ops/procs": 181.68}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10100.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 54856916.0, "Ops per second": 5485691.0, "ns per ops": 184.0, "Ops per threads": 109713.0, "Ops per procs": 54856916.0, "Ops/sec/procs": 5485691.0, "ns per ops/procs": 184.0}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10025.449006, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 558836360.0, "Total blocks": 558836360.0, "Ops per second": 55741778.71, "ns per ops": 17.94, "Ops per threads": 69854.0, "Ops per procs": 34927272.0, "Ops/sec/procs": 3483861.17, "ns per ops/procs": 287.04}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10038.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 58647049.0, "Total blocks": 58647049.0, "Ops per second": 5842287.68, "ns per ops": 171.17, "Ops per threads": 7330.0, "Ops per procs": 3665440.0, "Ops/sec/procs": 365142.98, "ns per ops/procs": 2738.65}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10003.489711, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 728096996.0, "Total blocks": 728096996.0, "Ops per second": 72784299.98, "ns per ops": 13.74, "Ops per threads": 60674.0, "Ops per procs": 30337374.0, "Ops/sec/procs": 3032679.17, "ns per ops/procs": 329.74}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10021.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 63157049.0, "Total blocks": 63157049.0, "Ops per second": 6302255.13, "ns per ops": 158.67, "Ops per threads": 15789.0, "Ops per procs": 7894631.0, "Ops/sec/procs": 787781.89, "ns per ops/procs": 1269.39}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10009.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 62412200.0, "Total blocks": 62411700.0, "Ops per second": 6235572.31, "ns per ops": 160.37, "Ops per threads": 124824.0, "Ops per procs": 62412200.0, "Ops/sec/procs": 6235572.31, "ns per ops/procs": 160.37}],["rdq-cycle-go", "./rdq-cycle-go -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10000.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 464608617.0, "Ops per second": 46457191.42, "ns per ops": 21.53, "Ops per threads": 116152.0, "Ops per procs": 58076077.0, "Ops/sec/procs": 5807148.93, "ns per ops/procs": 172.2}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10099.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 391521066.0, "Ops per second": 39152106.0, "ns per ops": 25.0, "Ops per threads": 97880.0, "Ops per procs": 48940133.0, "Ops/sec/procs": 4894013.0, "ns per ops/procs": 206.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10099.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 963549550.0, "Ops per second": 96354955.0, "ns per ops": 10.0, "Ops per threads": 80295.0, "Ops per procs": 40147897.0, "Ops/sec/procs": 4014789.0, "ns per ops/procs": 251.0}],["rdq-cycle-go", "./rdq-cycle-go -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10001.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 867718190.0, "Ops per second": 86761170.55, "ns per ops": 11.53, "Ops per threads": 108464.0, "Ops per procs": 54232386.0, "Ops/sec/procs": 5422573.16, "ns per ops/procs": 184.41}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10100.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 962016289.0, "Ops per second": 96201628.0, "ns per ops": 10.0, "Ops per threads": 80168.0, "Ops per procs": 40084012.0, "Ops/sec/procs": 4008401.0, "ns per ops/procs": 251.0}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10016.837824, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 54738237.0, "Total blocks": 54737741.0, "Ops per second": 5464622.46, "ns per ops": 183.0, "Ops per threads": 109476.0, "Ops per procs": 54738237.0, "Ops/sec/procs": 5464622.46, "ns per ops/procs": 183.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10099.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 731309408.0, "Ops per second": 73130940.0, "ns per ops": 13.0, "Ops per threads": 91413.0, "Ops per procs": 45706838.0, "Ops/sec/procs": 4570683.0, "ns per ops/procs": 220.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10100.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 739772688.0, "Ops per second": 73977268.0, "ns per ops": 13.0, "Ops per threads": 92471.0, "Ops per procs": 46235793.0, "Ops/sec/procs": 4623579.0, "ns per ops/procs": 218.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10100.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 391449785.0, "Ops per second": 39144978.0, "ns per ops": 25.0, "Ops per threads": 97862.0, "Ops per procs": 48931223.0, "Ops/sec/procs": 4893122.0, "ns per ops/procs": 206.0}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10048.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 57239183.0, "Total blocks": 57239183.0, "Ops per second": 5696211.13, "ns per ops": 175.56, "Ops per threads": 4769.0, "Ops per procs": 2384965.0, "Ops/sec/procs": 237342.13, "ns per ops/procs": 4213.33}],["rdq-cycle-go", "./rdq-cycle-go -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10000.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 55248375.0, "Ops per second": 5524562.87, "ns per ops": 181.01, "Ops per threads": 110496.0, "Ops per procs": 55248375.0, "Ops/sec/procs": 5524562.87, "ns per ops/procs": 181.01}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10021.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 61553053.0, "Total blocks": 61553053.0, "Ops per second": 6142186.88, "ns per ops": 162.81, "Ops per threads": 15388.0, "Ops per procs": 7694131.0, "Ops/sec/procs": 767773.36, "ns per ops/procs": 1302.47}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10008.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 62811642.0, "Total blocks": 62811142.0, "Ops per second": 6275517.47, "ns per ops": 159.35, "Ops per threads": 125623.0, "Ops per procs": 62811642.0, "Ops/sec/procs": 6275517.47, "ns per ops/procs": 159.35}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10018.820873, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 260866706.0, "Total blocks": 260862710.0, "Ops per second": 26037665.44, "ns per ops": 38.41, "Ops per threads": 65216.0, "Ops per procs": 32608338.0, "Ops/sec/procs": 3254708.18, "ns per ops/procs": 307.25}],["rdq-cycle-go", "./rdq-cycle-go -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10000.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 874581175.0, "Ops per second": 87449851.2, "ns per ops": 11.44, "Ops per threads": 109322.0, "Ops per procs": 54661323.0, "Ops/sec/procs": 5465615.7, "ns per ops/procs": 182.96}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10099.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 55228782.0, "Ops per second": 5522878.0, "ns per ops": 182.0, "Ops per threads": 110457.0, "Ops per procs": 55228782.0, "Ops/sec/procs": 5522878.0, "ns per ops/procs": 182.0}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10009.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 62564955.0, "Total blocks": 62564455.0, "Ops per second": 6250797.96, "ns per ops": 159.98, "Ops per threads": 125129.0, "Ops per procs": 62564955.0, "Ops/sec/procs": 6250797.96, "ns per ops/procs": 159.98}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10100.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 738848909.0, "Ops per second": 73884890.0, "ns per ops": 13.0, "Ops per threads": 92356.0, "Ops per procs": 46178056.0, "Ops/sec/procs": 4617805.0, "ns per ops/procs": 218.0}],["rdq-cycle-go", "./rdq-cycle-go -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10001.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 1131221613.0, "Ops per second": 113108175.94, "ns per ops": 8.84, "Ops per threads": 94268.0, "Ops per procs": 47134233.0, "Ops/sec/procs": 4712840.66, "ns per ops/procs": 212.19}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10008.209159, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 729328104.0, "Total blocks": 729328099.0, "Ops per second": 72872987.81, "ns per ops": 13.72, "Ops per threads": 60777.0, "Ops per procs": 30388671.0, "Ops/sec/procs": 3036374.49, "ns per ops/procs": 329.34}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10099.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 961002611.0, "Ops per second": 96100261.0, "ns per ops": 10.0, "Ops per threads": 80083.0, "Ops per procs": 40041775.0, "Ops/sec/procs": 4004177.0, "ns per ops/procs": 252.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10099.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 390098231.0, "Ops per second": 39009823.0, "ns per ops": 25.0, "Ops per threads": 97524.0, "Ops per procs": 48762278.0, "Ops/sec/procs": 4876227.0, "ns per ops/procs": 207.0}],["rdq-cycle-tokio", "./rdq-cycle-tokio -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10100.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 55237591.0, "Ops per second": 5523759.0, "ns per ops": 182.0, "Ops per threads": 110475.0, "Ops per procs": 55237591.0, "Ops/sec/procs": 5523759.0, "ns per ops/procs": 182.0}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10016.576699, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 54510321.0, "Total blocks": 54509820.0, "Ops per second": 5442011.04, "ns per ops": 183.76, "Ops per threads": 109020.0, "Ops per procs": 54510321.0, "Ops/sec/procs": 5442011.04, "ns per ops/procs": 183.76}],["rdq-cycle-go", "./rdq-cycle-go -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10001.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 1135730371.0, "Ops per second": 113558509.97, "ns per ops": 8.81, "Ops per threads": 94644.0, "Ops per procs": 47322098.0, "Ops/sec/procs": 4731604.58, "ns per ops/procs": 211.34}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10039.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 61004037.0, "Total blocks": 61004037.0, "Ops per second": 6076255.04, "ns per ops": 164.58, "Ops per threads": 7625.0, "Ops per procs": 3812752.0, "Ops/sec/procs": 379765.94, "ns per ops/procs": 2633.2}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10004.891999, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 747946345.0, "Total blocks": 747934349.0, "Ops per second": 74758062.86, "ns per ops": 13.38, "Ops per threads": 62328.0, "Ops per procs": 31164431.0, "Ops/sec/procs": 3114919.29, "ns per ops/procs": 321.04}],["rdq-cycle-go", "./rdq-cycle-go -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10000.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 466424792.0, "Ops per second": 46638931.23, "ns per ops": 21.44, "Ops per threads": 116606.0, "Ops per procs": 58303099.0, "Ops/sec/procs": 5829866.4, "ns per ops/procs": 171.53}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10086.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 57343570.0, "Total blocks": 57343570.0, "Ops per second": 5685308.81, "ns per ops": 175.89, "Ops per threads": 4778.0, "Ops per procs": 2389315.0, "Ops/sec/procs": 236887.87, "ns per ops/procs": 4221.41}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10020.39533, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 263517289.0, "Total blocks": 263513293.0, "Ops per second": 26298093.07, "ns per ops": 38.03, "Ops per threads": 65879.0, "Ops per procs": 32939661.0, "Ops/sec/procs": 3287261.63, "ns per ops/procs": 304.2}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10025.357431, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 551670395.0, "Total blocks": 551662399.0, "Ops per second": 55027503.89, "ns per ops": 18.17, "Ops per threads": 68958.0, "Ops per procs": 34479399.0, "Ops/sec/procs": 3439218.99, "ns per ops/procs": 290.76}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 24 -d 10 -r 5 -t 2400", {"Duration (ms)": 10050.0, "Number of processors": 24.0, "Number of threads": 12000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 56162695.0, "Total blocks": 56162695.0, "Ops per second": 5588033.65, "ns per ops": 178.95, "Ops per threads": 4680.0, "Ops per procs": 2340112.0, "Ops/sec/procs": 232834.74, "ns per ops/procs": 4294.89}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10019.690183, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 271866976.0, "Total blocks": 271862980.0, "Ops per second": 27133271.69, "ns per ops": 36.86, "Ops per threads": 67966.0, "Ops per procs": 33983372.0, "Ops/sec/procs": 3391658.96, "ns per ops/procs": 294.84}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10057.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 62105022.0, "Total blocks": 62105022.0, "Ops per second": 6175186.04, "ns per ops": 161.94, "Ops per threads": 15526.0, "Ops per procs": 7763127.0, "Ops/sec/procs": 771898.25, "ns per ops/procs": 1295.51}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10025.81217, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 537080117.0, "Total blocks": 537072121.0, "Ops per second": 53569736.59, "ns per ops": 18.67, "Ops per threads": 67135.0, "Ops per procs": 33567507.0, "Ops/sec/procs": 3348108.54, "ns per ops/procs": 298.68}],["rdq-cycle-go", "./rdq-cycle-go -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10000.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 55967030.0, "Ops per second": 5596438.25, "ns per ops": 178.69, "Ops per threads": 111934.0, "Ops per procs": 55967030.0, "Ops/sec/procs": 5596438.25, "ns per ops/procs": 178.69}],["rdq-cycle-go", "./rdq-cycle-go -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10000.0, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 55703320.0, "Ops per second": 5570084.72, "ns per ops": 179.53, "Ops per threads": 111406.0, "Ops per procs": 55703320.0, "Ops/sec/procs": 5570084.72, "ns per ops/procs": 179.53}],["rdq-cycle-go", "./rdq-cycle-go -p 8 -d 10 -r 5 -t 800", {"Duration (ms)": 10000.0, "Number of processors": 8.0, "Number of threads": 4000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 469211793.0, "Ops per second": 46918327.16, "ns per ops": 21.31, "Ops per threads": 117302.0, "Ops per procs": 58651474.0, "Ops/sec/procs": 5864790.9, "ns per ops/procs": 170.51}],["rdq-cycle-cfa", "./rdq-cycle-cfa -p 1 -d 10 -r 5 -t 100", {"Duration (ms)": 10016.545208, "Number of processors": 1.0, "Number of threads": 500.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 54925472.0, "Total blocks": 54924976.0, "Ops per second": 5483474.68, "ns per ops": 182.37, "Ops per threads": 109850.0, "Ops per procs": 54925472.0, "Ops/sec/procs": 5483474.68, "ns per ops/procs": 182.37}],["rdq-cycle-fibre", "./rdq-cycle-fibre -p 16 -d 10 -r 5 -t 1600", {"Duration (ms)": 10037.0, "Number of processors": 16.0, "Number of threads": 8000.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 60770550.0, "Total blocks": 60770550.0, "Ops per second": 6054474.7, "ns per ops": 165.17, "Ops per threads": 7596.0, "Ops per procs": 3798159.0, "Ops/sec/procs": 378404.67, "ns per ops/procs": 2642.67}]]
     1[["rdq-cycle-go", "./rdq-cycle-go -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 43606897.0, "Ops per second": 8720908.73, "ns per ops": 114.67, "Ops per threads": 2180344.0, "Ops per procs": 10901724.0, "Ops/sec/procs": 2180227.18, "ns per ops/procs": 458.67}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5010.922033, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 93993568.0, "Total blocks": 93993209.0, "Ops per second": 18757739.07, "ns per ops": 53.31, "Ops per threads": 1174919.0, "Ops per procs": 5874598.0, "Ops/sec/procs": 1172358.69, "ns per ops/procs": 852.98}],["rdq-cycle-go", "./rdq-cycle-go -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 136763517.0, "Ops per second": 27351079.35, "ns per ops": 36.56, "Ops per threads": 1709543.0, "Ops per procs": 8547719.0, "Ops/sec/procs": 1709442.46, "ns per ops/procs": 584.99}],["rdq-cycle-go", "./rdq-cycle-go -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 27778961.0, "Ops per second": 5555545.09, "ns per ops": 180.0, "Ops per threads": 5555792.0, "Ops per procs": 27778961.0, "Ops/sec/procs": 5555545.09, "ns per ops/procs": 180.0}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5009.290878, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 43976310.0, "Total blocks": 43976217.0, "Ops per second": 8778949.17, "ns per ops": 113.91, "Ops per threads": 2198815.0, "Ops per procs": 10994077.0, "Ops/sec/procs": 2194737.29, "ns per ops/procs": 455.64}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5009.151542, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 44132300.0, "Total blocks": 44132201.0, "Ops per second": 8810334.37, "ns per ops": 113.5, "Ops per threads": 2206615.0, "Ops per procs": 11033075.0, "Ops/sec/procs": 2202583.59, "ns per ops/procs": 454.01}],["rdq-cycle-go", "./rdq-cycle-go -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 46353896.0, "Ops per second": 9270294.11, "ns per ops": 107.87, "Ops per threads": 2317694.0, "Ops per procs": 11588474.0, "Ops/sec/procs": 2317573.53, "ns per ops/procs": 431.49}],["rdq-cycle-go", "./rdq-cycle-go -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 27894379.0, "Ops per second": 5578591.58, "ns per ops": 179.26, "Ops per threads": 5578875.0, "Ops per procs": 27894379.0, "Ops/sec/procs": 5578591.58, "ns per ops/procs": 179.26}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5008.743463, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 32825528.0, "Total blocks": 32825527.0, "Ops per second": 6553645.29, "ns per ops": 152.59, "Ops per threads": 6565105.0, "Ops per procs": 32825528.0, "Ops/sec/procs": 6553645.29, "ns per ops/procs": 152.59}],["rdq-cycle-go", "./rdq-cycle-go -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 138213098.0, "Ops per second": 27640977.5, "ns per ops": 36.18, "Ops per threads": 1727663.0, "Ops per procs": 8638318.0, "Ops/sec/procs": 1727561.09, "ns per ops/procs": 578.85}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5007.914168, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 44109513.0, "Total blocks": 44109419.0, "Ops per second": 8807961.06, "ns per ops": 113.53, "Ops per threads": 2205475.0, "Ops per procs": 11027378.0, "Ops/sec/procs": 2201990.27, "ns per ops/procs": 454.13}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5012.121876, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 94130673.0, "Total blocks": 94130291.0, "Ops per second": 18780603.37, "ns per ops": 53.25, "Ops per threads": 1176633.0, "Ops per procs": 5883167.0, "Ops/sec/procs": 1173787.71, "ns per ops/procs": 851.94}],["rdq-cycle-go", "./rdq-cycle-go -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 140936367.0, "Ops per second": 28185668.38, "ns per ops": 35.48, "Ops per threads": 1761704.0, "Ops per procs": 8808522.0, "Ops/sec/procs": 1761604.27, "ns per ops/procs": 567.66}],["rdq-cycle-go", "./rdq-cycle-go -t 4 -p 4 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 4.0, "Number of threads": 20.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 44279585.0, "Ops per second": 8855475.01, "ns per ops": 112.92, "Ops per threads": 2213979.0, "Ops per procs": 11069896.0, "Ops/sec/procs": 2213868.75, "ns per ops/procs": 451.7}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5008.37392, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 32227534.0, "Total blocks": 32227533.0, "Ops per second": 6434730.02, "ns per ops": 155.41, "Ops per threads": 6445506.0, "Ops per procs": 32227534.0, "Ops/sec/procs": 6434730.02, "ns per ops/procs": 155.41}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 16 -p 16 -d 5 -r 5", {"Duration (ms)": 5011.019789, "Number of processors": 16.0, "Number of threads": 80.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 90600569.0, "Total blocks": 90600173.0, "Ops per second": 18080265.66, "ns per ops": 55.31, "Ops per threads": 1132507.0, "Ops per procs": 5662535.0, "Ops/sec/procs": 1130016.6, "ns per ops/procs": 884.94}],["rdq-cycle-cfa", "./rdq-cycle-cfa -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5008.52474, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 32861776.0, "Total blocks": 32861775.0, "Ops per second": 6561168.75, "ns per ops": 152.41, "Ops per threads": 6572355.0, "Ops per procs": 32861776.0, "Ops/sec/procs": 6561168.75, "ns per ops/procs": 152.41}],["rdq-cycle-go", "./rdq-cycle-go -t 1 -p 1 -d 5 -r 5", {"Duration (ms)": 5000.0, "Number of processors": 1.0, "Number of threads": 5.0, "Cycle size (# thrds)": 5.0, "Total Operations(ops)": 28097680.0, "Ops per second": 5619274.9, "ns per ops": 177.96, "Ops per threads": 5619536.0, "Ops per procs": 28097680.0, "Ops/sec/procs": 5619274.9, "ns per ops/procs": 177.96}]]
  • doc/theses/thierry_delisle_PhD/thesis/local.bib

    r74ec742 r29d8c02  
    701701  note = "[Online; accessed 12-April-2022]"
    702702}
    703 
    704 % RMR notes :
    705 % [05/04, 12:36] Trevor Brown
    706 %     i don't know where rmr complexity was first introduced, but there are many many many papers that use the term and define it
    707 % ​[05/04, 12:37] Trevor Brown
    708 %     here's one paper that uses the term a lot and links to many others that use it... might trace it to something useful there https://drops.dagstuhl.de/opus/volltexte/2021/14832/pdf/LIPIcs-DISC-2021-30.pdf
    709 % ​[05/04, 12:37] Trevor Brown
    710 %     another option might be to cite a textbook
    711 % ​[05/04, 12:42] Trevor Brown
    712 %     but i checked two textbooks in the area i'm aware of and i don't see a definition of rmr complexity in either
    713 % ​[05/04, 12:42] Trevor Brown
    714 %     this one has a nice statement about the prevelance of rmr complexity, as well as some rough definition
    715 % ​[05/04, 12:42] Trevor Brown
    716 %     https://dl.acm.org/doi/pdf/10.1145/3465084.3467938
    717 
    718 % Race to idle notes :
    719 % [13/04, 16:56] Martin Karsten
    720 %       I don't have a citation. Google brings up this one, which might be good:
    721 %
    722 % https://doi.org/10.1137/1.9781611973099.100
  • doc/theses/thierry_delisle_PhD/thesis/text/eval_macro.tex

    r74ec742 r29d8c02  
    77Networked ZIPF
    88
    9 Nginx : 5Gb still good, 4Gb starts to suffer
    10 
    11 Cforall : 10Gb too high, 4 Gb too low
    12 
    139\section{Memcached}
    1410
    15 \subsection{Benchmark Environment}
    16 These experiments are run on a cluster of homogenous Supermicro SYS-6017R-TDF compute nodes with the following characteristics:
    17 The server runs Ubuntu 20.04.3 LTS on top of Linux Kernel 5.11.0-34.
    18 Each node has 2 Intel(R) Xeon(R) CPU E5-2620 v2 running at 2.10GHz.
    19 These CPUs have 6 cores per CPUs and 2 \glspl{hthrd} per core, for a total of 24 \glspl{hthrd}.
    20 The cpus each have 384 KB, 3 MB and 30 MB of L1, L2 and L3 caches respectively.
    21 Each node is connected to the network through a Mellanox 10 Gigabit Ethernet port.
    22 The network route uses 1 Mellanox SX1012 10/40 Gigabit Ethernet cluster switch.
     11In Memory
    2312
    24 
    25 
    26 \begin{figure}
    27         \centering
    28         \input{result.memcd.updt.qps.pstex_t}
    29         \caption[Churn Benchmark : Throughput on Intel]{Churn Benchmark : Throughput on Intel\smallskip\newline Description}
    30         \label{fig:memcd:updt:qps}
    31 \end{figure}
    32 
    33 \begin{figure}
    34         \centering
    35         \input{result.memcd.updt.lat.pstex_t}
    36         \caption[Churn Benchmark : Throughput on Intel]{Churn Benchmark : Throughput on Intel\smallskip\newline Description}
    37         \label{fig:memcd:updt:lat}
    38 \end{figure}
    39 
    40 \begin{figure}
    41         \centering
    42         \input{result.memcd.rate.qps.pstex_t}
    43         \caption[Churn Benchmark : Throughput on Intel]{Churn Benchmark : Throughput on Intel\smallskip\newline Description}
    44         \label{fig:memcd:rate:qps}
    45 \end{figure}
    46 
    47 \begin{figure}
    48         \centering
    49         \input{result.memcd.rate.99th.pstex_t}
    50         \caption[Churn Benchmark : Throughput on Intel]{Churn Benchmark : Throughput on Intel\smallskip\newline Description}
    51         \label{fig:memcd:rate:tail}
    52 \end{figure}
     13Networked
  • doc/theses/thierry_delisle_PhD/thesis/text/eval_micro.tex

    r74ec742 r29d8c02  
    66\section{Benchmark Environment}
    77All of these benchmarks are run on two distinct hardware environment, an AMD and an INTEL machine.
    8 
    9 For all benchmarks, \texttt{taskset} is used to limit the experiment to 1 NUMA Node with no hyper threading.
    10 If more \glspl{hthrd} are needed, then 1 NUMA Node with hyperthreading is used.
    11 If still more \glspl{hthrd} are needed then the experiment is limited to as few NUMA Nodes as needed.
    12 
    138
    149\paragraph{AMD} The AMD machine is a server with two AMD EPYC 7662 CPUs and 256GB of DDR4 RAM.
     
    2823
    2924\section{Cycling latency}
    30 \begin{figure}
    31         \centering
    32         \input{cycle.pstex_t}
    33         \caption[Cycle benchmark]{Cycle benchmark\smallskip\newline Each \gls{at} unparks the next \gls{at} in the cycle before parking itself.}
    34         \label{fig:cycle}
    35 \end{figure}
    3625The most basic evaluation of any ready queue is to evaluate the latency needed to push and pop one element from the ready-queue.
    3726Since these two operation also describe a \texttt{yield} operation, many systems use this as the most basic benchmark.
     
    5342Note that this problem is only present on SMP machines and is significantly mitigated by the fact that there are multiple rings in the system.
    5443
     44\begin{figure}
     45        \centering
     46        \input{cycle.pstex_t}
     47        \caption[Cycle benchmark]{Cycle benchmark\smallskip\newline Each \gls{at} unparks the next \gls{at} in the cycle before parking itself.}
     48        \label{fig:cycle}
     49\end{figure}
     50
    5551To avoid this benchmark from being dominated by the idle sleep handling, the number of rings is kept at least as high as the number of \glspl{proc} available.
    5652Beyond this point, adding more rings serves to mitigate even more the idle sleep handling.
     
    5854
    5955The actual benchmark is more complicated to handle termination, but that simply requires using a binary semphore or a channel instead of raw \texttt{park}/\texttt{unpark} and carefully picking the order of the \texttt{P} and \texttt{V} with respect to the loop condition.
    60 Figure~\ref{fig:cycle:code} shows pseudo code for this benchmark.
     56
     57\begin{lstlisting}
     58        Thread.main() {
     59                count := 0
     60                for {
     61                        wait()
     62                        this.next.wake()
     63                        count ++
     64                        if must_stop() { break }
     65                }
     66                global.count += count
     67        }
     68\end{lstlisting}
    6169
    6270\begin{figure}
    63         \begin{lstlisting}
    64                 Thread.main() {
    65                         count := 0
    66                         for {
    67                                 wait()
    68                                 this.next.wake()
    69                                 count ++
    70                                 if must_stop() { break }
    71                         }
    72                         global.count += count
    73                 }
    74         \end{lstlisting}
    75         \caption[Cycle Benchmark : Pseudo Code]{Cycle Benchmark : Pseudo Code}
    76         \label{fig:cycle:code}
     71        \centering
     72        \input{result.cycle.jax.ops.pstex_t}
     73        \vspace*{-10pt}
     74        \label{fig:cycle:ns:jax}
    7775\end{figure}
    78 
    79 
    80 
    81 \subsection{Results}
    82 \begin{figure}
    83         \subfloat[][Throughput, 100 \ats per \proc]{
    84                 \resizebox{0.5\linewidth}{!}{
    85                         \input{result.cycle.jax.ops.pstex_t}
    86                 }
    87                 \label{fig:cycle:jax:ops}
    88         }
    89         \subfloat[][Throughput, 1 \ats per \proc]{
    90                 \resizebox{0.5\linewidth}{!}{
    91                         \input{result.cycle.low.jax.ops.pstex_t}
    92                 }
    93                 \label{fig:cycle:jax:low:ops}
    94         }
    95 
    96         \subfloat[][Latency, 100 \ats per \proc]{
    97                 \resizebox{0.5\linewidth}{!}{
    98                         \input{result.cycle.jax.ns.pstex_t}
    99                 }
    100 
    101         }
    102         \subfloat[][Latency, 1 \ats per \proc]{
    103                 \resizebox{0.5\linewidth}{!}{
    104                         \input{result.cycle.low.jax.ns.pstex_t}
    105                 }
    106                 \label{fig:cycle:jax:low:ns}
    107         }
    108         \caption[Cycle Benchmark on Intel]{Cycle Benchmark on Intel\smallskip\newline Throughput as a function of \proc count, using 100 cycles per \proc, 5 \ats per cycle.}
    109         \label{fig:cycle:jax}
    110 \end{figure}
    111 Figure~\ref{fig:cycle:jax} shows the throughput as a function of \proc count, with the following constants:
    112 Each run uses 100 cycles per \proc, 5 \ats per cycle.
    113 
    114 \todo{results discussion}
    11576
    11677\section{Yield}
     
    12081Its only interesting variable is the number of \glspl{at} per \glspl{proc}, where ratios close to 1 means the ready queue(s) could be empty.
    12182This sometimes puts more strain on the idle sleep handling, compared to scenarios where there is clearly plenty of work to be done.
    122 Figure~\ref{fig:yield:code} shows pseudo code for this benchmark, the ``wait/wake-next'' is simply replaced by a yield.
    12383
    124 \begin{figure}
    125         \begin{lstlisting}
    126                 Thread.main() {
    127                         count := 0
    128                         for {
    129                                 yield()
    130                                 count ++
    131                                 if must_stop() { break }
    132                         }
    133                         global.count += count
     84\todo{code, setup, results}
     85
     86\begin{lstlisting}
     87        Thread.main() {
     88                count := 0
     89                while !stop {
     90                        yield()
     91                        count ++
    13492                }
    135         \end{lstlisting}
    136         \caption[Yield Benchmark : Pseudo Code]{Yield Benchmark : Pseudo Code}
    137         \label{fig:yield:code}
    138 \end{figure}
    139 
    140 \subsection{Results}
    141 \begin{figure}
    142         \subfloat[][Throughput, 100 \ats per \proc]{
    143                 \resizebox{0.5\linewidth}{!}{
    144                         \input{result.yield.jax.ops.pstex_t}
    145                 }
    146                 \label{fig:yield:jax:ops}
     93                global.count += count
    14794        }
    148         \subfloat[][Throughput, 1 \ats per \proc]{
    149                 \resizebox{0.5\linewidth}{!}{
    150                 \input{result.yield.low.jax.ops.pstex_t}
    151                 }
    152                 \label{fig:yield:jax:low:ops}
    153         }
    154 
    155         \subfloat[][Latency, 100 \ats per \proc]{
    156                 \resizebox{0.5\linewidth}{!}{
    157                 \input{result.yield.jax.ns.pstex_t}
    158                 }
    159                 \label{fig:yield:jax:ns}
    160         }
    161         \subfloat[][Latency, 1 \ats per \proc]{
    162                 \resizebox{0.5\linewidth}{!}{
    163                 \input{result.yield.low.jax.ns.pstex_t}
    164                 }
    165                 \label{fig:yield:jax:low:ns}
    166         }
    167         \caption[Yield Benchmark on Intel]{Yield Benchmark on Intel\smallskip\newline Throughput as a function of \proc count, using 1 \ats per \proc.}
    168         \label{fig:yield:jax}
    169 \end{figure}
    170 Figure~\ref{fig:yield:ops:jax} shows the throughput as a function of \proc count, with the following constants:
    171 Each run uses 100 \ats per \proc.
    172 
    173 \todo{results discussion}
     95\end{lstlisting}
    17496
    17597
     
    183105In either case, this benchmark aims to highlight how each scheduler handles these cases, since both cases can lead to performance degradation if they are not handled correctly.
    184106
    185 To achieve this the benchmark uses a fixed size array of semaphores.
    186 Each \gls{at} picks a random semaphore, \texttt{V}s it to unblock a \at waiting and then \texttt{P}s on the semaphore.
    187 This creates a flow where \glspl{at} push each other out of the semaphores before being pushed out themselves.
    188 For this benchmark to work however, the number of \glspl{at} must be equal or greater to the number of semaphores plus the number of \glspl{proc}.
    189 Note that the nature of these semaphores mean the counter can go beyond 1, which could lead to calls to \texttt{P} not blocking.
     107To achieve this the benchmark uses a fixed size array of \newterm{chair}s, where a chair is a data structure that holds a single blocked \gls{at}.
     108When a \gls{at} attempts to block on the chair, it must first unblocked the \gls{at} currently blocked on said chair, if any.
     109This creates a flow where \glspl{at} push each other out of the chairs before being pushed out themselves.
     110For this benchmark to work however, the number of \glspl{at} must be equal or greater to the number of chairs plus the number of \glspl{proc}.
    190111
    191112\todo{code, setup, results}
     
    195116                for {
    196117                        r := random() % len(spots)
    197                         spots[r].V()
    198                         spots[r].P()
     118                        next := xchg(spots[r], this)
     119                        if next { next.wake() }
     120                        wait()
    199121                        count ++
    200122                        if must_stop() { break }
     
    203125        }
    204126\end{lstlisting}
    205 
    206 \begin{figure}
    207         \subfloat[][Throughput, 100 \ats per \proc]{
    208                 \resizebox{0.5\linewidth}{!}{
    209                         \input{result.churn.jax.ops.pstex_t}
    210                 }
    211                 \label{fig:churn:jax:ops}
    212         }
    213         \subfloat[][Throughput, 1 \ats per \proc]{
    214                 \resizebox{0.5\linewidth}{!}{
    215                         \input{result.churn.low.jax.ops.pstex_t}
    216                 }
    217                 \label{fig:churn:jax:low:ops}
    218         }
    219 
    220         \subfloat[][Latency, 100 \ats per \proc]{
    221                 \resizebox{0.5\linewidth}{!}{
    222                         \input{result.churn.jax.ns.pstex_t}
    223                 }
    224 
    225         }
    226         \subfloat[][Latency, 1 \ats per \proc]{
    227                 \resizebox{0.5\linewidth}{!}{
    228                         \input{result.churn.low.jax.ns.pstex_t}
    229                 }
    230                 \label{fig:churn:jax:low:ns}
    231         }
    232         \caption[Churn Benchmark on Intel]{\centering Churn Benchmark on Intel\smallskip\newline Throughput and latency of the Churn on the benchmark on the Intel machine. Throughput is the total operation per second across all cores. Latency is the duration of each opeartion.}
    233         \label{fig:churn:jax}
    234 \end{figure}
    235127
    236128\section{Locality}
  • doc/theses/thierry_delisle_PhD/thesis/text/practice.tex

    r74ec742 r29d8c02  
    77More precise \CFA supports adding \procs using the RAII object @processor@.
    88These objects can be created at any time and can be destroyed at any time.
    9 They are normally created as automatic stack variables, but this is not a requirement.
     9They are normally create as automatic stack variables, but this is not a requirement.
    1010
    1111The consequence is that the scheduler and \io subsystems must support \procs comming in and out of existence.
    1212
    1313\section{Manual Resizing}
    14 Manual resizing is expected to be a rare operation.
    15 Programmers are mostly expected to resize clusters on startup or teardown.
    16 Therefore dynamically changing the number of \procs is an appropriate moment to allocate or free resources to match the new state.
    17 As such all internal arrays that are sized based on the number of \procs need to be \texttt{realloc}ed.
    18 This also means that any references into these arrays, pointers or indexes, may need to be fixed when shrinking\footnote{Indexes may still need fixing when shrinkingbecause some indexes are expected to refer to dense contiguous resources and there is no guarantee the resource being removed has the highest index.}.
     14The consequence of dynamically changing the number of \procs is that all internal arrays that are sized based on the number of \procs neede to be \texttt{realloc}ed.
     15This also means that any references into these arrays, pointers or indexes, may need to be fixed when shrinking\footnote{Indexes may still need fixing because there is no guarantee the \proc causing the shrink had the highest index. Therefore indexes need to be reassigned to preserve contiguous indexes.}.
    1916
    20 There are no performance requirements, within reason, for resizing since it is expected to be rare.
     17There are no performance requirements, within reason, for resizing since this is usually considered as part of setup and teardown.
    2118However, this operation has strict correctness requirements since shrinking and idle sleep can easily lead to deadlocks.
    2219It should also avoid as much as possible any effect on performance when the number of \procs remain constant.
    23 This later requirement prohibits naive solutions, like simply adding a global lock to the ready-queue arrays.
     20This later requirement prehibits simple solutions, like simply adding a global lock to these arrays.
    2421
    2522\subsection{Read-Copy-Update}
     
    2724In this pattern, resizing is done by creating a copy of the internal data strucures, updating the copy with the desired changes, and then attempt an Idiana Jones Switch to replace the original witht the copy.
    2825This approach potentially has the advantage that it may not need any synchronization to do the switch.
    29 However, there is a race where \procs could still use the previous, original, data structure after the copy was switched in.
    30 This race not only requires some added memory reclamation scheme, it also requires that operations made on the stale original version be eventually moved to the copy.
     26The switch definitely implies a race where \procs could still use the previous, original, data structure after the copy was switched in.
     27The important question then becomes whether or not this race can be recovered from.
     28If the changes that arrived late can be transferred from the original to the copy then this solution works.
    3129
    32 For linked-lists, enqueing is only somewhat problematic, \ats enqueued to the original queues need to be transferred to the new, which might not preserve ordering.
    33 Dequeing is more challenging.
     30For linked-lists, dequeing is somewhat of a problem.
    3431Dequeing from the original will not necessarily update the copy which could lead to multiple \procs dequeing the same \at.
    35 Fixing this requires more synchronization or more indirection on the queues.
     32Fixing this requires making the array contain pointers to subqueues rather than the subqueues themselves.
    3633
    3734Another challenge is that the original must be kept until all \procs have witnessed the change.
     
    10097In addition to users manually changing the number of \procs, it is desireable to support ``removing'' \procs when there is not enough \ats for all the \procs to be useful.
    10198While manual resizing is expected to be rare, the number of \ats is expected to vary much more which means \procs may need to be ``removed'' for only short periods of time.
    102 Furthermore, race conditions that spuriously lead to the impression that no \ats are ready are actually common in practice.
    103 Therefore resources associated with \procs should not be freed but \procs simply put into an idle state where the \gls{kthrd} is blocked until more \ats become ready.
     99Furthermore, race conditions that spuriously lead to the impression no \ats are ready are actually common in practice.
     100Therefore \procs should not be actually \emph{removed} but simply put into an idle state where the \gls{kthrd} is blocked until more \ats become ready.
    104101This state is referred to as \newterm{Idle-Sleep}.
    105102
     
    113110The \CFA scheduler simply follows the ``Race-to-Idle'\cit{https://doi.org/10.1137/1.9781611973099.100}' approach where a sleeping \proc is woken any time an \at becomes ready and \procs go to idle sleep anytime they run out of work.
    114111
    115 \section{Sleeping}
    116 As usual, the corner-stone of any feature related to the kernel is the choice of system call.
    117 In terms of blocking a \gls{kthrd} until some event occurs the linux kernel has many available options:
    118 
    119 \paragraph{\texttt{pthread\_mutex}/\texttt{pthread\_cond}}
    120 The most classic option is to use some combination of \texttt{pthread\_mutex} and \texttt{pthread\_cond}.
    121 These serve as straight forward mutual exclusion and synchronization tools and allow a \gls{kthrd} to wait on a \texttt{pthread\_cond} until signalled.
    122 While this approach is generally perfectly appropriate for \glspl{kthrd} waiting after eachother, \io operations do not signal \texttt{pthread\_cond}s.
    123 For \io results to wake a \proc waiting on a \texttt{pthread\_cond} means that a different \glspl{kthrd} must be woken up first, and then the \proc can be signalled.
    124 
    125 \subsection{\texttt{io\_uring} and Epoll}
    126 An alternative is to flip the problem on its head and block waiting for \io, using \texttt{io\_uring} or even \texttt{epoll}.
    127 This creates the inverse situation, where \io operations directly wake sleeping \procs but waking \proc from a running \gls{kthrd} must use an indirect scheme.
    128 This generally takes the form of creating a file descriptor, \eg, a dummy file, a pipe or an event fd, and using that file descriptor when \procs need to wake eachother.
    129 This leads to additional complexity because there can be a race between these artificial \io operations and genuine \io operations.
    130 If not handled correctly, this can lead to the artificial files going out of sync.
    131 
    132 \subsection{Event FDs}
    133 Another interesting approach is to use an event file descriptor\cit{eventfd}.
    134 This is a Linux feature that is a file descriptor that behaves like \io, \ie, uses \texttt{read} and \texttt{write}, but also behaves like a semaphore.
    135 Indeed, all read and writes must use 64bits large values\footnote{On 64-bit Linux, a 32-bit Linux would use 32 bits values.}.
    136 Writes add their values to the buffer, that is arithmetic addition and not buffer append, and reads zero out the buffer and return the buffer values so far\footnote{This is without the \texttt{EFD\_SEMAPHORE} flag. This flags changes the behavior of \texttt{read} but is not needed for this work.}.
    137 If a read is made while the buffer is already 0, the read blocks until a non-0 value is added.
    138 What makes this feature particularly interesting is that \texttt{io\_uring} supports the \texttt{IORING\_REGISTER\_EVENTFD} command, to register an event fd to a particular instance.
    139 Once that instance is registered, any \io completion will result in \texttt{io\_uring} writing to the event FD.
    140 This means that a \proc waiting on the event FD can be \emph{directly} woken up by either other \procs or incomming \io.
    141 
    142 \begin{figure}
    143         \centering
    144         \input{idle1.pstex_t}
    145         \caption[Basic Idle Sleep Data Structure]{Basic Idle Sleep Data Structure \smallskip\newline Each idle \proc is put unto a doubly-linked stack protected by a lock.
    146         Each \proc has a private event FD.}
    147         \label{fig:idle1}
    148 \end{figure}
    149 
    150112
    151113\section{Tracking Sleepers}
    152114Tracking which \procs are in idle sleep requires a data structure holding all the sleeping \procs, but more importantly it requires a concurrent \emph{handshake} so that no \at is stranded on a ready-queue with no active \proc.
    153115The classic challenge is when a \at is made ready while a \proc is going to sleep, there is a race where the new \at may not see the sleeping \proc and the sleeping \proc may not see the ready \at.
    154 Since \ats can be made ready by timers, \io operations or other events outside a clusre, this race can occur even if the \proc going to sleep is the only \proc awake.
    155 As a result, improper handling of this race can lead to all \procs going to sleep and the system deadlocking.
    156116
    157 Furthermore, the ``Race-to-Idle'' approach means that there may be contention on the data structure tracking sleepers.
    158 Contention slowing down \procs attempting to sleep or wake-up can be tolerated.
    159 These \procs are not doing useful work and therefore not contributing to overall performance.
    160 However, notifying, checking if a \proc must be woken-up and doing so if needed, can significantly affect overall performance and must be low cost.
     117Furthermore, the ``Race-to-Idle'' approach means that there is some
    161118
    162 \subsection{Sleepers List}
    163 Each cluster maintains a list of idle \procs, organized as a stack.
    164 This ordering hopefully allows \proc at the tail to stay in idle sleep for extended period of times.
    165 Because of these unbalanced performance requirements, the algorithm tracking sleepers is designed to have idle \proc handle as much of the work as possible.
    166 The idle \procs maintain the of sleepers among themselves and notifying a sleeping \proc takes as little work as possible.
    167 This approach means that maintaining the list is fairly straightforward.
    168 The list can simply use a single lock per cluster and only \procs that are getting in and out of idle state will contend for that lock.
     119\section{Sleeping}
    169120
    170 This approach also simplifies notification.
    171 Indeed, \procs need to be notify when a new \at is readied, but they also must be notified during resizing, so the \gls{kthrd} can be joined.
    172 This means that whichever entity removes idle \procs from the sleeper list must be able to do so in any order.
    173 Using a simple lock over this data structure makes the removal much simpler than using a lock-free data structure.
    174 The notification process then simply needs to wake-up the desired idle \proc, using \texttt{pthread\_cond\_signal}, \texttt{write} on an fd, etc., and the \proc will handle the rest.
     121\subsection{Event FDs}
    175122
    176 \subsection{Reducing Latency}
    177 As mentioned in this section, \procs going idle for extremely short periods of time is likely in certain common scenarios.
    178 Therefore, the latency of doing a system call to read from and writing to the event fd can actually negatively affect overall performance in a notable way.
    179 Is it important to reduce latency and contention of the notification as much as possible.
    180 Figure~\ref{fig:idle1} shoes the basic idle sleep data structure.
    181 For the notifiers, this data structure can cause contention on the lock and the event fd syscall can cause notable latency.
     123\subsection{Epoll}
    182124
    183 \begin{figure}
    184         \centering
    185         \input{idle2.pstex_t}
    186         \caption[Improved Idle Sleep Data Structure]{Improved Idle Sleep Data Structure \smallskip\newline An atomic pointer is added to the list, pointing to the Event FD of the first \proc on the list.}
    187         \label{fig:idle2}
    188 \end{figure}
     125\subsection{\texttt{io\_uring}}
    189126
    190 The contention is mostly due to the lock on the list needing to be held to get to the head \proc.
    191 That lock can be contended by \procs attempting to go to sleep, \procs waking or notification attempts.
    192 The contentention from the \procs attempting to go to sleep can be mitigated slightly by using \texttt{try\_acquire} instead, so the \procs simply continue searching for \ats if the lock is held.
    193 This trick cannot be used for waking \procs since they are not in a state where they can run \ats.
    194 However, it is worth nothing that notification does not strictly require accessing the list or the head \proc.
    195 Therefore, contention can be reduced notably by having notifiers avoid the lock entirely and adding a pointer to the event fd of the first idle \proc, as in Figure~\ref{fig:idle2}.
    196 To avoid contention between the notifiers, instead of simply reading the atomic pointer, notifiers atomically exchange it to \texttt{null} so only only notifier will contend on the system call.
    197 
    198 \begin{figure}
    199         \centering
    200         \input{idle_state.pstex_t}
    201         \caption[Improved Idle Sleep Data Structure]{Improved Idle Sleep Data Structure \smallskip\newline An atomic pointer is added to the list, pointing to the Event FD of the first \proc on the list.}
    202         \label{fig:idle:state}
    203 \end{figure}
    204 
    205 The next optimization that can be done is to avoid the latency of the event fd when possible.
    206 This can be done by adding what is effectively a benaphore\cit{benaphore} in front of the event fd.
    207 A simple three state flag is added beside the event fd to avoid unnecessary system calls, as shown in Figure~\ref{fig:idle:state}.
    208 The flag starts in state \texttt{SEARCH}, while the \proc is searching for \ats to run.
    209 The \proc then confirms the sleep by atomically swaping the state to \texttt{SLEEP}.
    210 If the previous state was still \texttt{SEARCH}, then the \proc does read the event fd.
    211 Meanwhile, notifiers atomically exchange the state to \texttt{AWAKE} state.
    212 if the previous state was \texttt{SLEEP}, then the notifier must write to the event fd.
    213 However, if the notify arrives almost immediately after the \proc marks itself idle, then both reads and writes on the event fd can be omitted, which reduces latency notably.
    214 This leads to the final data structure shown in Figure~\ref{fig:idle}.
    215 
    216 \begin{figure}
    217         \centering
    218         \input{idle.pstex_t}
    219         \caption[Low-latency Idle Sleep Data Structure]{Low-latency Idle Sleep Data Structure \smallskip\newline Each idle \proc is put unto a doubly-linked stack protected by a lock.
    220         Each \proc has a private event FD with a benaphore in front of it.
    221         The list also has an atomic pointer to the event fd and benaphore of the first \proc on the list.}
    222         \label{fig:idle}
    223 \end{figure}
     127\section{Reducing Latency}
  • doc/theses/thierry_delisle_PhD/thesis/thesis.tex

    r74ec742 r29d8c02  
    8282\usepackage{xcolor}
    8383\usepackage{graphicx} % For including graphics
    84 \usepackage{subcaption}
    8584
    8685% Hyperlinks make it very easy to navigate an electronic document.
     
    205204\newcommand\at{\gls{at}\xspace}%
    206205\newcommand\ats{\glspl{at}\xspace}%
    207 \newcommand\Proc{\Pls{proc}\xspace}%
    208206\newcommand\proc{\gls{proc}\xspace}%
    209207\newcommand\procs{\glspl{proc}\xspace}%
  • libcfa/src/Makefile.am

    r74ec742 r29d8c02  
    3333# The built sources must not depend on the installed inst_headers_src
    3434AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr -I$(srcdir)/concurrency $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    35 AM_CFLAGS = -g -Wall -Werror=return-type -Wno-unused-function -fPIC -fexceptions -fvisibility=hidden -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
     35AM_CFLAGS = -g -Wall -Werror=return-type -Wno-unused-function -fPIC -fexceptions -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3636AM_CCASFLAGS = -g -Wall -Werror=return-type -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3737CFACC = @CFACC@
     
    194194
    195195prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
    196         ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA,-l ${<} -c -fvisibility=default -o ${@}
     196        ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA,-l ${<} -c -o ${@}
    197197
    198198prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
    199199        ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
    200         $(CFACOMPILE) -quiet -XCFA,-l ${<} -c -fvisibility=default -o ${@}
     200        $(CFACOMPILE) -quiet -XCFA,-l ${<} -c -o ${@}
    201201
    202202concurrency/io/call.cfa: $(srcdir)/concurrency/io/call.cfa.in
  • libcfa/src/algorithms/range_iterator.cfa

    r74ec742 r29d8c02  
    2020#include <fstream.hfa>
    2121
    22 #include "bits/defs.hfa"
    23 
    24 void main(RangeIter & this) libcfa_public {
     22void main(RangeIter & this) {
    2523        for() {
    2624                this._start = -1;
  • libcfa/src/assert.cfa

    r74ec742 r29d8c02  
    1919#include <unistd.h>                                                             // STDERR_FILENO
    2020#include "bits/debug.hfa"
    21 #include "bits/defs.hfa"
    2221
    2322extern "C" {
     
    2726
    2827        // called by macro assert in assert.h
    29         // would be cool to remove libcfa_public but it's needed for libcfathread
    30         void __assert_fail( const char assertion[], const char file[], unsigned int line, const char function[] ) libcfa_public {
     28        void __assert_fail( const char assertion[], const char file[], unsigned int line, const char function[] ) {
    3129                __cfaabi_bits_print_safe( STDERR_FILENO, CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
    3230                abort();
     
    3432
    3533        // called by macro assertf
    36         // would be cool to remove libcfa_public but it's needed for libcfathread
    37         void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) libcfa_public {
     34        void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) {
    3835                __cfaabi_bits_acquire();
    3936                __cfaabi_bits_print_nolock( STDERR_FILENO, CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
  • libcfa/src/bits/align.hfa

    r74ec742 r29d8c02  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 29 19:14:43 2022
    13 // Update Count     : 4
     12// Last Modified On : Sat Nov 16 18:58:22 2019
     13// Update Count     : 3
    1414//
    1515// This  library is free  software; you  can redistribute  it and/or  modify it
     
    3535//#define libAlign() (sizeof(double))
    3636// gcc-7 uses xmms instructions, which require 16 byte alignment.
    37 #define libAlign() (__BIGGEST_ALIGNMENT__)
     37#define libAlign() (16)
    3838
    3939// Check for power of 2
  • libcfa/src/bits/debug.cfa

    r74ec742 r29d8c02  
    2121#include <unistd.h>
    2222
    23 #include "bits/defs.hfa"
    24 
    2523enum { buffer_size = 4096 };
    2624static char buffer[ buffer_size ];
    2725
    2826extern "C" {
    29         // would be cool to remove libcfa_public but it's needed for libcfathread
    30         void __cfaabi_bits_write( int fd, const char in_buffer[], int len ) libcfa_public {
     27        void __cfaabi_bits_write( int fd, const char in_buffer[], int len ) {
    3128                // ensure all data is written
    3229                for ( int count = 0, retcode; count < len; count += retcode ) {
     
    4744        void __cfaabi_bits_release() __attribute__((__weak__)) {}
    4845
    49         // would be cool to remove libcfa_public but it's needed for libcfathread
    50         int __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) libcfa_public {
     46        int __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
    5147                va_list args;
    5248
  • libcfa/src/bits/defs.hfa

    r74ec742 r29d8c02  
    3636#define __cfa_dlink(x) struct { struct x * next; struct x * back; } __dlink_substitute
    3737#endif
    38 
    39 #define libcfa_public __attribute__((visibility("default")))
    4038
    4139#ifdef __cforall
  • libcfa/src/bits/weakso_locks.cfa

    r74ec742 r29d8c02  
    1818#include "bits/weakso_locks.hfa"
    1919
    20 #pragma GCC visibility push(default)
    21 
    2220void  ?{}( blocking_lock &, bool, bool ) {}
    2321void ^?{}( blocking_lock & ) {}
  • libcfa/src/common.cfa

    r74ec742 r29d8c02  
    1818#include <stdlib.h>                                     // div_t, *div
    1919
    20 #pragma GCC visibility push(default)
    21 
    2220//---------------------------------------
    2321
  • libcfa/src/concurrency/alarm.cfa

    r74ec742 r29d8c02  
    141141//=============================================================================================
    142142
    143 void sleep( Duration duration ) libcfa_public {
     143void sleep( Duration duration ) {
    144144        alarm_node_t node = { active_thread(), duration, 0`s };
    145145
  • libcfa/src/concurrency/clib/cfathread.cfa

    r74ec742 r29d8c02  
    326326}
    327327
    328 #pragma GCC visibility push(default)
    329 
    330328//================================================================================
    331329// Main Api
    332330extern "C" {
    333         int cfathread_cluster_create(cfathread_cluster_t * cl) __attribute__((nonnull(1))) libcfa_public {
     331        int cfathread_cluster_create(cfathread_cluster_t * cl) __attribute__((nonnull(1))) {
    334332                *cl = new();
    335333                return 0;
    336334        }
    337335
    338         cfathread_cluster_t cfathread_cluster_self(void) libcfa_public {
     336        cfathread_cluster_t cfathread_cluster_self(void) {
    339337                return active_cluster();
    340338        }
    341339
    342         int cfathread_cluster_print_stats( cfathread_cluster_t cl ) libcfa_public {
     340        int cfathread_cluster_print_stats( cfathread_cluster_t cl ) {
    343341                #if !defined(__CFA_NO_STATISTICS__)
    344342                        print_stats_at_exit( *cl, CFA_STATS_READY_Q | CFA_STATS_IO );
  • libcfa/src/concurrency/coroutine.cfa

    r74ec742 r29d8c02  
    4848//-----------------------------------------------------------------------------
    4949forall(T &)
    50 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) libcfa_public {
     50void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    5151        dst->virtual_table = src->virtual_table;
    5252        dst->the_coroutine = src->the_coroutine;
     
    5555
    5656forall(T &)
    57 const char * msg(CoroutineCancelled(T) *) libcfa_public {
     57const char * msg(CoroutineCancelled(T) *) {
    5858        return "CoroutineCancelled(...)";
    5959}
     
    6262forall(T & | is_coroutine(T))
    6363void __cfaehm_cancelled_coroutine(
    64                 T & cor, coroutine$ * desc, EHM_DEFAULT_VTABLE(CoroutineCancelled, (T)) ) libcfa_public {
     64                T & cor, coroutine$ * desc, EHM_DEFAULT_VTABLE(CoroutineCancelled, (T)) ) {
    6565        verify( desc->cancellation );
    6666        desc->state = Cancelled;
     
    8989
    9090void __stack_prepare( __stack_info_t * this, size_t create_size );
    91 static void __stack_clean  ( __stack_info_t * this );
     91void __stack_clean  ( __stack_info_t * this );
    9292
    9393//-----------------------------------------------------------------------------
     
    114114}
    115115
    116 void ?{}( coroutine$ & this, const char name[], void * storage, size_t storageSize ) libcfa_public with( this ) {
     116void ?{}( coroutine$ & this, const char name[], void * storage, size_t storageSize ) with( this ) {
    117117        (this.context){0p, 0p};
    118118        (this.stack){storage, storageSize};
     
    124124}
    125125
    126 void ^?{}(coroutine$& this) libcfa_public {
     126void ^?{}(coroutine$& this) {
    127127        if(this.state != Halted && this.state != Start && this.state != Primed) {
    128128                coroutine$ * src = active_coroutine();
     
    147147// Not inline since only ever called once per coroutine
    148148forall(T & | is_coroutine(T) | { EHM_DEFAULT_VTABLE(CoroutineCancelled, (T)); })
    149 void prime(T& cor) libcfa_public {
     149void prime(T& cor) {
    150150        coroutine$* this = get_coroutine(cor);
    151151        assert(this->state == Start);
     
    155155}
    156156
    157 static [void *, size_t] __stack_alloc( size_t storageSize ) {
     157[void *, size_t] __stack_alloc( size_t storageSize ) {
    158158        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    159159        assert(__page_size != 0l);
     
    193193}
    194194
    195 static void __stack_clean  ( __stack_info_t * this ) {
     195void __stack_clean  ( __stack_info_t * this ) {
    196196        void * storage = this->storage->limit;
    197197
     
    215215}
    216216
    217 void __stack_prepare( __stack_info_t * this, size_t create_size ) libcfa_public {
     217void __stack_prepare( __stack_info_t * this, size_t create_size ) {
    218218        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    219219        bool userStack;
  • libcfa/src/concurrency/coroutine.hfa

    r74ec742 r29d8c02  
    113113
    114114extern void __stack_prepare( __stack_info_t * this, size_t size /* ignored if storage already allocated */);
     115extern void __stack_clean  ( __stack_info_t * this );
     116
    115117
    116118// Suspend implementation inlined for performance
  • libcfa/src/concurrency/exception.cfa

    r74ec742 r29d8c02  
    6464extern "C" {
    6565
    66 struct exception_context_t * this_exception_context(void) libcfa_public {
     66struct exception_context_t * this_exception_context(void) {
    6767        return &__get_stack( active_coroutine() )->exception_context;
    6868}
    6969
    70 _Unwind_Reason_Code __cfaehm_cancellation_unwind( struct _Unwind_Exception * unwind_exception ) libcfa_public {
     70_Unwind_Reason_Code __cfaehm_cancellation_unwind( struct _Unwind_Exception * unwind_exception ) {
    7171        _Unwind_Stop_Fn stop_func;
    7272        void * stop_param;
  • libcfa/src/concurrency/invoke.c

    r74ec742 r29d8c02  
    3636extern void enable_interrupts( _Bool poll );
    3737
    38 libcfa_public void __cfactx_invoke_coroutine(
     38void __cfactx_invoke_coroutine(
    3939        void (*main)(void *),
    4040        void *this
     
    7070}
    7171
    72 libcfa_public void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct coroutine$ * cor) __attribute__ ((__noreturn__));
     72void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct coroutine$ * cor) __attribute__ ((__noreturn__));
    7373void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct coroutine$ * cor) {
    7474        _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, __cfactx_coroutine_unwindstop, cor );
     
    7777}
    7878
    79 libcfa_public void __cfactx_invoke_thread(
     79void __cfactx_invoke_thread(
    8080        void (*main)(void *),
    8181        void *this
     
    9898}
    9999
    100 libcfa_public void __cfactx_start(
     100void __cfactx_start(
    101101        void (*main)(void *),
    102102        struct coroutine$ * cor,
  • libcfa/src/concurrency/io.cfa

    r74ec742 r29d8c02  
    244244
    245245                                        remote = true;
    246                                         __STATS__( true, io.calls.helped++; )
     246                                        __STATS__( false, io.calls.helped++; )
    247247                                }
    248248                                proc->io.target = MAX;
     
    340340        // for convenience, return both the index and the pointer to the sqe
    341341        // sqe == &sqes[idx]
    342         struct $io_context * cfa_io_allocate(struct io_uring_sqe * sqes[], __u32 idxs[], __u32 want) libcfa_public {
     342        struct $io_context * cfa_io_allocate(struct io_uring_sqe * sqes[], __u32 idxs[], __u32 want) {
    343343                // __cfadbg_print_safe(io, "Kernel I/O : attempting to allocate %u\n", want);
    344344
     
    419419        }
    420420
    421         void cfa_io_submit( struct $io_context * inctx, __u32 idxs[], __u32 have, bool lazy ) __attribute__((nonnull (1))) libcfa_public {
     421        void cfa_io_submit( struct $io_context * inctx, __u32 idxs[], __u32 have, bool lazy ) __attribute__((nonnull (1))) {
    422422                // __cfadbg_print_safe(io, "Kernel I/O : attempting to submit %u (%s)\n", have, lazy ? "lazy" : "eager");
    423423
  • libcfa/src/concurrency/io/call.cfa.in

    r74ec742 r29d8c02  
    139139// I/O Interface
    140140//=============================================================================================
    141 #pragma GCC visibility push(default)
    142141"""
    143142
  • libcfa/src/concurrency/io/setup.cfa

    r74ec742 r29d8c02  
    2626
    2727#if !defined(CFA_HAVE_LINUX_IO_URING_H)
    28         void ?{}(io_context_params & this) libcfa_public {}
     28        void ?{}(io_context_params & this) {}
    2929
    3030        void  ?{}($io_context & this, struct cluster & cl) {}
     
    6666#pragma GCC diagnostic pop
    6767
    68         void ?{}(io_context_params & this) libcfa_public {
     68        void ?{}(io_context_params & this) {
    6969                this.num_entries = 256;
    7070        }
  • libcfa/src/concurrency/kernel.cfa

    r74ec742 r29d8c02  
    389389
    390390// KERNEL_ONLY
    391 static void returnToKernel() {
     391void returnToKernel() {
    392392        /* paranoid */ verify( ! __preemption_enabled() );
    393393        coroutine$ * proc_cor = get_coroutine(kernelTLS().this_processor->runner);
     
    547547}
    548548
    549 void unpark( thread$ * thrd, unpark_hint hint ) libcfa_public {
     549void unpark( thread$ * thrd, unpark_hint hint ) {
    550550        if( !thrd ) return;
    551551
     
    558558}
    559559
    560 void park( void ) libcfa_public {
     560void park( void ) {
    561561        __disable_interrupts_checked();
    562562                /* paranoid */ verify( kernelTLS().this_thread->preempted == __NO_PREEMPTION );
     
    601601
    602602// KERNEL ONLY
    603 bool force_yield( __Preemption_Reason reason ) libcfa_public {
     603bool force_yield( __Preemption_Reason reason ) {
    604604        __disable_interrupts_checked();
    605605                thread$ * thrd = kernelTLS().this_thread;
     
    849849//-----------------------------------------------------------------------------
    850850// Debug
    851 bool threading_enabled(void) __attribute__((const)) libcfa_public {
     851bool threading_enabled(void) __attribute__((const)) {
    852852        return true;
    853853}
     
    856856// Statistics
    857857#if !defined(__CFA_NO_STATISTICS__)
    858         void print_halts( processor & this ) libcfa_public {
     858        void print_halts( processor & this ) {
    859859                this.print_halts = true;
    860860        }
     
    873873        }
    874874
    875         static void crawl_cluster_stats( cluster & this ) {
     875        void crawl_cluster_stats( cluster & this ) {
    876876                // Stop the world, otherwise stats could get really messed-up
    877877                // this doesn't solve all problems but does solve many
     
    889889
    890890
    891         void print_stats_now( cluster & this, int flags ) libcfa_public {
     891        void print_stats_now( cluster & this, int flags ) {
    892892                crawl_cluster_stats( this );
    893893                __print_stats( this.stats, flags, "Cluster", this.name, (void*)&this );
  • libcfa/src/concurrency/kernel.hfa

    r74ec742 r29d8c02  
    4949
    5050// Coroutine used py processors for the 2-step context switch
    51 
    52 struct processorCtx_t {
    53         struct coroutine$ self;
     51coroutine processorCtx_t {
    5452        struct processor * proc;
    5553};
  • libcfa/src/concurrency/kernel/cluster.cfa

    r74ec742 r29d8c02  
    4949
    5050// returns the maximum number of processors the RWLock support
    51 __attribute__((weak)) unsigned __max_processors() libcfa_public {
     51__attribute__((weak)) unsigned __max_processors() {
    5252        const char * max_cores_s = getenv("CFA_MAX_PROCESSORS");
    5353        if(!max_cores_s) {
  • libcfa/src/concurrency/kernel/private.hfa

    r74ec742 r29d8c02  
    109109//-----------------------------------------------------------------------------
    110110// Processor
    111 void main(processorCtx_t &);
    112 static inline coroutine$* get_coroutine(processorCtx_t & this) { return &this.self; }
     111void main(processorCtx_t *);
    113112
    114113void * __create_pthread( pthread_t *, void * (*)(void *), void * );
  • libcfa/src/concurrency/kernel/startup.cfa

    r74ec742 r29d8c02  
    120120#endif
    121121
    122 cluster              * mainCluster libcfa_public;
     122cluster              * mainCluster;
    123123processor            * mainProcessor;
    124124thread$              * mainThread;
     
    169169};
    170170
    171 static void ?{}( current_stack_info_t & this ) {
     171void ?{}( current_stack_info_t & this ) {
    172172        __stack_context_t ctx;
    173173        CtxGet( ctx );
     
    209209        // Construct the processor context of the main processor
    210210        void ?{}(processorCtx_t & this, processor * proc) {
    211                 (this.self){ "Processor" };
    212                 this.self.starter = 0p;
     211                (this.__cor){ "Processor" };
     212                this.__cor.starter = 0p;
    213213                this.proc = proc;
    214214        }
     
    526526// Construct the processor context of non-main processors
    527527static void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
    528         (this.self){ info };
     528        (this.__cor){ info };
    529529        this.proc = proc;
    530530}
     
    578578}
    579579
    580 void ?{}(processor & this, const char name[], cluster & _cltr, thread$ * initT) libcfa_public {
     580void ?{}(processor & this, const char name[], cluster & _cltr, thread$ * initT) {
    581581        ( this.terminated ){};
    582582        ( this.runner ){};
     
    591591}
    592592
    593 void ?{}(processor & this, const char name[], cluster & _cltr) libcfa_public {
     593void ?{}(processor & this, const char name[], cluster & _cltr) {
    594594        (this){name, _cltr, 0p};
    595595}
    596596
    597597extern size_t __page_size;
    598 void ^?{}(processor & this) libcfa_public with( this ) {
     598void ^?{}(processor & this) with( this ){
    599599        /* paranoid */ verify( !__atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) );
    600600        __cfadbg_print_safe(runtime_core, "Kernel : core %p signaling termination\n", &this);
     
    623623}
    624624
    625 void ?{}(cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params) libcfa_public with( this ) {
     625void ?{}(cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params) with( this ) {
    626626        this.name = name;
    627627        this.preemption_rate = preemption_rate;
     
    658658}
    659659
    660 void ^?{}(cluster & this) libcfa_public {
     660void ^?{}(cluster & this) {
    661661        destroy(this.io.arbiter);
    662662
  • libcfa/src/concurrency/locks.cfa

    r74ec742 r29d8c02  
    2424#include <stdlib.hfa>
    2525
    26 #pragma GCC visibility push(default)
    27 
    2826//-----------------------------------------------------------------------------
    2927// info_thread
     
    118116}
    119117
    120 static void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
     118void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
    121119        thread$ * t = &try_pop_front( blocked_threads );
    122120        owner = t;
     
    194192        void ^?{}( alarm_node_wrap(L) & this ) { }
    195193
    196         static void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
     194        void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
    197195                // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
    198196                lock( cond->lock __cfaabi_dbg_ctx2 );
     
    218216
    219217        // this casts the alarm node to our wrapped type since we used type erasure
    220         static void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); }
     218        void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); }
    221219}
    222220
    223221//-----------------------------------------------------------------------------
    224 // Synchronization Locks
     222// condition variable
    225223forall(L & | is_blocking_lock(L)) {
    226224
    227         //-----------------------------------------------------------------------------
    228         // condition variable
    229225        void ?{}( condition_variable(L) & this ){
    230226                this.lock{};
     
    235231        void ^?{}( condition_variable(L) & this ){ }
    236232
    237         static void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) {
     233        void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) {
    238234                if(&popped != 0p) {
    239235                        popped.signalled = true;
     
    280276        int counter( condition_variable(L) & this ) with(this) { return count; }
    281277
    282         static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
     278        size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
    283279                // add info_thread to waiting queue
    284280                insert_last( blocked_threads, *i );
     
    293289
    294290        // helper for wait()'s' with no timeout
    295         static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
     291        void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    296292                lock( lock __cfaabi_dbg_ctx2 );
    297293                size_t recursion_count = queue_and_get_recursion(this, &i);
     
    310306
    311307        // helper for wait()'s' with a timeout
    312         static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
     308        void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    313309                lock( lock __cfaabi_dbg_ctx2 );
    314310                size_t recursion_count = queue_and_get_recursion(this, &info);
     
    341337        bool wait( condition_variable(L) & this, L & l, Duration duration                 ) with(this) { WAIT_TIME( 0   , &l , duration ) }
    342338        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , duration ) }
    343 
    344         //-----------------------------------------------------------------------------
    345         // fast_cond_var
    346         void  ?{}( fast_cond_var(L) & this ){
    347                 this.blocked_threads{};
    348                 #ifdef __CFA_DEBUG__
    349                 this.lock_used = 0p;
    350                 #endif
    351         }
    352         void ^?{}( fast_cond_var(L) & this ){ }
    353 
    354         bool notify_one( fast_cond_var(L) & this ) with(this) {
    355                 bool ret = ! blocked_threads`isEmpty;
    356                 if ( ret ) {
    357                         info_thread(L) & popped = try_pop_front( blocked_threads );
    358                         on_notify(*popped.lock, popped.t);
    359                 }
    360                 return ret;
    361         }
    362         bool notify_all( fast_cond_var(L) & this ) with(this) {
    363                 bool ret = ! blocked_threads`isEmpty;
    364                 while( ! blocked_threads`isEmpty ) {
    365                         info_thread(L) & popped = try_pop_front( blocked_threads );
    366                         on_notify(*popped.lock, popped.t);
    367                 }
    368                 return ret;
    369         }
    370 
    371         uintptr_t front( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty ? NULL : blocked_threads`first.info; }
    372         bool empty ( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
    373 
    374         void wait( fast_cond_var(L) & this, L & l ) {
    375                 wait( this, l, 0 );
    376         }
    377 
    378         void wait( fast_cond_var(L) & this, L & l, uintptr_t info ) with(this) {
    379                 // brand cond lock with lock
    380                 #ifdef __CFA_DEBUG__
    381                         if ( lock_used == 0p ) lock_used = &l;
    382                         else { assert(lock_used == &l); }
    383                 #endif
    384                 info_thread( L ) i = { active_thread(), info, &l };
    385                 insert_last( blocked_threads, i );
    386                 size_t recursion_count = on_wait( *i.lock );
    387                 park( );
    388                 on_wakeup(*i.lock, recursion_count);
    389         }
    390339}
    391340
  • libcfa/src/concurrency/locks.hfa

    r74ec742 r29d8c02  
    7373static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    7474
    75 //-----------------------------------------------------------------------------
    76 // MCS Lock
    7775struct mcs_node {
    7876        mcs_node * volatile next;
     
    10098}
    10199
    102 //-----------------------------------------------------------------------------
    103 // Linear backoff Spinlock
    104100struct linear_backoff_then_block_lock {
    105101        // Spin lock used for mutual exclusion
     
    203199
    204200//-----------------------------------------------------------------------------
    205 // Fast Block Lock
    206 
    207 // High efficiency minimal blocking lock
    208 // - No reacquire for cond var
    209 // - No recursive acquisition
    210 // - No ownership
    211 struct fast_block_lock {
    212         // Spin lock used for mutual exclusion
    213         __spinlock_t lock;
    214 
    215         // List of blocked threads
    216         dlist( thread$ ) blocked_threads;
    217 
    218         bool held:1;
    219 };
    220 
    221 static inline void  ?{}( fast_block_lock & this ) with(this) {
    222         lock{};
    223         blocked_threads{};
    224         held = false;
    225 }
    226 static inline void ^?{}( fast_block_lock & this ) {}
    227 static inline void ?{}( fast_block_lock & this, fast_block_lock this2 ) = void;
    228 static inline void ?=?( fast_block_lock & this, fast_block_lock this2 ) = void;
    229 
    230 // if this is called recursively IT WILL DEADLOCK!!!!!
    231 static inline void lock(fast_block_lock & this) with(this) {
    232         lock( lock __cfaabi_dbg_ctx2 );
    233         if (held) {
    234                 insert_last( blocked_threads, *active_thread() );
    235                 unlock( lock );
    236                 park( );
    237                 return;
    238         }
    239         held = true;
    240         unlock( lock );
    241 }
    242 
    243 static inline void unlock(fast_block_lock & this) with(this) {
    244         lock( lock __cfaabi_dbg_ctx2 );
    245         /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
    246         thread$ * t = &try_pop_front( blocked_threads );
    247         held = ( t ? true : false );
    248         unpark( t );
    249         unlock( lock );
    250 }
    251 
    252 static inline void on_notify(fast_block_lock & this, struct thread$ * t ) { unpark(t); }
    253 static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
    254 static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
    255 
    256 //-----------------------------------------------------------------------------
    257201// is_blocking_lock
    258202trait is_blocking_lock(L & | sized(L)) {
     
    282226// Synchronization Locks
    283227forall(L & | is_blocking_lock(L)) {
    284 
    285         //-----------------------------------------------------------------------------
    286         // condition_variable
    287 
    288         // The multi-tool condition variable
    289         // - can pass timeouts to wait for either a signal or timeout
    290         // - can wait without passing a lock
    291         // - can have waiters reacquire different locks while waiting on the same cond var
    292         // - has shadow queue
    293         // - can be signalled outside of critical sections with no locks held
    294228        struct condition_variable {
    295229                // Spin lock used for mutual exclusion
     
    324258        bool wait( condition_variable(L) & this, L & l, Duration duration );
    325259        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );
    326 
    327         //-----------------------------------------------------------------------------
    328         // fast_cond_var
    329 
    330         // The trimmed and slim condition variable
    331         // - no internal lock so you must hold a lock while using this cond var
    332         // - signalling without holding branded lock is UNSAFE!
    333         // - only allows usage of one lock, cond var is branded after usage
    334         struct fast_cond_var {
    335                 // List of blocked threads
    336                 dlist( info_thread(L) ) blocked_threads;
    337 
    338                 #ifdef __CFA_DEBUG__
    339                 L * lock_used;
    340                 #endif
    341         };
    342 
    343 
    344         void  ?{}( fast_cond_var(L) & this );
    345         void ^?{}( fast_cond_var(L) & this );
    346 
    347         bool notify_one( fast_cond_var(L) & this );
    348         bool notify_all( fast_cond_var(L) & this );
    349 
    350         uintptr_t front( fast_cond_var(L) & this );
    351 
    352         bool empty  ( fast_cond_var(L) & this );
    353 
    354         void wait( fast_cond_var(L) & this, L & l );
    355         void wait( fast_cond_var(L) & this, L & l, uintptr_t info );
    356 }
     260}
  • libcfa/src/concurrency/monitor.cfa

    r74ec742 r29d8c02  
    4444static inline void restore( monitor$ * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );
    4545
    46 static inline void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info );
    47 static inline void ?{}(__condition_criterion_t & this );
    48 static inline void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t * owner );
    49 
    5046static inline void init     ( __lock_size_t count, monitor$ * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
    5147static inline void init_push( __lock_size_t count, monitor$ * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
     
    247243
    248244// Leave single monitor
    249 static void __leave( monitor$ * this ) {
     245void __leave( monitor$ * this ) {
    250246        // Lock the monitor spinlock
    251247        lock( this->lock __cfaabi_dbg_ctx2 );
     
    282278
    283279// Leave single monitor for the last time
    284 static void __dtor_leave( monitor$ * this, bool join ) {
     280void __dtor_leave( monitor$ * this, bool join ) {
    285281        __cfaabi_dbg_debug_do(
    286282                if( active_thread() != this->owner ) {
     
    348344// Ctor for monitor guard
    349345// Sorts monitors before entering
    350 void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count, fptr_t func ) libcfa_public {
     346void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count, fptr_t func ) {
    351347        thread$ * thrd = active_thread();
    352348
     
    373369}
    374370
    375 void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count ) libcfa_public {
     371void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count ) {
    376372        this{ m, count, 0p };
    377373}
     
    379375
    380376// Dtor for monitor guard
    381 void ^?{}( monitor_guard_t & this ) libcfa_public {
     377void ^?{}( monitor_guard_t & this ) {
    382378        // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count);
    383379
     
    393389// Ctor for monitor guard
    394390// Sorts monitors before entering
    395 void ?{}( monitor_dtor_guard_t & this, monitor$ * m [], fptr_t func, bool join ) libcfa_public {
     391void ?{}( monitor_dtor_guard_t & this, monitor$ * m [], fptr_t func, bool join ) {
    396392        // optimization
    397393        thread$ * thrd = active_thread();
     
    413409
    414410// Dtor for monitor guard
    415 void ^?{}( monitor_dtor_guard_t & this ) libcfa_public {
     411void ^?{}( monitor_dtor_guard_t & this ) {
    416412        // Leave the monitors in order
    417413        __dtor_leave( this.m, this.join );
     
    423419//-----------------------------------------------------------------------------
    424420// Internal scheduling types
    425 static void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
     421void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
    426422        this.waiting_thread = waiting_thread;
    427423        this.count = count;
     
    430426}
    431427
    432 static void ?{}(__condition_criterion_t & this ) with( this ) {
     428void ?{}(__condition_criterion_t & this ) with( this ) {
    433429        ready  = false;
    434430        target = 0p;
     
    437433}
    438434
    439 static void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t & owner ) {
     435void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t & owner ) {
    440436        this.ready  = false;
    441437        this.target = target;
     
    446442//-----------------------------------------------------------------------------
    447443// Internal scheduling
    448 void wait( condition & this, uintptr_t user_info = 0 ) libcfa_public {
     444void wait( condition & this, uintptr_t user_info = 0 ) {
    449445        brand_condition( this );
    450446
     
    500496}
    501497
    502 bool signal( condition & this ) libcfa_public {
     498bool signal( condition & this ) {
    503499        if( is_empty( this ) ) { return false; }
    504500
     
    542538}
    543539
    544 bool signal_block( condition & this ) libcfa_public {
     540bool signal_block( condition & this ) {
    545541        if( !this.blocked.head ) { return false; }
    546542
     
    590586
    591587// Access the user_info of the thread waiting at the front of the queue
    592 uintptr_t front( condition & this ) libcfa_public {
     588uintptr_t front( condition & this ) {
    593589        verifyf( !is_empty(this),
    594590                "Attempt to access user data on an empty condition.\n"
     
    612608//              setup mask
    613609//              block
    614 void __waitfor_internal( const __waitfor_mask_t & mask, int duration ) libcfa_public {
     610void __waitfor_internal( const __waitfor_mask_t & mask, int duration ) {
    615611        // This statment doesn't have a contiguous list of monitors...
    616612        // Create one!
     
    998994// Can't be accepted since a mutex stmt is effectively an anonymous routine
    999995// Thus we do not need a monitor group
    1000 void lock( monitor$ * this ) libcfa_public {
     996void lock( monitor$ * this ) {
    1001997        thread$ * thrd = active_thread();
    1002998
     
    10501046// Leave routine for mutex stmt
    10511047// Is just a wrapper around __leave for the is_lock trait to see
    1052 void unlock( monitor$ * this ) libcfa_public { __leave( this ); }
     1048void unlock( monitor$ * this ) { __leave( this ); }
    10531049
    10541050// Local Variables: //
  • libcfa/src/concurrency/monitor.hfa

    r74ec742 r29d8c02  
    119119}
    120120
    121 // void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info );
    122 // void ?{}(__condition_criterion_t & this );
    123 // void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t * owner );
     121void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info );
     122void ?{}(__condition_criterion_t & this );
     123void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t * owner );
    124124
    125125struct condition {
  • libcfa/src/concurrency/preemption.cfa

    r74ec742 r29d8c02  
    3838#endif
    3939
    40 __attribute__((weak)) Duration default_preemption() libcfa_public {
     40__attribute__((weak)) Duration default_preemption() {
    4141        const char * preempt_rate_s = getenv("CFA_DEFAULT_PREEMPTION");
    4242        if(!preempt_rate_s) {
     
    238238//----------
    239239// special case for preemption since used often
    240 __attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_public {
     240__attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() {
    241241        // create a assembler label before
    242242        // marked as clobber all to avoid movement
     
    276276// Get data from the TLS block
    277277// struct asm_region __cfaasm_get;
    278 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__, visibility("default"))); //no inline to avoid problems
     278uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems
    279279uintptr_t __cfatls_get( unsigned long int offset ) {
    280280        // create a assembler label before
     
    295295extern "C" {
    296296        // Disable interrupts by incrementing the counter
    297         __attribute__((__noinline__, visibility("default"))) void disable_interrupts() libcfa_public {
     297        void disable_interrupts() {
    298298                // create a assembler label before
    299299                // marked as clobber all to avoid movement
     
    326326        // Enable interrupts by decrementing the counter
    327327        // If counter reaches 0, execute any pending __cfactx_switch
    328         void enable_interrupts( bool poll ) libcfa_public {
     328        void enable_interrupts( bool poll ) {
    329329                // Cache the processor now since interrupts can start happening after the atomic store
    330330                processor   * proc = __cfaabi_tls.this_processor;
     
    362362//-----------------------------------------------------------------------------
    363363// Kernel Signal Debug
    364 void __cfaabi_check_preemption() libcfa_public {
     364void __cfaabi_check_preemption() {
    365365        bool ready = __preemption_enabled();
    366366        if(!ready) { abort("Preemption should be ready"); }
  • libcfa/src/concurrency/ready_subqueue.hfa

    r74ec742 r29d8c02  
    8383        /* paranoid */ verify( node->link.ts   != 0  );
    8484        /* paranoid */ verify( this.anchor.ts  != 0  );
    85         /* paranoid */ verify( (this.anchor.ts  == MAX) == is_empty );
    8685        return [node, this.anchor.ts];
    8786}
     
    9493// Return the timestamp
    9594static inline unsigned long long ts(__intrusive_lane_t & this) {
    96         // Cannot verify 'emptiness' here since it may not be locked
     95        // Cannot verify here since it may not be locked
    9796        /* paranoid */ verify(this.anchor.ts != 0);
    9897        return this.anchor.ts;
  • libcfa/src/concurrency/thread.cfa

    r74ec742 r29d8c02  
    2626
    2727extern uint32_t __global_random_seed, __global_random_prime, __global_random_mask;
    28 
    29 #pragma GCC visibility push(default)
    3028
    3129//-----------------------------------------------------------------------------
  • libcfa/src/containers/maybe.cfa

    r74ec742 r29d8c02  
    1717#include <assert.h>
    1818
    19 #pragma GCC visibility push(default)
    2019
    2120forall(T)
  • libcfa/src/containers/result.cfa

    r74ec742 r29d8c02  
    1717#include <assert.h>
    1818
    19 #pragma GCC visibility push(default)
    2019
    2120forall(T, E)
  • libcfa/src/containers/string.cfa

    r74ec742 r29d8c02  
    1818#include <stdlib.hfa>
    1919
    20 #pragma GCC visibility push(default)
    2120
    2221/*
  • libcfa/src/containers/string_sharectx.hfa

    r74ec742 r29d8c02  
    1616#pragma once
    1717
    18 #pragma GCC visibility push(default)
    19 
    2018//######################### String Sharing Context #########################
    2119
    2220struct VbyteHeap;
    2321
    24 // A string_sharectx
     22// A string_sharectx 
    2523//
    2624// Usage:
  • libcfa/src/containers/vector.cfa

    r74ec742 r29d8c02  
    1818#include <stdlib.hfa>
    1919
    20 #pragma GCC visibility push(default)
    21 
    2220forall(T, allocator_t | allocator_c(T, allocator_t))
    23 static void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other);
     21void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other);
    2422
    2523//------------------------------------------------------------------------------
     
    8583
    8684forall(T, allocator_t | allocator_c(T, allocator_t))
    87 static void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other)
     85void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other)
    8886{
    8987        this->size = other->size;
  • libcfa/src/device/cpu.cfa

    r74ec742 r29d8c02  
    3131}
    3232
    33 #include "bits/defs.hfa"
    3433#include "algorithms/range_iterator.hfa"
    3534
     
    457456}
    458457
    459 libcfa_public cpu_info_t cpu_info;
     458cpu_info_t cpu_info;
  • libcfa/src/exception.c

    r74ec742 r29d8c02  
    2727#include "stdhdr/assert.h"
    2828#include "virtual.h"
    29 
    30 #pragma GCC visibility push(default)
    31 
    3229#include "lsda.h"
    3330
     
    264261#else // defined( __ARM_ARCH )
    265262        // The return code from _Unwind_RaiseException seems to be corrupt on ARM at end of stack.
    266         // This workaround tries to keep default exception handling working.
     263        // This workaround tries to keep default exception handling working. 
    267264        if ( ret == _URC_FATAL_PHASE1_ERROR || ret == _URC_FATAL_PHASE2_ERROR ) {
    268265#endif
  • libcfa/src/fstream.cfa

    r74ec742 r29d8c02  
    2222#include <assert.h>
    2323#include <errno.h>                                                                              // errno
    24 
    25 #pragma GCC visibility push(default)
    2624
    2725// *********************************** ofstream ***********************************
     
    120118                // abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno );
    121119        } // if
    122         (os){ file };                                                                           // initialize
     120        (os){ file };                                                                           // initialize 
    123121} // open
    124122
     
    159157        va_list args;
    160158        va_start( args, format );
    161 
     159               
    162160        int len;
    163161    for ( cnt; 10 ) {
     
    243241                // abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno );
    244242        } // if
    245         (is){ file };                                                                           // initialize
     243        (is){ file };                                                                           // initialize 
    246244} // open
    247245
  • libcfa/src/fstream.hfa

    r74ec742 r29d8c02  
    1818#include "bits/weakso_locks.hfa"                                                // mutex_lock
    1919#include "iostream.hfa"
     20#include <exception.hfa>
    2021
    2122
  • libcfa/src/heap.cfa

    r74ec742 r29d8c02  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 29 19:05:03 2022
    13 // Update Count     : 1167
     12// Last Modified On : Mon Apr 25 18:51:36 2022
     13// Update Count     : 1147
    1414//
    1515
     
    3636static bool traceHeap = false;
    3737
    38 inline bool traceHeap() libcfa_public { return traceHeap; }
    39 
    40 bool traceHeapOn() libcfa_public {
     38inline bool traceHeap() { return traceHeap; }
     39
     40bool traceHeapOn() {
    4141        bool temp = traceHeap;
    4242        traceHeap = true;
     
    4444} // traceHeapOn
    4545
    46 bool traceHeapOff() libcfa_public {
     46bool traceHeapOff() {
    4747        bool temp = traceHeap;
    4848        traceHeap = false;
     
    5050} // traceHeapOff
    5151
    52 bool traceHeapTerm() libcfa_public { return false; }
     52bool traceHeapTerm() { return false; }
    5353
    5454
    5555static bool prtFree = false;
    5656
    57 static bool prtFree() {
     57bool prtFree() {
    5858        return prtFree;
    5959} // prtFree
    6060
    61 static bool prtFreeOn() {
     61bool prtFreeOn() {
    6262        bool temp = prtFree;
    6363        prtFree = true;
     
    6565} // prtFreeOn
    6666
    67 static bool prtFreeOff() {
     67bool prtFreeOff() {
    6868        bool temp = prtFree;
    6969        prtFree = false;
     
    8787
    8888
    89 //####################### Heap Statistics ####################
     89#ifdef __CFA_DEBUG__
     90static size_t allocUnfreed;                                                             // running total of allocations minus frees
     91
     92static void prtUnfreed() {
     93        if ( allocUnfreed != 0 ) {
     94                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     95                char helpText[512];
     96                int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n"
     97                                                        "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
     98                                                        (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
     99                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     100        } // if
     101} // prtUnfreed
     102
     103extern int cfa_main_returned;                                                   // from interpose.cfa
     104extern "C" {
     105        void heapAppStart() {                                                           // called by __cfaabi_appready_startup
     106                allocUnfreed = 0;
     107        } // heapAppStart
     108
     109        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
     110                fclose( stdin ); fclose( stdout );
     111                if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
     112        } // heapAppStop
     113} // extern "C"
     114#endif // __CFA_DEBUG__
     115
     116
     117// statically allocated variables => zero filled.
     118static size_t heapExpand;                                                               // sbrk advance
     119static size_t mmapStart;                                                                // cross over point for mmap
     120static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
     121// extern visibility, used by runtime kernel
     122size_t __page_size;                                                                             // architecture pagesize
     123int __map_prot;                                                                                 // common mmap/mprotect protection
     124
     125
     126#define SPINLOCK 0
     127#define LOCKFREE 1
     128#define BUCKETLOCK SPINLOCK
     129#if BUCKETLOCK == SPINLOCK
     130#elif BUCKETLOCK == LOCKFREE
     131#include <stackLockFree.hfa>
     132#else
     133        #error undefined lock type for bucket lock
     134#endif // LOCKFREE
     135
     136// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
     137// Break recursion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
     138enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
     139
     140struct Heap {
     141        struct Storage {
     142                struct Header {                                                                 // header
     143                        union Kind {
     144                                struct RealHeader {
     145                                        union {
     146                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
     147                                                        union {
     148                                                                // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped
     149                                                                // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
     150                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
     151                                                                size_t blockSize;               // size for munmap (must overlay alignment)
     152                                                                #if BUCKETLOCK == SPINLOCK
     153                                                                Storage * next;                 // freed block points to next freed block of same size
     154                                                                #endif // SPINLOCK
     155                                                        };
     156                                                        size_t size;                            // allocation size in bytes
     157                                                };
     158                                                #if BUCKETLOCK == LOCKFREE
     159                                                Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
     160                                                #endif // LOCKFREE
     161                                        };
     162                                } real; // RealHeader
     163
     164                                struct FakeHeader {
     165                                        uintptr_t alignment;                            // 1st low-order bit => fake header & alignment
     166                                        uintptr_t offset;
     167                                } fake; // FakeHeader
     168                        } kind; // Kind
     169                } header; // Header
     170
     171                char pad[libAlign() - sizeof( Header )];
     172                char data[0];                                                                   // storage
     173        }; // Storage
     174
     175        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
     176
     177        struct FreeHeader {
     178                #if BUCKETLOCK == SPINLOCK
     179                __spinlock_t lock;                                                              // must be first field for alignment
     180                Storage * freeList;
     181                #else
     182                StackLF(Storage) freeList;
     183                #endif // BUCKETLOCK
     184                size_t blockSize;                                                               // size of allocations on this list
     185        }; // FreeHeader
     186
     187        // must be first fields for alignment
     188        __spinlock_t extlock;                                                           // protects allocation-buffer extension
     189        FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
     190
     191        void * heapBegin;                                                                       // start of heap
     192        void * heapEnd;                                                                         // logical end of heap
     193        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
     194}; // Heap
     195
     196#if BUCKETLOCK == LOCKFREE
     197static inline {
     198        Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
     199        void ?{}( Heap.FreeHeader & ) {}
     200        void ^?{}( Heap.FreeHeader & ) {}
     201} // distribution
     202#endif // LOCKFREE
     203
     204static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
     205
     206
     207#ifdef FASTLOOKUP
     208enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
     209static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
     210#endif // FASTLOOKUP
     211
     212static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
     213#ifdef __CFA_DEBUG__
     214static bool heapBoot = 0;                                                               // detect recursion during boot
     215#endif // __CFA_DEBUG__
     216
     217
     218// Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16.
     219// Smaller multiples of 16 and powers of 2 are common allocation sizes, so make them generate the minimum required bucket size.
     220// malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed.
     221static const unsigned int bucketSizes[] @= {                    // different bucket sizes
     222        16 + sizeof(Heap.Storage), 32 + sizeof(Heap.Storage), 48 + sizeof(Heap.Storage), 64 + sizeof(Heap.Storage), // 4
     223        96 + sizeof(Heap.Storage), 112 + sizeof(Heap.Storage), 128 + sizeof(Heap.Storage), // 3
     224        160, 192, 224, 256 + sizeof(Heap.Storage), // 4
     225        320, 384, 448, 512 + sizeof(Heap.Storage), // 4
     226        640, 768, 896, 1_024 + sizeof(Heap.Storage), // 4
     227        1_536, 2_048 + sizeof(Heap.Storage), // 2
     228        2_560, 3_072, 3_584, 4_096 + sizeof(Heap.Storage), // 4
     229        6_144, 8_192 + sizeof(Heap.Storage), // 2
     230        9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(Heap.Storage), // 8
     231        18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(Heap.Storage), // 8
     232        36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(Heap.Storage), // 8
     233        73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(Heap.Storage), // 8
     234        147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(Heap.Storage), // 8
     235        294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(Heap.Storage), // 8
     236        655_360, 786_432, 917_504, 1_048_576 + sizeof(Heap.Storage), // 4
     237        1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(Heap.Storage), // 8
     238        2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(Heap.Storage), // 4
     239};
     240
     241static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
     242
     243// The constructor for heapManager is called explicitly in memory_startup.
     244static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
     245
     246
     247//####################### Memory Allocation Routines Helpers ####################
    90248
    91249
     
    149307        return lhs;
    150308} // ?+=?
    151 #endif // __STATISTICS__
    152 
    153 
    154 #define SPINLOCK 0
    155 #define LOCKFREE 1
    156 #define BUCKETLOCK SPINLOCK
    157 #if BUCKETLOCK == SPINLOCK
    158 #elif BUCKETLOCK == LOCKFREE
    159 #include <stackLockFree.hfa>
    160 #else
    161         #error undefined lock type for bucket lock
    162 #endif // LOCKFREE
    163 
    164 // Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    165 // Break recursion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    166 enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
    167 
    168 struct Heap {
    169         struct Storage {
    170                 struct Header {                                                                 // header
    171                         union Kind {
    172                                 struct RealHeader {
    173                                         union {
    174                                                 struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    175                                                         union {
    176                                                                 // 2nd low-order bit => zero filled, 3rd low-order bit => mmapped
    177                                                                 // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
    178                                                                 void * home;                    // allocated block points back to home locations (must overlay alignment)
    179                                                                 size_t blockSize;               // size for munmap (must overlay alignment)
    180                                                                 #if BUCKETLOCK == SPINLOCK
    181                                                                 Storage * next;                 // freed block points to next freed block of same size
    182                                                                 #endif // SPINLOCK
    183                                                         };
    184                                                         size_t size;                            // allocation size in bytes
    185                                                 };
    186                                                 #if BUCKETLOCK == LOCKFREE
    187                                                 Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
    188                                                 #endif // LOCKFREE
    189                                         };
    190                                 } real; // RealHeader
    191 
    192                                 struct FakeHeader {
    193                                         uintptr_t alignment;                            // 1st low-order bit => fake header & alignment
    194                                         uintptr_t offset;
    195                                 } fake; // FakeHeader
    196                         } kind; // Kind
    197                 } header; // Header
    198 
    199                 char pad[libAlign() - sizeof( Header )];
    200                 char data[0];                                                                   // storage
    201         }; // Storage
    202 
    203         static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    204 
    205         struct FreeHeader {
    206                 size_t blockSize __attribute__(( aligned (8) )); // size of allocations on this list
    207                 #if BUCKETLOCK == SPINLOCK
    208                 __spinlock_t lock;
    209                 Storage * freeList;
    210                 #else
    211                 StackLF(Storage) freeList;
    212                 #endif // BUCKETLOCK
    213         } __attribute__(( aligned (8) )); // FreeHeader
    214 
    215         FreeHeader freeLists[NoBucketSizes];                            // buckets for different allocation sizes
    216 
    217         __spinlock_t extlock;                                                           // protects allocation-buffer extension
    218         void * heapBegin;                                                                       // start of heap
    219         void * heapEnd;                                                                         // logical end of heap
    220         size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    221 }; // Heap
    222 
    223 #if BUCKETLOCK == LOCKFREE
    224 static inline {
    225         Link(Heap.Storage) * ?`next( Heap.Storage * this ) { return &this->header.kind.real.next; }
    226         void ?{}( Heap.FreeHeader & ) {}
    227         void ^?{}( Heap.FreeHeader & ) {}
    228 } // distribution
    229 #endif // LOCKFREE
    230 
    231 static inline size_t getKey( const Heap.FreeHeader & freeheader ) { return freeheader.blockSize; }
    232 
    233 
    234 #ifdef FASTLOOKUP
    235 enum { LookupSizes = 65_536 + sizeof(Heap.Storage) }; // number of fast lookup sizes
    236 static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    237 #endif // FASTLOOKUP
    238 
    239 static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
    240 #ifdef __CFA_DEBUG__
    241 static bool heapBoot = 0;                                                               // detect recursion during boot
    242 #endif // __CFA_DEBUG__
    243 
    244 
    245 // Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16.
    246 // Smaller multiples of 16 and powers of 2 are common allocation sizes, so make them generate the minimum required bucket size.
    247 // malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed.
    248 static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    249         16 + sizeof(Heap.Storage), 32 + sizeof(Heap.Storage), 48 + sizeof(Heap.Storage), 64 + sizeof(Heap.Storage), // 4
    250         96 + sizeof(Heap.Storage), 112 + sizeof(Heap.Storage), 128 + sizeof(Heap.Storage), // 3
    251         160, 192, 224, 256 + sizeof(Heap.Storage), // 4
    252         320, 384, 448, 512 + sizeof(Heap.Storage), // 4
    253         640, 768, 896, 1_024 + sizeof(Heap.Storage), // 4
    254         1_536, 2_048 + sizeof(Heap.Storage), // 2
    255         2_560, 3_072, 3_584, 4_096 + sizeof(Heap.Storage), // 4
    256         6_144, 8_192 + sizeof(Heap.Storage), // 2
    257         9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(Heap.Storage), // 8
    258         18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(Heap.Storage), // 8
    259         36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(Heap.Storage), // 8
    260         73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(Heap.Storage), // 8
    261         147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(Heap.Storage), // 8
    262         294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(Heap.Storage), // 8
    263         655_360, 786_432, 917_504, 1_048_576 + sizeof(Heap.Storage), // 4
    264         1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(Heap.Storage), // 8
    265         2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(Heap.Storage), // 4
    266 };
    267 
    268 static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    269 
    270 // The constructor for heapManager is called explicitly in memory_startup.
    271 static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    272 
    273 
    274 //####################### Memory Allocation Routines Helpers ####################
    275 
    276 
    277 #ifdef __CFA_DEBUG__
    278 static size_t allocUnfreed;                                                             // running total of allocations minus frees
    279 
    280 static void prtUnfreed() {
    281         if ( allocUnfreed != 0 ) {
    282                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    283                 char helpText[512];
    284                 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    285                                                                         "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n"
    286                                                                         "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    287                                                                         (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
    288         } // if
    289 } // prtUnfreed
    290 
    291 extern int cfa_main_returned;                                                   // from interpose.cfa
    292 extern "C" {
    293         void heapAppStart() {                                                           // called by __cfaabi_appready_startup
    294                 allocUnfreed = 0;
    295         } // heapAppStart
    296 
    297         void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    298                 fclose( stdin ); fclose( stdout );
    299                 if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
    300         } // heapAppStop
    301 } // extern "C"
    302 #endif // __CFA_DEBUG__
    303 
    304 
    305 #ifdef __STATISTICS__
     309
    306310static HeapStatistics stats;                                                    // zero filled
    307311static unsigned int sbrk_calls;
     
    383387
    384388
    385 // statically allocated variables => zero filled.
    386 static size_t heapExpand;                                                               // sbrk advance
    387 static size_t mmapStart;                                                                // cross over point for mmap
    388 static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    389 // extern visibility, used by runtime kernel
    390 // would be cool to remove libcfa_public but it's needed for libcfathread
    391 libcfa_public size_t __page_size;                                                       // architecture pagesize
    392 libcfa_public int __map_prot;                                                           // common mmap/mprotect protection
    393 
    394 
    395389// thunk problem
    396390size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    496490        } else {
    497491                fakeHeader( header, alignment );
    498                 if ( unlikely( MmappedBit( header ) ) ) {               // mmapped ?
    499                         verify( addr < heapBegin || heapEnd < addr );
     492                if ( unlikely( MmappedBit( header ) ) ) {
     493                        assert( addr < heapBegin || heapEnd < addr );
    500494                        size = ClearStickyBits( header->kind.real.blockSize ); // mmap size
    501495                        return true;
     
    509503        checkHeader( header < (Heap.Storage.Header *)heapBegin || (Heap.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    510504
    511         Heap * homeManager;
    512         if ( unlikely( freeHead == 0p || // freed and only free-list node => null link
    513                                    // freed and link points at another free block not to a bucket in the bucket array.
    514                                    freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) ) {
    515                 abort( "**** Error **** attempt to %s storage %p with corrupted header.\n"
    516                            "Possible cause is duplicate free on same block or overwriting of header information.",
    517                            name, addr );
    518         } // if
     505        if ( freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) {
     506                abort( "Attempt to %s storage %p with corrupted header.\n"
     507                           "Possible cause is duplicate free on same block or overwriting of header information.",
     508                           name, addr );
     509        } // if
    519510        #endif // __CFA_DEBUG__
    520511
     
    569560                sbrk_storage += increase;
    570561                #endif // __STATISTICS__
    571 
    572562                #ifdef __CFA_DEBUG__
    573563                // Set new memory to garbage so subsequent uninitialized usages might fail.
     
    575565                //Memset( (char *)heapEnd + heapRemaining, increase );
    576566                #endif // __CFA_DEBUG__
    577 
    578567                rem = heapRemaining + increase - size;
    579568        } // if
     
    662651        __atomic_add_fetch( &allocUnfreed, tsize, __ATOMIC_SEQ_CST );
    663652        if ( traceHeap() ) {
    664                 char helpText[64];
    665                 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    666                                                                         "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize ); // print debug/nodebug
     653                enum { BufferSize = 64 };
     654                char helpText[BufferSize];
     655                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
     656                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    667657        } // if
    668658        #endif // __CFA_DEBUG__
     
    721711        if ( traceHeap() ) {
    722712                char helpText[64];
    723                 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    724                                                                         "Free( %p ) size:%zu\n", addr, size ); // print debug/nodebug
     713                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
     714                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    725715        } // if
    726716        #endif // __CFA_DEBUG__
     
    728718
    729719
    730 static size_t prtFree( Heap & manager ) with( manager ) {
     720size_t prtFree( Heap & manager ) with( manager ) {
    731721        size_t total = 0;
    732722        #ifdef __STATISTICS__
     
    880870        // Allocates size bytes and returns a pointer to the allocated memory.  The contents are undefined. If size is 0,
    881871        // then malloc() returns a unique pointer value that can later be successfully passed to free().
    882         void * malloc( size_t size ) libcfa_public {
     872        void * malloc( size_t size ) {
    883873                #ifdef __STATISTICS__
    884874                if ( likely( size > 0 ) ) {
     
    895885
    896886        // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes.
    897         void * aalloc( size_t dim, size_t elemSize ) libcfa_public {
     887        void * aalloc( size_t dim, size_t elemSize ) {
    898888                size_t size = dim * elemSize;
    899889                #ifdef __STATISTICS__
     
    911901
    912902        // Same as aalloc() with memory set to zero.
    913         void * calloc( size_t dim, size_t elemSize ) libcfa_public {
     903        void * calloc( size_t dim, size_t elemSize ) {
    914904                size_t size = dim * elemSize;
    915905          if ( unlikely( size ) == 0 ) {                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     
    952942        // not 0p, then the call is equivalent to free(oaddr). Unless oaddr is 0p, it must have been returned by an earlier
    953943        // call to malloc(), alloc(), calloc() or realloc(). If the area pointed to was moved, a free(oaddr) is done.
    954         void * resize( void * oaddr, size_t size ) libcfa_public {
     944        void * resize( void * oaddr, size_t size ) {
    955945                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    956946          if ( unlikely( size == 0 ) ) {                                        // special cases
     
    997987        // Same as resize() but the contents are unchanged in the range from the start of the region up to the minimum of
    998988        // the old and new sizes.
    999         void * realloc( void * oaddr, size_t size ) libcfa_public {
     989        void * realloc( void * oaddr, size_t size ) {
    1000990                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    1001991          if ( unlikely( size == 0 ) ) {                                        // special cases
     
    10611051
    10621052        // Same as realloc() except the new allocation size is large enough for an array of nelem elements of size elsize.
    1063         void * reallocarray( void * oaddr, size_t dim, size_t elemSize ) libcfa_public {
     1053        void * reallocarray( void * oaddr, size_t dim, size_t elemSize ) {
    10641054                return realloc( oaddr, dim * elemSize );
    10651055        } // reallocarray
     
    10671057
    10681058        // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete)
    1069         void * memalign( size_t alignment, size_t size ) libcfa_public {
     1059        void * memalign( size_t alignment, size_t size ) {
    10701060                #ifdef __STATISTICS__
    10711061                if ( likely( size > 0 ) ) {
     
    10821072
    10831073        // Same as aalloc() with memory alignment.
    1084         void * amemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
     1074        void * amemalign( size_t alignment, size_t dim, size_t elemSize ) {
    10851075                size_t size = dim * elemSize;
    10861076                #ifdef __STATISTICS__
     
    10981088
    10991089        // Same as calloc() with memory alignment.
    1100         void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) libcfa_public {
     1090        void * cmemalign( size_t alignment, size_t dim, size_t elemSize ) {
    11011091                size_t size = dim * elemSize;
    11021092          if ( unlikely( size ) == 0 ) {                                        // 0 BYTE ALLOCATION RETURNS NULL POINTER
     
    11371127        // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple
    11381128        // of alignment. This requirement is universally ignored.
    1139         void * aligned_alloc( size_t alignment, size_t size ) libcfa_public {
     1129        void * aligned_alloc( size_t alignment, size_t size ) {
    11401130                return memalign( alignment, size );
    11411131        } // aligned_alloc
     
    11461136        // is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later be successfully passed to
    11471137        // free(3).
    1148         int posix_memalign( void ** memptr, size_t alignment, size_t size ) libcfa_public {
     1138        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    11491139          if ( unlikely( alignment < libAlign() || ! is_pow2( alignment ) ) ) return EINVAL; // check alignment
    11501140                *memptr = memalign( alignment, size );
     
    11551145        // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the
    11561146        // page size.  It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
    1157         void * valloc( size_t size ) libcfa_public {
     1147        void * valloc( size_t size ) {
    11581148                return memalign( __page_size, size );
    11591149        } // valloc
     
    11611151
    11621152        // Same as valloc but rounds size to multiple of page size.
    1163         void * pvalloc( size_t size ) libcfa_public {
     1153        void * pvalloc( size_t size ) {
    11641154                return memalign( __page_size, ceiling2( size, __page_size ) ); // round size to multiple of page size
    11651155        } // pvalloc
     
    11691159        // or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is
    11701160        // 0p, no operation is performed.
    1171         void free( void * addr ) libcfa_public {
     1161        void free( void * addr ) {
    11721162          if ( unlikely( addr == 0p ) ) {                                       // special case
    11731163                        #ifdef __STATISTICS__
     
    11901180
    11911181        // Returns the alignment of an allocation.
    1192         size_t malloc_alignment( void * addr ) libcfa_public {
     1182        size_t malloc_alignment( void * addr ) {
    11931183          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    11941184                Heap.Storage.Header * header = HeaderAddr( addr );
     
    12021192
    12031193        // Returns true if the allocation is zero filled, e.g., allocated by calloc().
    1204         bool malloc_zero_fill( void * addr ) libcfa_public {
     1194        bool malloc_zero_fill( void * addr ) {
    12051195          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    12061196                Heap.Storage.Header * header = HeaderAddr( addr );
     
    12131203
    12141204        // Returns original total allocation size (not bucket size) => array size is dimension * sizeof(T).
    1215         size_t malloc_size( void * addr ) libcfa_public {
     1205        size_t malloc_size( void * addr ) {
    12161206          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    12171207                Heap.Storage.Header * header = HeaderAddr( addr );
     
    12251215        // Returns the number of usable bytes in the block pointed to by ptr, a pointer to a block of memory allocated by
    12261216        // malloc or a related function.
    1227         size_t malloc_usable_size( void * addr ) libcfa_public {
     1217        size_t malloc_usable_size( void * addr ) {
    12281218          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    12291219                Heap.Storage.Header * header;
     
    12371227
    12381228        // Prints (on default standard error) statistics about memory allocated by malloc and related functions.
    1239         void malloc_stats( void ) libcfa_public {
     1229        void malloc_stats( void ) {
    12401230                #ifdef __STATISTICS__
    12411231                printStats();
     
    12461236
    12471237        // Changes the file descriptor where malloc_stats() writes statistics.
    1248         int malloc_stats_fd( int fd __attribute__(( unused )) ) libcfa_public {
     1238        int malloc_stats_fd( int fd __attribute__(( unused )) ) {
    12491239                #ifdef __STATISTICS__
    12501240                int temp = stats_fd;
     
    12601250        // The string is printed on the file stream stream.  The exported string includes information about all arenas (see
    12611251        // malloc).
    1262         int malloc_info( int options, FILE * stream __attribute__(( unused )) ) libcfa_public {
     1252        int malloc_info( int options, FILE * stream __attribute__(( unused )) ) {
    12631253          if ( options != 0 ) { errno = EINVAL; return -1; }
    12641254                #ifdef __STATISTICS__
     
    12721262        // Adjusts parameters that control the behaviour of the memory-allocation functions (see malloc). The param argument
    12731263        // specifies the parameter to be modified, and value specifies the new value for that parameter.
    1274         int mallopt( int option, int value ) libcfa_public {
     1264        int mallopt( int option, int value ) {
    12751265          if ( value < 0 ) return 0;
    12761266                choose( option ) {
     
    12861276
    12871277        // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument).
    1288         int malloc_trim( size_t ) libcfa_public {
     1278        int malloc_trim( size_t ) {
    12891279                return 0;                                                                               // => impossible to release memory
    12901280        } // malloc_trim
     
    12951285        // structure dynamically allocated via malloc, and a pointer to that data structure is returned as the function
    12961286        // result.  (The caller must free this memory.)
    1297         void * malloc_get_state( void ) libcfa_public {
     1287        void * malloc_get_state( void ) {
    12981288                return 0p;                                                                              // unsupported
    12991289        } // malloc_get_state
     
    13021292        // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data
    13031293        // structure pointed to by state.
    1304         int malloc_set_state( void * ) libcfa_public {
     1294        int malloc_set_state( void * ) {
    13051295                return 0;                                                                               // unsupported
    13061296        } // malloc_set_state
     
    13081298
    13091299        // Sets the amount (bytes) to extend the heap when there is insufficent free storage to service an allocation.
    1310         __attribute__((weak)) size_t malloc_expansion() libcfa_public { return __CFA_DEFAULT_HEAP_EXPANSION__; }
     1300        __attribute__((weak)) size_t malloc_expansion() { return __CFA_DEFAULT_HEAP_EXPANSION__; }
    13111301
    13121302        // Sets the crossover point between allocations occuring in the sbrk area or separately mmapped.
    1313         __attribute__((weak)) size_t malloc_mmap_start() libcfa_public { return __CFA_DEFAULT_MMAP_START__; }
     1303        __attribute__((weak)) size_t malloc_mmap_start() { return __CFA_DEFAULT_MMAP_START__; }
    13141304
    13151305        // Amount subtracted to adjust for unfreed program storage (debug only).
    1316         __attribute__((weak)) size_t malloc_unfreed() libcfa_public { return __CFA_DEFAULT_HEAP_UNFREED__; }
     1306        __attribute__((weak)) size_t malloc_unfreed() { return __CFA_DEFAULT_HEAP_UNFREED__; }
    13171307} // extern "C"
    13181308
    13191309
    13201310// Must have CFA linkage to overload with C linkage realloc.
    1321 void * resize( void * oaddr, size_t nalign, size_t size ) libcfa_public {
     1311void * resize( void * oaddr, size_t nalign, size_t size ) {
    13221312        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    13231313  if ( unlikely( size == 0 ) ) {                                                // special cases
     
    13811371
    13821372
    1383 void * realloc( void * oaddr, size_t nalign, size_t size ) libcfa_public {
     1373void * realloc( void * oaddr, size_t nalign, size_t size ) {
    13841374        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    13851375  if ( unlikely( size == 0 ) ) {                                                // special cases
  • libcfa/src/interpose.cfa

    r74ec742 r29d8c02  
    3636//=============================================================================================
    3737
    38 static void preload_libgcc(void) {
     38void preload_libgcc(void) {
    3939        dlopen( "libgcc_s.so.1", RTLD_NOW );
    4040        if ( const char * error = dlerror() ) abort( "interpose_symbol : internal error pre-loading libgcc, %s\n", error );
     
    4242
    4343typedef void (* generic_fptr_t)(void);
    44 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
     44generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    4545        const char * error;
    4646
     
    8383//=============================================================================================
    8484
    85 static void sigHandler_segv( __CFA_SIGPARMS__ );
    86 static void sigHandler_ill ( __CFA_SIGPARMS__ );
    87 static void sigHandler_fpe ( __CFA_SIGPARMS__ );
    88 static void sigHandler_abrt( __CFA_SIGPARMS__ );
    89 static void sigHandler_term( __CFA_SIGPARMS__ );
    90 
    91 static struct {
     85void sigHandler_segv( __CFA_SIGPARMS__ );
     86void sigHandler_ill ( __CFA_SIGPARMS__ );
     87void sigHandler_fpe ( __CFA_SIGPARMS__ );
     88void sigHandler_abrt( __CFA_SIGPARMS__ );
     89void sigHandler_term( __CFA_SIGPARMS__ );
     90
     91struct {
    9292        void (* exit)( int ) __attribute__(( __noreturn__ ));
    9393        void (* abort)( void ) __attribute__(( __noreturn__ ));
    9494} __cabi_libc;
    9595
    96 libcfa_public int cfa_main_returned;
     96int cfa_main_returned;
    9797
    9898extern "C" {
     
    148148
    149149// Forward declare abort after the __typeof__ call to avoid ambiguities
    150 libcfa_public void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    151 libcfa_public void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
    152 libcfa_public void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    153 libcfa_public void __abort( bool signalAbort, const char fmt[], va_list args ) __attribute__(( __nothrow__, __leaf__, __noreturn__ ));
     150void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
     151void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     152void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
     153void __abort( bool signalAbort, const char fmt[], va_list args ) __attribute__(( __nothrow__, __leaf__, __noreturn__ ));
    154154
    155155extern "C" {
    156         libcfa_public void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
     156        void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    157157                abort( false, "%s", "" );
    158158        }
    159159
    160         libcfa_public void __cabi_abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
     160        void __cabi_abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
    161161                va_list argp;
    162162                va_start( argp, fmt );
     
    165165        }
    166166
    167         libcfa_public void exit( int status ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
     167        void exit( int status ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    168168                __cabi_libc.exit( status );
    169169        }
  • libcfa/src/iostream.cfa

    r74ec742 r29d8c02  
    3232#include "bitmanip.hfa"                                                                 // high1
    3333
    34 #pragma GCC visibility push(default)
    3534
    3635// *********************************** ostream ***********************************
  • libcfa/src/limits.cfa

    r74ec742 r29d8c02  
    2020#include <complex.h>
    2121#include "limits.hfa"
    22 
    23 #pragma GCC visibility push(default)
    2422
    2523// Integral Constants
  • libcfa/src/memory.cfa

    r74ec742 r29d8c02  
    1616#include "memory.hfa"
    1717#include "stdlib.hfa"
    18 
    19 #pragma GCC visibility push(default)
    2018
    2119// Internal data object.
  • libcfa/src/parseargs.cfa

    r74ec742 r29d8c02  
    2424#include "common.hfa"
    2525#include "limits.hfa"
    26 
    27 #pragma GCC visibility push(default)
    2826
    2927extern int cfa_args_argc __attribute__((weak));
     
    210208        }
    211209
    212         if(strcmp(arg, "Y") == 0) {
    213                 value = true;
    214                 return true;
    215         }
    216 
    217         if(strcmp(arg, "y") == 0) {
    218                 value = true;
    219                 return true;
    220         }
    221 
    222210        if(strcmp(arg, "no") == 0) {
    223                 value = false;
    224                 return true;
    225         }
    226 
    227         if(strcmp(arg, "N") == 0) {
    228                 value = false;
    229                 return true;
    230         }
    231 
    232         if(strcmp(arg, "n") == 0) {
    233211                value = false;
    234212                return true;
  • libcfa/src/parseconfig.cfa

    r74ec742 r29d8c02  
    1414
    1515
    16 #pragma GCC visibility push(default)
    17 
    1816// *********************************** exceptions ***********************************
    1917
    2018
    2119// TODO: Add names of missing config entries to exception (see further below)
    22 vtable(Missing_Config_Entries) Missing_Config_Entries_vt;
     20static vtable(Missing_Config_Entries) Missing_Config_Entries_vt;
    2321
    2422[ void ] ?{}( & Missing_Config_Entries this, unsigned int num_missing ) {
     
    3331
    3432
    35 vtable(Parse_Failure) Parse_Failure_vt;
     33static vtable(Parse_Failure) Parse_Failure_vt;
    3634
    3735[ void ] ?{}( & Parse_Failure this, [] char failed_key, [] char failed_value ) {
     
    5553
    5654
    57 vtable(Validation_Failure) Validation_Failure_vt;
     55static vtable(Validation_Failure) Validation_Failure_vt;
    5856
    5957[ void ] ?{}( & Validation_Failure this, [] char failed_key, [] char failed_value ) {
     
    112110
    113111
    114 static [ bool ] comments( & ifstream in, [] char name ) {
     112[ bool ] comments( & ifstream in, [] char name ) {
    115113        while () {
    116114                in | name;
  • libcfa/src/rational.cfa

    r74ec742 r29d8c02  
    1717#include "fstream.hfa"
    1818#include "stdlib.hfa"
    19 
    20 #pragma GCC visibility push(default)
    2119
    2220forall( T | Arithmetic( T ) ) {
  • libcfa/src/startup.cfa

    r74ec742 r29d8c02  
    4141        } // __cfaabi_appready_shutdown
    4242
    43         void disable_interrupts() __attribute__(( weak )) libcfa_public {}
    44         void enable_interrupts() __attribute__(( weak )) libcfa_public {}
     43        void disable_interrupts() __attribute__(( weak )) {}
     44        void enable_interrupts() __attribute__(( weak )) {}
    4545
    4646
     
    6464struct __spinlock_t;
    6565extern "C" {
    66         void __cfaabi_dbg_record_lock(struct __spinlock_t & this, const char prev_name[]) __attribute__(( weak )) libcfa_public {}
     66        void __cfaabi_dbg_record_lock(struct __spinlock_t & this, const char prev_name[]) __attribute__(( weak )) {}
    6767}
    6868
  • libcfa/src/stdlib.cfa

    r74ec742 r29d8c02  
    2525#include <complex.h>                                                                    // _Complex_I
    2626#include <assert.h>
    27 
    28 #pragma GCC visibility push(default)
    2927
    3028//---------------------------------------
     
    227225#define GENERATOR LCG
    228226
    229 // would be cool to make hidden but it's needed for libcfathread
    230 __attribute__((visibility("default"))) uint32_t __global_random_seed;                                                   // sequential/concurrent
    231 __attribute__((visibility("hidden"))) uint32_t __global_random_state;                                                   // sequential only
     227uint32_t __global_random_seed;                                                  // sequential/concurrent
     228uint32_t __global_random_state;                                                 // sequential only
    232229
    233230void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; GENERATOR( state ); } // set seed
  • libcfa/src/strstream.cfa

    r74ec742 r29d8c02  
    1 //
     1// 
    22// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
    3 //
     3// 
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // strstream.cfa --
    8 //
     7// strstream.cfa -- 
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Thu Apr 22 22:24:35 2021
     
    1212// Last Modified On : Sun Oct 10 16:13:20 2021
    1313// Update Count     : 101
    14 //
     14// 
    1515
    1616#include "strstream.hfa"
     
    2424#include <unistd.h>                                                                             // sbrk, sysconf
    2525
    26 #pragma GCC visibility push(default)
    2726
    2827// *********************************** strstream ***********************************
  • libcfa/src/time.cfa

    r74ec742 r29d8c02  
    1818#include <stdio.h>                                                                              // snprintf
    1919#include <assert.h>
    20 
    21 #pragma GCC visibility push(default)
    2220
    2321static char * nanomsd( long int ns, char * buf ) {              // most significant digits
  • libcfa/src/virtual.c

    r74ec742 r29d8c02  
    1616#include "virtual.h"
    1717#include "assert.h"
    18 
    19 #pragma GCC visibility push(default)
    2018
    2119int __cfavir_is_parent(
  • src/AST/Convert.cpp

    r74ec742 r29d8c02  
    9393        };
    9494
    95         template<typename T>
    96         Getter<T> get() {
    97                 return Getter<T>{ *this };
    98         }
     95    template<typename T>
     96    Getter<T> get() {
     97        return Getter<T>{ *this };
     98    }
    9999
    100100        Label makeLabel(Statement * labelled, const ast::Label& label) {
     
    16511651                        // GET_ACCEPT_1(type, FunctionType),
    16521652                        std::move(forall),
    1653                         std::move(assertions),
    16541653                        std::move(paramVars),
    16551654                        std::move(returnVars),
     
    16651664                cache.emplace( old, decl );
    16661665
     1666                decl->assertions = std::move(assertions);
    16671667                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    16681668                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    17301730        }
    17311731
    1732 
     1732        // Convert SynTree::EnumDecl to AST::EnumDecl
    17331733        virtual void visit( const EnumDecl * old ) override final {
    17341734                if ( inCache( old ) ) return;
     
    27292729                        ty->forall.emplace_back(new ast::TypeInstType(param));
    27302730                        for (auto asst : param->assertions) {
    2731                                 ty->assertions.emplace_back(
    2732                                         new ast::VariableExpr(param->location, asst));
     2731                                ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
    27332732                        }
    27342733                }
  • src/AST/Copy.cpp

    r74ec742 r29d8c02  
    1010// Created On       : Thr Nov 11  9:16:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May  3 16:28:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Thr Nov 11  9:28:00 2021
     13// Update Count     : 0
    1414//
    1515
     
    7777        }
    7878
    79         void postvisit( const UniqueExpr * node ) {
    80                 readonlyInsert( &node->object );
    81         }
    82 
    8379        void postvisit( const MemberExpr * node ) {
    8480                readonlyInsert( &node->member );
  • src/AST/Decl.cpp

    r74ec742 r29d8c02  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu May  5 12:10:00 2022
    13 // Update Count     : 24
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Jan 12 16:54:55 2021
     13// Update Count     : 23
    1414//
    1515
     
    5353// --- FunctionDecl
    5454
    55 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
     55FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 
    5656        std::vector<ptr<TypeDecl>>&& forall,
    5757        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     
    7474        }
    7575        this->type = ftype;
    76 }
    77 
    78 FunctionDecl::FunctionDecl( const CodeLocation & location, const std::string & name,
    79         std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
    80         std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    81         CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    82         std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
    83 : DeclWithType( location, name, storage, linkage, std::move(attrs), fs ),
    84                 params( std::move(params) ), returns( std::move(returns) ),
    85                 type_params( std::move( forall) ), assertions( std::move( assertions ) ),
    86                 type( nullptr ), stmts( stmts ) {
    87         FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );
    88         for ( auto & param : this->params ) {
    89                 type->params.emplace_back( param->get_type() );
    90         }
    91         for ( auto & ret : this->returns ) {
    92                 type->returns.emplace_back( ret->get_type() );
    93         }
    94         for ( auto & param : this->type_params ) {
    95                 type->forall.emplace_back( new TypeInstType( param ) );
    96         }
    97         for ( auto & assertion : this->assertions ) {
    98                 type->assertions.emplace_back(
    99                         new VariableExpr( assertion->location, assertion ) );
    100         }
    101         this->type = type;
    10276}
    10377
  • src/AST/Decl.hpp

    r74ec742 r29d8c02  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu May  5 12:09:00 2022
    13 // Update Count     : 33
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Mar 12 18:25:05 2021
     13// Update Count     : 32
    1414//
    1515
     
    135135        std::vector< ptr<Expr> > withExprs;
    136136
    137         // The difference between the two constructors is in how they handle
    138         // assertions. The first constructor uses the assertions from the type
    139         // parameters, in the style of the old ast, and puts them on the type.
    140         // The second takes an explicite list of assertions and builds a list of
    141         // references to them on the type.
    142 
    143137        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
    144138                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    145139                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    146140                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
    147 
    148         FunctionDecl( const CodeLocation & location, const std::string & name,
    149                 std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
    150                 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    151                 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    152                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
     141        // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     142        //  stmts( stmts ) {}
    153143
    154144        const Type * get_type() const override;
  • src/AST/Expr.cpp

    r74ec742 r29d8c02  
    1010// Created On       : Wed May 15 17:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Created On       : Wed May 18 13:56:00 2022
    13 // Update Count     : 8
     12// Created On       : Tue Nov 30 14:23:00 2021
     13// Update Count     : 7
    1414//
    1515
     
    2121
    2222#include "Copy.hpp"                // for shallowCopy
     23#include "Eval.hpp"                // for call
    2324#include "GenericSubstitution.hpp"
    2425#include "LinkageSpec.hpp"
     
    6667// --- UntypedExpr
    6768
    68 bool UntypedExpr::get_lvalue() const {
    69         std::string fname = InitTweak::getFunctionName( this );
    70         return lvalueFunctionNames.count( fname );
    71 }
    72 
    7369UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
    7470        assert( arg );
    7571
    76         UntypedExpr * ret = createCall( loc, "*?", { arg } );
     72        UntypedExpr * ret = call( loc, "*?", arg );
    7773        if ( const Type * ty = arg->result ) {
    7874                const Type * base = InitTweak::getPointerBase( ty );
     
    9187}
    9288
     89bool UntypedExpr::get_lvalue() const {
     90        std::string fname = InitTweak::getFunctionName( this );
     91        return lvalueFunctionNames.count( fname );
     92}
     93
    9394UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
    9495        assert( lhs && rhs );
    9596
    96         UntypedExpr * ret = createCall( loc, "?=?", { lhs, rhs } );
     97        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    9798        if ( lhs->result && rhs->result ) {
    9899                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    101102        }
    102103        return ret;
    103 }
    104 
    105 UntypedExpr * UntypedExpr::createCall( const CodeLocation & loc,
    106                 const std::string & name, std::vector<ptr<Expr>> && args ) {
    107         return new UntypedExpr( loc,
    108                         new NameExpr( loc, name ), std::move( args ) );
    109104}
    110105
  • src/AST/Expr.hpp

    r74ec742 r29d8c02  
    230230        /// Creates a new assignment expression
    231231        static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
    232         /// Creates a new call of a variable.
    233         static UntypedExpr * createCall( const CodeLocation & loc,
    234                 const std::string & name, std::vector<ptr<Expr>> && args );
    235232
    236233        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    787784public:
    788785        ptr<Expr> expr;
    789         readonly<ObjectDecl> object;
     786        ptr<ObjectDecl> object;
    790787        ptr<VariableExpr> var;
    791788        unsigned long long id;
  • src/AST/Label.hpp

    r74ec742 r29d8c02  
    3434        std::vector< ptr<Attribute> > attributes;
    3535
    36         Label( const CodeLocation& loc, const std::string& name = "",
     36        Label( CodeLocation loc, const std::string& name = "",
    3737                std::vector<ptr<Attribute>> && attrs = std::vector<ptr<Attribute>>{} )
    3838        : location( loc ), name( name ), attributes( attrs ) {}
  • src/AST/Node.hpp

    r74ec742 r29d8c02  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon May  9 10:20:00 2022
    13 // Update Count     : 8
     12// Last Modified On : Fri Mar 25 10:33:00 2022
     13// Update Count     : 7
    1414//
    1515
     
    4949
    5050        bool unique() const { return strong_count == 1; }
    51         bool isManaged() const { return strong_count > 0; }
    52         bool isReferenced() const { return weak_count > 0; }
    53         bool isStable() const {
    54                 return (1 == strong_count || (1 < strong_count && 0 == weak_count));
    55         }
     51        bool isManaged() const {return strong_count > 0; }
    5652
    5753private:
  • src/AST/Pass.proto.hpp

    r74ec742 r29d8c02  
    131131        template< typename node_t >
    132132        struct result1 {
    133                 bool differs = false;
    134                 const node_t * value = nullptr;
     133                bool differs;
     134                const node_t * value;
    135135
    136136                template< typename object_t, typename super_t, typename field_t >
     
    151151                };
    152152
    153                 bool differs = false;
     153                bool differs;
    154154                container_t< delta > values;
    155155
     
    167167        template< template<class...> class container_t, typename node_t >
    168168        struct resultN {
    169                 bool differs = false;
     169                bool differs;
    170170                container_t<ptr<node_t>> values;
    171171
  • src/AST/Stmt.cpp

    r74ec742 r29d8c02  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May  3 15:18:20 2022
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 19:01:20 2022
     13// Update Count     : 3
    1414//
    1515
    1616#include "Stmt.hpp"
    1717
    18 #include "Copy.hpp"
     18
    1919#include "DeclReplacer.hpp"
    2020#include "Type.hpp"
     
    2323
    2424// --- CompoundStmt
    25 CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids() {
    26         // Statements can have weak references to them, if that happens inserting
    27         // the original node into the new list will put the original node in a
    28         // bad state, where it cannot be mutated. To avoid this, just perform an
    29         // additional shallow copy on the statement.
    30         for ( const Stmt * kid : other.kids ) {
    31                 if ( kid->isReferenced() ) {
    32                         kids.emplace_back( ast::shallowCopy( kid ) );
    33                 } else {
    34                         kids.emplace_back( kid );
    35                 }
    36         }
    37 
     25CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids(other.kids) {
    3826        // when cloning a compound statement, we may end up cloning declarations which
    3927        // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
  • src/AST/Stmt.hpp

    r74ec742 r29d8c02  
    5858        // cannot be, they are sub-types of this type, for organization.
    5959
    60         StmtClause( const CodeLocation & loc )
     60    StmtClause( const CodeLocation & loc )
    6161                : ParseNode(loc) {}
    6262
     
    396396class WaitForClause final : public StmtClause {
    397397  public:
    398         ptr<Expr> target_func;
    399         std::vector<ptr<Expr>> target_args;
    400         ptr<Stmt> stmt;
    401         ptr<Expr> cond;
    402 
    403         WaitForClause( const CodeLocation & loc )
     398    ptr<Expr> target_func;
     399    std::vector<ptr<Expr>> target_args;
     400    ptr<Stmt> stmt;
     401    ptr<Expr> cond;
     402
     403    WaitForClause( const CodeLocation & loc )
    404404                : StmtClause( loc ) {}
    405405
    406406        const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
    407407  private:
    408         WaitForClause * clone() const override { return new WaitForClause{ *this }; }
    409         MUTATE_FRIEND
     408    WaitForClause * clone() const override { return new WaitForClause{ *this }; }
     409    MUTATE_FRIEND
    410410};
    411411
  • src/AST/Util.cpp

    r74ec742 r29d8c02  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Util.cpp -- General utilities for working with the AST.
     7// Util.hpp -- General utilities for working with the AST.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Wed Jan 19  9:46:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 11 16:16:00 2022
    13 // Update Count     : 3
     12// Last Modified On : Fri Mar 11 18:07:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    4646
    4747/// Check that every note that can has a set CodeLocation.
    48 void isCodeLocationSet( const ParseNode * node ) {
    49         assert( node->location.isSet() );
    50 }
    51 
    52 void areLabelLocationsSet( const Stmt * stmt ) {
    53         for ( const Label& label : stmt->labels ) {
    54                 assert( label.location.isSet() );
     48struct SetCodeLocationsCore {
     49        void previsit( const ParseNode * node ) {
     50                assert( node->location.isSet() );
    5551        }
    56 }
    57 
    58 /// Make sure the reference counts are in a valid combination.
    59 void isStable( const Node * node ) {
    60         assert( node->isStable() );
    61 }
    62 
    63 /// Check that a FunctionDecl is synchronized with it's FunctionType.
    64 void functionDeclMatchesType( const FunctionDecl * decl ) {
    65         // The type is a cache of sorts, if it is missing that is only a
    66         // problem if isTypeFixed is set.
    67         if ( decl->isTypeFixed ) {
    68                 assert( decl->type );
    69         } else if ( !decl->type ) {
    70                 return;
    71         }
    72 
    73         const FunctionType * type = decl->type;
    74 
    75         // Check that `type->forall` corresponds with `decl->type_params`.
    76         assert( type->forall.size() == decl->type_params.size() );
    77         // Check that `type->assertions` corresponds with `decl->assertions`.
    78         assert( type->assertions.size() == decl->assertions.size() );
    79         // Check that `type->params` corresponds with `decl->params`.
    80         assert( type->params.size() == decl->params.size() );
    81         // Check that `type->returns` corresponds with `decl->returns`.
    82         assert( type->returns.size() == decl->returns.size() );
    83 }
     52};
    8453
    8554struct InvariantCore {
     
    8756        // None of the passes should make changes so ordering doesn't matter.
    8857        NoStrongCyclesCore no_strong_cycles;
     58        SetCodeLocationsCore set_code_locations;
    8959
    9060        void previsit( const Node * node ) {
    9161                no_strong_cycles.previsit( node );
    92                 isStable( node );
    9362        }
    9463
    9564        void previsit( const ParseNode * node ) {
    96                 previsit( (const Node *)node );
    97                 isCodeLocationSet( node );
    98         }
    99 
    100         void previsit( const FunctionDecl * node ) {
    101                 previsit( (const ParseNode *)node );
    102                 functionDeclMatchesType( node );
    103         }
    104 
    105         void previsit( const Stmt * node ) {
    106                 previsit( (const ParseNode *)node );
    107                 areLabelLocationsSet( node );
     65                no_strong_cycles.previsit( node );
     66                set_code_locations.previsit( node );
    10867        }
    10968
  • src/AST/module.mk

    r74ec742 r29d8c02  
    2929        AST/DeclReplacer.cpp \
    3030        AST/DeclReplacer.hpp \
     31        AST/Eval.hpp \
    3132        AST/Expr.cpp \
    3233        AST/Expr.hpp \
  • src/CodeGen/CodeGenerator.cc

    r74ec742 r29d8c02  
    12381238} // namespace CodeGen
    12391239
     1240
     1241unsigned Indenter::tabsize = 2;
     1242
     1243std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ) {
     1244        if ( node ) {
     1245                node->print( out );
     1246        } else {
     1247                out << "nullptr";
     1248        }
     1249        return out;
     1250}
     1251
    12401252// Local Variables: //
    12411253// tab-width: 4 //
  • src/CodeGen/FixMain.cc

    r74ec742 r29d8c02  
    4949
    5050}
     51
     52        bool FixMain::replace_main = false;
    5153
    5254        template<typename container>
  • src/CodeGen/LinkOnce.cc

    r74ec742 r29d8c02  
    5353                                new ConstantExpr( Constant::from_string( section_name ) )
    5454                        );
    55 
    56                         // Unconditionnaly add "visibility(default)" to anything with gnu.linkonce
    57                         // visibility is a mess otherwise
    58                         attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));
    59 
    6055                }
    6156                visit_children = false;
  • src/CodeGen/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:26:00 2022
    14 ## Update Count     : 5
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat Dec 14 07:29:42 2019
     14## Update Count     : 4
    1515###############################################################################
    1616
     17#SRC +=  ArgTweak/Rewriter.cc \
     18#       ArgTweak/Mutate.cc
     19
    1720SRC_CODEGEN = \
    18         CodeGen/FixMain2.cc \
    19         CodeGen/FixMain.h \
    20         CodeGen/OperatorTable.cc \
    21         CodeGen/OperatorTable.h
    22 
    23 SRC += $(SRC_CODEGEN) \
    2421        CodeGen/CodeGenerator.cc \
    2522        CodeGen/CodeGenerator.h \
    26         CodeGen/Generate.cc \
    27         CodeGen/Generate.h \
    2823        CodeGen/FixMain.cc \
    29         CodeGen/FixNames.cc \
    30         CodeGen/FixNames.h \
     24        CodeGen/FixMain.h \
    3125        CodeGen/GenType.cc \
    3226        CodeGen/GenType.h \
    3327        CodeGen/LinkOnce.cc \
    3428        CodeGen/LinkOnce.h \
     29        CodeGen/OperatorTable.cc \
     30        CodeGen/OperatorTable.h \
    3531        CodeGen/Options.h
    3632
     33SRC += $(SRC_CODEGEN) CodeGen/Generate.cc CodeGen/Generate.h CodeGen/FixNames.cc CodeGen/FixNames.h
    3734SRCDEMANGLE += $(SRC_CODEGEN)
  • src/Common/CodeLocationTools.cpp

    r74ec742 r29d8c02  
    1010// Created On       : Fri Dec  4 15:42:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 11 16:16:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2424namespace {
    2525
     26// There are a lot of helpers in this file that could be used much more
     27// generally if anyone has another use for them.
     28
     29// Check if a node type has a code location.
     30template<typename node_t>
     31struct has_code_location : public std::is_base_of<ast::ParseNode, node_t> {};
     32
     33template<typename node_t, bool has_location>
     34struct __GetCL;
     35
     36template<typename node_t>
     37struct __GetCL<node_t, true> {
     38        static inline CodeLocation const * get( node_t const * node ) {
     39                return &node->location;
     40        }
     41
     42        static inline CodeLocation * get( node_t * node ) {
     43                return &node->location;
     44        }
     45};
     46
     47template<typename node_t>
     48struct __GetCL<node_t, false> {
     49        static inline CodeLocation * get( node_t const * ) {
     50                return nullptr;
     51        }
     52};
     53
     54template<typename node_t>
     55CodeLocation const * get_code_location( node_t const * node ) {
     56        return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
     57}
     58
     59template<typename node_t>
     60CodeLocation * get_code_location( node_t * node ) {
     61        return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
     62}
     63
    2664// Fill every location with a nearby (parent) location.
    2765class FillCore : public ast::WithGuards {
    2866        CodeLocation const * parent;
     67public:
     68        FillCore() : parent( nullptr ) {}
    2969
    3070        template<typename node_t>
    31         node_t const * parse_visit( node_t const * node ) {
    32                 if ( node->location.isUnset() ) {
     71        node_t const * previsit( node_t const * node ) {
     72                GuardValue( parent );
     73                CodeLocation const * location = get_code_location( node );
     74                if ( location && location->isUnset() ) {
    3375                        assert( parent );
    3476                        node_t * newNode = ast::mutate( node );
    35                         newNode->location = *parent;
     77                        CodeLocation * newLocation = get_code_location( newNode );
     78                        assert( newLocation );
     79                        *newLocation = *parent;
     80                        parent = newLocation;
    3681                        return newNode;
    37                 }
    38                 GuardValue( parent ) = &node->location;
     82                } else if ( location ) {
     83                        parent = location;
     84                }
    3985                return node;
    40         }
    41 
    42         bool hasUnsetLabels( const ast::Stmt * stmt ) {
    43                 for ( const ast::Label& label : stmt->labels ) {
    44                         if ( label.location.isUnset() ) {
    45                                 return true;
    46                         }
    47                 }
    48                 return false;
    49         }
    50 
    51         template<typename node_t>
    52         node_t const * stmt_visit( node_t const * node ) {
    53                 assert( node->location.isSet() );
    54 
    55                 if ( hasUnsetLabels( node ) ) {
    56                         node_t * newNode = ast::mutate( node );
    57                         for ( ast::Label& label : newNode->labels ) {
    58                                 if ( label.location.isUnset() ) {
    59                                         label.location = newNode->location;
    60                                 }
    61                         }
    62                         return newNode;
    63                 }
    64                 return node;
    65         }
    66 
    67         template<typename node_t>
    68         auto visit( node_t const * node, long ) {
    69                 return node;
    70         }
    71 
    72         template<typename node_t>
    73         auto visit( node_t const * node, int ) -> typename
    74                         std::remove_reference< decltype( node->location, node ) >::type {
    75                 return parse_visit( node );
    76         }
    77 
    78         template<typename node_t>
    79         auto visit( node_t const * node, char ) -> typename
    80                         std::remove_reference< decltype( node->labels, node ) >::type {
    81                 return stmt_visit( parse_visit( node ) );
    82         }
    83 
    84 public:
    85         FillCore() : parent( nullptr ) {}
    86         FillCore( const CodeLocation& location ) : parent( &location ) {
    87                 assert( location.isSet() );
    88         }
    89 
    90         template<typename node_t>
    91         node_t const * previsit( node_t const * node ) {
    92                 return visit( node, '\0' );
    9386        }
    9487};
     
    240233
    241234        template<typename node_t>
    242         auto previsit( node_t const * node ) -> decltype( node->location, void() ) {
    243                 if ( node->location.isUnset() ) {
     235        void previsit( node_t const * node ) {
     236                CodeLocation const * location = get_code_location( node );
     237                if ( location && location->isUnset() ) {
    244238                        unset.push_back( node );
     239                }
     240        }
     241};
     242
     243class LocalFillCore : public ast::WithGuards {
     244        CodeLocation const * parent;
     245public:
     246        LocalFillCore( CodeLocation const & location ) : parent( &location ) {
     247                assert( location.isSet() );
     248        }
     249
     250        template<typename node_t>
     251        auto previsit( node_t const * node )
     252                        -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {
     253                if ( node->location.isSet() ) {
     254                        GuardValue( parent ) = &node->location;
     255                        return node;
     256                } else {
     257                        node_t * mut = ast::mutate( node );
     258                        mut->location = *parent;
     259                        return mut;
    245260                }
    246261        }
     
    289304ast::Node const * localFillCodeLocations(
    290305                CodeLocation const & location , ast::Node const * node ) {
    291         ast::Pass<FillCore> visitor( location );
     306        ast::Pass<LocalFillCore> visitor( location );
    292307        return node->accept( visitor );
    293308}
  • src/Common/Indenter.h

    r74ec742 r29d8c02  
    1010// Created On       : Fri Jun 30 16:55:23 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri May 13 14:10:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Fri Aug 11 11:15:00 2017
     13// Update Count     : 1
    1414//
    1515
    16 #pragma once
    17 
    18 #include <ostream>
     16#ifndef INDENTER_H
     17#define INDENTER_H
    1918
    2019struct Indenter {
     
    3837        return out << std::string(indent.indent * indent.amt, ' ');
    3938}
     39
     40#endif // INDENTER_H
  • src/Common/SemanticError.h

    r74ec742 r29d8c02  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  4 14:08:26 2022
    13 // Update Count     : 35
     12// Last Modified On : Thu Jul 19 10:09:17 2018
     13// Update Count     : 31
    1414//
    1515
     
    5959        {"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    6060        {"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
    61         {"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
    6261        {"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
    6362        {"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     
    7069        AggrForwardDecl,
    7170        SuperfluousDecl,
    72         SuperfluousElse,
    7371        GccAttributes,
    7472        CppCopy,
     
    8179);
    8280
    83 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, ##__VA_ARGS__)
     81#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, __VA_ARGS__)
    8482
    8583void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
  • src/Common/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:27:00 2022
    14 ## Update Count     : 5
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Tue Sep 27 11:06:38 2016
     14## Update Count     : 4
    1515###############################################################################
    1616
    1717SRC_COMMON = \
    18         Common/Assert.cc \
    19         Common/CodeLocation.h \
    20         Common/CodeLocationTools.hpp \
    21         Common/CodeLocationTools.cpp \
    22         Common/CompilerError.h \
    23         Common/Debug.h \
    24         Common/DeclStats.hpp \
    25         Common/DeclStats.cpp \
    26         Common/ErrorObjects.h \
    27         Common/Eval.cc \
    28         Common/Examine.cc \
    29         Common/Examine.h \
    30         Common/FilterCombos.h \
    31         Common/Indenter.h \
    32         Common/Indenter.cc \
    33         Common/PassVisitor.cc \
    34         Common/PassVisitor.h \
    35         Common/PassVisitor.impl.h \
    36         Common/PassVisitor.proto.h \
    37         Common/PersistentMap.h \
    38         Common/ResolvProtoDump.hpp \
    39         Common/ResolvProtoDump.cpp \
    40         Common/ScopedMap.h \
    41         Common/SemanticError.cc \
    42         Common/SemanticError.h \
    43         Common/Stats.h \
    44         Common/Stats/Base.h \
    45         Common/Stats/Counter.cc \
    46         Common/Stats/Counter.h \
    47         Common/Stats/Heap.cc \
    48         Common/Stats/Heap.h \
    49         Common/Stats/ResolveTime.cc \
    50         Common/Stats/ResolveTime.h \
    51         Common/Stats/Stats.cc \
    52         Common/Stats/Time.cc \
    53         Common/Stats/Time.h \
    54         Common/UnimplementedError.h \
    55         Common/UniqueName.cc \
    56         Common/UniqueName.h \
    57         Common/utility.h \
    58         Common/VectorMap.h
     18      Common/Assert.cc \
     19      Common/CodeLocation.h \
     20      Common/CodeLocationTools.hpp \
     21      Common/CodeLocationTools.cpp \
     22      Common/CompilerError.h \
     23      Common/Debug.h \
     24      Common/DeclStats.hpp \
     25      Common/DeclStats.cpp \
     26      Common/ErrorObjects.h \
     27      Common/Eval.cc \
     28      Common/Examine.cc \
     29      Common/Examine.h \
     30      Common/FilterCombos.h \
     31      Common/Indenter.h \
     32      Common/PassVisitor.cc \
     33      Common/PassVisitor.h \
     34      Common/PassVisitor.impl.h \
     35      Common/PassVisitor.proto.h \
     36      Common/PersistentMap.h \
     37      Common/ResolvProtoDump.hpp \
     38      Common/ResolvProtoDump.cpp \
     39      Common/ScopedMap.h \
     40      Common/SemanticError.cc \
     41      Common/SemanticError.h \
     42      Common/Stats.h \
     43      Common/Stats/Base.h \
     44      Common/Stats/Counter.cc \
     45      Common/Stats/Counter.h \
     46      Common/Stats/Heap.cc \
     47      Common/Stats/Heap.h \
     48      Common/Stats/ResolveTime.cc \
     49      Common/Stats/ResolveTime.h \
     50      Common/Stats/Stats.cc \
     51      Common/Stats/Time.cc \
     52      Common/Stats/Time.h \
     53      Common/UnimplementedError.h \
     54      Common/UniqueName.cc \
     55      Common/UniqueName.h \
     56      Common/utility.h \
     57      Common/VectorMap.h
    5958
    60 SRC += $(SRC_COMMON) \
    61         Common/DebugMalloc.cc
    62 
     59SRC += $(SRC_COMMON) Common/DebugMalloc.cc
    6360SRCDEMANGLE += $(SRC_COMMON)
  • src/Common/utility.h

    r74ec742 r29d8c02  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Apr 25 14:26:00 2022
    13 // Update Count     : 51
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Feb 11 13:00:36 2020
     13// Update Count     : 50
    1414//
    1515
     
    230230}
    231231
    232 template<typename Container, typename Pred>
    233 void erase_if( Container & cont, Pred && pred ) {
    234         auto keep_end = std::remove_if( cont.begin(), cont.end(), pred );
    235         cont.erase( keep_end, cont.end() );
    236 }
    237 
    238232template< typename... Args >
    239233auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
  • src/Concurrency/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Thierry Delisle
    1111## Created On       : Mon Mar 13 12:48:40 2017
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 13:28:00 2022
    14 ## Update Count     : 1
     12## Last Modified By :
     13## Last Modified On :
     14## Update Count     : 0
    1515###############################################################################
    1616
    17 SRC += \
     17SRC_CONCURRENCY = \
    1818        Concurrency/KeywordsNew.cpp \
    19         Concurrency/Keywords.cc \
     19        Concurrency/Keywords.cc
     20
     21SRC += $(SRC_CONCURRENCY) \
    2022        Concurrency/Keywords.h \
    2123        Concurrency/Waitfor.cc \
    2224        Concurrency/Waitfor.h
     25
     26SRCDEMANGLE += $(SRC_CONCURRENCY)
     27
  • src/ControlStruct/LabelGeneratorNew.hpp

    r74ec742 r29d8c02  
    1818#include <string>                                                                               // for string
    1919
    20 struct CodeLocation;
     20class CodeLocation;
    2121
    2222namespace ast {
  • src/ControlStruct/MultiLevelExit.cpp

    r74ec742 r29d8c02  
    1818#include "AST/Pass.hpp"
    1919#include "AST/Stmt.hpp"
    20 #include "Common/CodeLocationTools.hpp"
    2120#include "LabelGeneratorNew.hpp"
    2221
     
    229228        // Labels on different stmts require different approaches to access
    230229        switch ( stmt->kind ) {
    231         case BranchStmt::Goto:
     230          case BranchStmt::Goto:
    232231                return stmt;
    233         case BranchStmt::Continue:
    234         case BranchStmt::Break: {
    235                 bool isContinue = stmt->kind == BranchStmt::Continue;
    236                 // Handle unlabeled break and continue.
    237                 if ( stmt->target.empty() ) {
    238                         if ( isContinue ) {
    239                                 targetEntry = findEnclosingControlStructure( isContinueTarget );
    240                         } else {
    241                                 if ( enclosing_control_structures.empty() ) {
     232          case BranchStmt::Continue:
     233          case BranchStmt::Break: {
     234                  bool isContinue = stmt->kind == BranchStmt::Continue;
     235                  // Handle unlabeled break and continue.
     236                  if ( stmt->target.empty() ) {
     237                          if ( isContinue ) {
     238                                  targetEntry = findEnclosingControlStructure( isContinueTarget );
     239                          } else {
     240                                  if ( enclosing_control_structures.empty() ) {
    242241                                          SemanticError( stmt->location,
    243242                                                                         "'break' outside a loop, 'switch', or labelled block" );
    244                                 }
    245                                 targetEntry = findEnclosingControlStructure( isBreakTarget );
    246                         }
    247                         // Handle labeled break and continue.
    248                 } else {
    249                         // Lookup label in table to find attached control structure.
    250                         targetEntry = findEnclosingControlStructure(
    251                                 [ targetStmt = target_table.at(stmt->target) ](auto entry){
     243                                  }
     244                                  targetEntry = findEnclosingControlStructure( isBreakTarget );
     245                          }
     246                          // Handle labeled break and continue.
     247                  } else {
     248                          // Lookup label in table to find attached control structure.
     249                          targetEntry = findEnclosingControlStructure(
     250                                  [ targetStmt = target_table.at(stmt->target) ](auto entry){
    252251                                          return entry.stmt == targetStmt;
    253                                 } );
    254                 }
    255                 // Ensure that selected target is valid.
    256                 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
    257                         SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
     252                                  } );
     253                  }
     254                  // Ensure that selected target is valid.
     255                  if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
     256                          SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
    258257                                                        " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
    259258                                                        stmt->originalTarget ) );
    260                 }
    261                 break;
    262         }
    263         // handle fallthrough in case/switch stmts
    264         case BranchStmt::FallThrough: {
    265                 targetEntry = findEnclosingControlStructure( isFallthroughTarget );
    266                 // Check that target is valid.
    267                 if ( targetEntry == enclosing_control_structures.rend() ) {
    268                         SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    269                 }
    270                 if ( ! stmt->target.empty() ) {
    271                         // Labelled fallthrough: target must be a valid fallthough label.
    272                         if ( ! fallthrough_labels.count( stmt->target ) ) {
    273                                 SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
     259                  }
     260                  break;
     261          }
     262          // handle fallthrough in case/switch stmts
     263          case BranchStmt::FallThrough: {
     264                  targetEntry = findEnclosingControlStructure( isFallthroughTarget );
     265                  // Check that target is valid.
     266                  if ( targetEntry == enclosing_control_structures.rend() ) {
     267                          SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
     268                  }
     269                  if ( ! stmt->target.empty() ) {
     270                          // Labelled fallthrough: target must be a valid fallthough label.
     271                          if ( ! fallthrough_labels.count( stmt->target ) ) {
     272                                  SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
    274273                                                                                                                   stmt->originalTarget ) );
    275                         }
    276                         return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
    277                 }
    278                 break;
    279         }
    280         case BranchStmt::FallThroughDefault: {
    281                 targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
    282 
    283                 // Check if in switch or choose statement.
    284                 if ( targetEntry == enclosing_control_structures.rend() ) {
    285                         SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    286                 }
    287 
    288                 // Check if switch or choose has default clause.
    289                 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
    290                 bool foundDefault = false;
    291                 for ( auto caseStmt : switchStmt->cases ) {
    292                         if ( caseStmt->isDefault() ) {
    293                                 foundDefault = true;
    294                                 break;
    295                         }
    296                 }
    297                 if ( ! foundDefault ) {
    298                         SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
    299                                                   "control structure with a 'default' clause" );
    300                 }
    301                 break;
    302         }
    303         default:
     274                          }
     275                          return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
     276                  }
     277                  break;
     278          }
     279          case BranchStmt::FallThroughDefault: {
     280                  targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
     281
     282                  // Check if in switch or choose statement.
     283                  if ( targetEntry == enclosing_control_structures.rend() ) {
     284                          SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
     285                  }
     286
     287                  // Check if switch or choose has default clause.
     288                  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
     289                  bool foundDefault = false;
     290                  for ( auto caseStmt : switchStmt->cases ) {
     291                          if ( caseStmt->isDefault() ) {
     292                                  foundDefault = true;
     293                                  break;
     294                          }
     295                  }
     296                  if ( ! foundDefault ) {
     297                          SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
     298                                                        "control structure with a 'default' clause" );
     299                  }
     300                  break;
     301          }
     302          default:
    304303                assert( false );
    305304        }
     
    308307        Label exitLabel( CodeLocation(), "" );
    309308        switch ( stmt->kind ) {
    310         case BranchStmt::Break:
     309          case BranchStmt::Break:
    311310                assert( ! targetEntry->useBreakExit().empty() );
    312311                exitLabel = targetEntry->useBreakExit();
    313312                break;
    314         case BranchStmt::Continue:
     313          case BranchStmt::Continue:
    315314                assert( ! targetEntry->useContExit().empty() );
    316315                exitLabel = targetEntry->useContExit();
    317316                break;
    318         case BranchStmt::FallThrough:
     317          case BranchStmt::FallThrough:
    319318                assert( ! targetEntry->useFallExit().empty() );
    320319                exitLabel = targetEntry->useFallExit();
    321320                break;
    322         case BranchStmt::FallThroughDefault:
     321          case BranchStmt::FallThroughDefault:
    323322                assert( ! targetEntry->useFallDefaultExit().empty() );
    324323                exitLabel = targetEntry->useFallDefaultExit();
     
    328327                }
    329328                break;
    330         default:
     329          default:
    331330                assert(0);
    332331        }
     
    589588                }
    590589
    591                 ptr<Stmt> else_stmt = nullptr;
    592                 Stmt * loop_kid = nullptr;
    593                 // check if loop node and if so add else clause if it exists
    594                 const WhileDoStmt * whilePtr = dynamic_cast<const WhileDoStmt *>(kid.get());
    595                 if ( whilePtr && whilePtr->else_) {
    596                         else_stmt = whilePtr->else_;
    597                         WhileDoStmt * mutate_ptr = mutate(whilePtr);
    598                         mutate_ptr->else_ = nullptr;
    599                         loop_kid = mutate_ptr;
    600                 }
    601                 const ForStmt * forPtr = dynamic_cast<const ForStmt *>(kid.get());
    602                 if ( forPtr && forPtr->else_) {
    603                         else_stmt = forPtr->else_;
    604                         ForStmt * mutate_ptr = mutate(forPtr);
    605                         mutate_ptr->else_ = nullptr;
    606                         loop_kid = mutate_ptr;
    607                 }
    608 
    609590                try {
    610                         if (else_stmt) ret.push_back( loop_kid->accept( *visitor ) );
    611                         else ret.push_back( kid->accept( *visitor ) );
     591                        ret.push_back( kid->accept( *visitor ) );
    612592                } catch ( SemanticErrorException & e ) {
    613593                        errors.append( e );
    614594                }
    615 
    616                 if (else_stmt) ret.push_back(else_stmt);
    617595
    618596                if ( ! break_label.empty() ) {
     
    634612        Pass<MultiLevelExitCore> visitor( labelTable );
    635613        const CompoundStmt * ret = stmt->accept( visitor );
    636         // There are some unset code locations slipping in, possibly by Labels.
    637         const Node * node = localFillCodeLocations( ret->location, ret );
    638         return strict_dynamic_cast<const CompoundStmt *>( node );
     614        return ret;
    639615}
    640616} // namespace ControlStruct
  • src/ControlStruct/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:30:00 2022
    14 ## Update Count     : 8
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat Jan 29 12:04:19 2022
     14## Update Count     : 7
    1515###############################################################################
    1616
    17 SRC += \
     17SRC_CONTROLSTRUCT = \
    1818        ControlStruct/ExceptDecl.cc \
    1919        ControlStruct/ExceptDecl.h \
    20         ControlStruct/ExceptTranslateNew.cpp \
    21         ControlStruct/ExceptTranslate.cc \
    22         ControlStruct/ExceptTranslate.h \
    2320        ControlStruct/FixLabels.cpp \
    2421        ControlStruct/FixLabels.hpp \
     
    4037        ControlStruct/Mutate.h
    4138
     39SRC += $(SRC_CONTROLSTRUCT) \
     40        ControlStruct/ExceptTranslateNew.cpp \
     41        ControlStruct/ExceptTranslate.cc \
     42        ControlStruct/ExceptTranslate.h
     43
     44SRCDEMANGLE += $(SRC_CONTROLSTRUCT)
     45
  • src/GenPoly/Lvalue.cc

    r74ec742 r29d8c02  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon May 16 14:09:00 2022
    13 // Update Count     : 8
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 23:14:38 2019
     13// Update Count     : 7
    1414//
    1515
     
    125125        } // namespace
    126126
    127         // Stored elsewhere (Lvalue2, initially false).
    128         extern bool referencesEliminated;
     127        static bool referencesEliminated = false;
     128        // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
     129        bool referencesPermissable() {
     130                return ! referencesEliminated;
     131        }
    129132
    130133        void convertLvalue( std::list< Declaration* > & translationUnit ) {
  • src/GenPoly/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:31:00 2022
    14 ## Update Count     : 2
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Mon Jun  1 17:52:30 2015
     14## Update Count     : 1
    1515###############################################################################
    1616
    17 SRC_GENPOLY = \
    18         GenPoly/GenPoly.cc \
    19         GenPoly/GenPoly.h \
    20         GenPoly/Lvalue2.cc \
    21         GenPoly/Lvalue.h
     17SRC += GenPoly/Box.cc \
     18       GenPoly/Box.h \
     19       GenPoly/ErasableScopedMap.h \
     20       GenPoly/FindFunction.cc \
     21       GenPoly/FindFunction.h \
     22       GenPoly/GenPoly.cc \
     23       GenPoly/GenPoly.h \
     24       GenPoly/InstantiateGeneric.cc \
     25       GenPoly/InstantiateGeneric.h \
     26       GenPoly/Lvalue.cc \
     27       GenPoly/Lvalue.h \
     28       GenPoly/ScopedSet.h \
     29       GenPoly/ScrubTyVars.cc \
     30       GenPoly/ScrubTyVars.h \
     31       GenPoly/Specialize.cc \
     32       GenPoly/Specialize.h
    2233
    23 SRC += $(SRC_GENPOLY) \
    24         GenPoly/Box.cc \
    25         GenPoly/Box.h \
    26         GenPoly/ErasableScopedMap.h \
    27         GenPoly/FindFunction.cc \
    28         GenPoly/FindFunction.h \
    29         GenPoly/InstantiateGeneric.cc \
    30         GenPoly/InstantiateGeneric.h \
    31         GenPoly/Lvalue.cc \
    32         GenPoly/ScopedSet.h \
    33         GenPoly/ScrubTyVars.cc \
    34         GenPoly/ScrubTyVars.h \
    35         GenPoly/Specialize.cc \
    36         GenPoly/Specialize.h
     34SRCDEMANGLE += GenPoly/GenPoly.cc GenPoly/GenPoly.h GenPoly/Lvalue.cc GenPoly/Lvalue.h
    3735
    38 SRCDEMANGLE += $(SRC_GENPOLY)
  • src/InitTweak/FixInitNew.cpp

    r74ec742 r29d8c02  
    454454
    455455                auto expr = new ast::ImplicitCopyCtorExpr( appExpr->location, mutExpr );
    456                 // Move the type substitution to the new top-level. The substitution
    457                 // is needed to obtain the type of temporary variables so that copy
    458                 // constructor calls can be resolved.
     456                // Move the type substitution to the new top-level, if it is attached to the appExpr.
     457                // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion.
     458                // The substitution is needed to obtain the type of temporary variables so that copy constructor
     459                // calls can be resolved.
    459460                assert( typeSubs );
     461                // assert (mutExpr->env);
    460462                expr->env = tmp;
     463                // mutExpr->env = nullptr;
     464                //std::swap( expr->env, appExpr->env );
    461465                return expr;
    462466        }
    463467
    464468        void ResolveCopyCtors::previsit(const ast::Expr * expr) {
    465                 if ( nullptr == expr->env ) {
    466                         return;
    467                 }
    468                 GuardValue( env ) = expr->env->clone();
    469                 GuardValue( envModified ) = false;
     469                if (expr->env) {
     470                        GuardValue(env);
     471                        GuardValue(envModified);
     472                        env = expr->env->clone();
     473                        envModified = false;
     474                }
    470475        }
    471476
    472477        const ast::Expr * ResolveCopyCtors::postvisit(const ast::Expr * expr) {
    473                 // No local environment, skip.
    474                 if ( nullptr == expr->env ) {
    475                         return expr;
    476                 // Environment was modified, mutate and replace.
    477                 } else if ( envModified ) {
    478                         auto mutExpr = mutate(expr);
    479                         mutExpr->env = env;
    480                         return mutExpr;
    481                 // Environment was not mutated, delete the shallow copy before guard.
    482                 } else {
    483                         delete env;
     478                if (expr->env) {
     479                        if (envModified) {
     480                                auto mutExpr = mutate(expr);
     481                                mutExpr->env = env;
     482                                return mutExpr;
     483                        }
     484                        else {
     485                                // env was not mutated, skip and delete the shallow copy
     486                                delete env;
     487                                return expr;
     488                        }
     489                }
     490                else {
    484491                        return expr;
    485492                }
     
    490497        const ast::Expr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, const ast::ObjectDecl * var, const ast::Expr * cpArg ) {
    491498                assert( var );
    492                 assert( var->isManaged() );
    493                 assert( !cpArg || cpArg->isManaged() );
     499                assert (var->isManaged());
     500                assert (!cpArg || cpArg->isManaged());
    494501                // arrays are not copy constructed, so this should always be an ExprStmt
    495502                ast::ptr< ast::Stmt > stmt = genCtorDtor(var->location, fname, var, cpArg );
     
    497504                auto exprStmt = stmt.strict_as<ast::ImplicitCtorDtorStmt>()->callStmt.strict_as<ast::ExprStmt>();
    498505                ast::ptr<ast::Expr> untyped = exprStmt->expr; // take ownership of expr
     506                // exprStmt->expr = nullptr;
    499507
    500508                // resolve copy constructor
     
    508516                        env->add( *resolved->env );
    509517                        envModified = true;
     518                        // delete resolved->env;
    510519                        auto mut = mutate(resolved.get());
    511520                        assertf(mut == resolved.get(), "newly resolved expression must be unique");
    512521                        mut->env = nullptr;
    513522                } // if
     523                // delete stmt;
    514524                if ( auto assign = resolved.as<ast::TupleAssignExpr>() ) {
    515525                        // fix newly generated StmtExpr
  • src/InitTweak/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:31:00 2022
    14 ## Update Count     : 4
     12## Last Modified By : Rob Schluntz
     13## Last Modified On : Fri May 13 11:36:24 2016
     14## Update Count     : 3
    1515###############################################################################
    1616
    17 SRC_INITTWEAK = \
     17SRC += \
     18        InitTweak/FixGlobalInit.cc \
     19        InitTweak/FixGlobalInit.h \
     20        InitTweak/FixInit.cc \
     21        InitTweak/FixInit.h \
     22        InitTweak/GenInit.cc \
     23        InitTweak/GenInit.h \
     24        InitTweak/InitTweak.cc \
     25        InitTweak/InitTweak.h \
     26        InitTweak/FixInitNew.cpp
     27
     28SRCDEMANGLE += \
    1829        InitTweak/GenInit.cc \
    1930        InitTweak/GenInit.h \
     
    2132        InitTweak/InitTweak.h
    2233
    23 SRC += $(SRC_INITTWEAK) \
    24         InitTweak/FixGlobalInit.cc \
    25         InitTweak/FixGlobalInit.h \
    26         InitTweak/FixInit.cc \
    27         InitTweak/FixInit.h \
    28         InitTweak/FixInitNew.cpp
    29 
    30 SRCDEMANGLE += $(SRC_INITTWEAK)
  • src/Parser/DeclarationNode.cc

    r74ec742 r29d8c02  
    253253} // DeclarationNode::newAggregate
    254254
    255 DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, DeclarationNode * base) {
     255DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body) {
    256256        DeclarationNode * newnode = new DeclarationNode;
    257257        newnode->type = new TypeData( TypeData::Enum );
     
    260260        newnode->type->enumeration.body = body;
    261261        newnode->type->enumeration.anon = name == nullptr;
    262         if ( base && base->type)  {
    263                 newnode->type->base = base->type;       
    264         } // if
    265 
    266         // Check: if base has TypeData
    267262        return newnode;
    268263} // DeclarationNode::newEnum
     
    295290                return newName( name ); // Not explicitly inited enum value;
    296291        } // if
    297 } // DeclarationNode::newEnumValueGeneric
     292} // DeclarationNode::newEnumGeneric
    298293
    299294DeclarationNode * DeclarationNode::newFromTypedef( const string * name ) {
  • src/Parser/ParseNode.h

    r74ec742 r29d8c02  
    235235        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    236236        static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    237         static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, DeclarationNode * base = nullptr );
     237        static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body );
    238238        static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
    239239        static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );
  • src/Parser/TypeData.cc

    r74ec742 r29d8c02  
    388388                if ( enumeration.body ) {
    389389                        os << string( indent + 2, ' ' ) << " with body" << endl;
    390                 } // if
    391                 if ( base ) {
    392                         os << "for ";
    393                         base->print( os, indent + 2 );
    394390                } // if
    395391                break;
     
    930926                        ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
    931927                        member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) );
    932                 } else if ( !cur->initializer ) {
     928                } else {
    933929                        if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isWholeNumber())) {
    934930                                SemanticError( td->location, "A non whole number enum value decl must be explicitly initialized." );
    935931                        }
    936                 }
    937                 // else cur is a List Initializer and has been set as init in buildList()
    938                 // if
     932                } // if
    939933        } // for
    940         ret->set_body( td->enumeration.body );
     934        ret->set_body( td->enumeration.body ); // Boolean; if it has body
    941935        return ret;
    942936} // buildEnum
  • src/Parser/parser.yy

    r74ec742 r29d8c02  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 14 09:16:22 2022
    13 // Update Count     : 5401
     12// Last Modified On : Mon Mar 14 16:35:29 2022
     13// Update Count     : 5276
    1414//
    1515
     
    5454#include "Common/SemanticError.h"                                               // error_str
    5555#include "Common/utility.h"                                                             // for maybeMoveBuild, maybeBuild, CodeLo...
    56 
    57 #include "SynTree/Attribute.h"     // for Attribute
    5856
    5957extern DeclarationNode * parseTree;
     
    9593} // appendStr
    9694
    97 DeclarationNode * distAttr( DeclarationNode * typeSpec, DeclarationNode * declList ) {
    98         // distribute declaration_specifier across all declared variables, e.g., static, const, but not __attribute__.
    99         assert( declList );
    100 //      printf( "distAttr1 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout );
    101         DeclarationNode * cur = declList, * cl = (new DeclarationNode)->addType( typeSpec );
    102 //      printf( "distAttr2 cl %p\n", cl ); cl->type->print( std::cout );
    103 //      cl->type->aggregate.name = cl->type->aggInst.aggregate->aggregate.name;
    104 
     95DeclarationNode * distAttr( DeclarationNode * specifier, DeclarationNode * declList ) {
     96        // distribute declaration_specifier across all declared variables, e.g., static, const, __attribute__.
     97        DeclarationNode * cur = declList, * cl = (new DeclarationNode)->addType( specifier );
    10598        for ( cur = dynamic_cast<DeclarationNode *>( cur->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
    10699                cl->cloneBaseType( cur );
    107100        } // for
    108101        declList->addType( cl );
    109 //      printf( "distAttr3 declList %p\n", declList ); declList->print( std::cout, 0 );
    110102        return declList;
    111103} // distAttr
     
    119111
    120112void distInl( DeclarationNode * declaration ) {
    121         // distribute INLINE across all declarations
     113        // distribute EXTENSION across all declarations
    122114        for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    123115                iter->set_inLine( true );
     
    179171                if ( ! ( typeSpec->type && (typeSpec->type->kind == TypeData::Aggregate || typeSpec->type->kind == TypeData::Enum) ) ) {
    180172                        stringstream ss;
    181                         // printf( "fieldDecl1 typeSpec %p\n", typeSpec ); typeSpec->type->print( std::cout );
     173                        typeSpec->type->print( ss );
    182174                        SemanticWarning( yylloc, Warning::SuperfluousDecl, ss.str().c_str() );
    183175                        return nullptr;
    184176                } // if
    185                 // printf( "fieldDecl2 typeSpec %p\n", typeSpec ); typeSpec->type->print( std::cout );
    186177                fieldList = DeclarationNode::newName( nullptr );
    187178        } // if
    188 //      return distAttr( typeSpec, fieldList );                         // mark all fields in list
    189 
    190         // printf( "fieldDecl3 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout, 0 );
    191         DeclarationNode * temp = distAttr( typeSpec, fieldList );                               // mark all fields in list
    192         // printf( "fieldDecl4 temp %p\n", temp ); temp->print( std::cout, 0 );
    193         return temp;
     179        return distAttr( typeSpec, fieldList );                         // mark all fields in list
    194180} // fieldDecl
    195181
     
    12351221
    12361222iteration_statement:
    1237         WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
     1223        WHILE '(' ')' statement                                                         // CFA => while ( 1 )
    12381224                { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
    1239         | WHILE '(' ')' statement ELSE statement                        // CFA
    1240                 {
    1241                         $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) );
    1242                         SemanticWarning( yylloc, Warning::SuperfluousElse );
    1243                 }
    12441225        | WHILE '(' conditional_declaration ')' statement       %prec THEN
    12451226                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
     
    12481229        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    12491230                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
    1250         | DO statement WHILE '(' ')' ELSE statement                     // CFA
    1251                 {
    1252                         $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) );
    1253                         SemanticWarning( yylloc, Warning::SuperfluousElse );
    1254                 }
    1255         | DO statement WHILE '(' comma_expression ')' ';'
     1231        | DO statement WHILE '(' comma_expression ')' ';'       %prec THEN
    12561232                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    12571233        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    12581234                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
    1259         | FOR '(' ')' statement                                                         %prec THEN // CFA => for ( ;; )
     1235        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    12601236                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
    1261         | FOR '(' ')' statement ELSE statement                          // CFA
    1262                 {
    1263                         $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) );
    1264                         SemanticWarning( yylloc, Warning::SuperfluousElse );
    1265                 }
    12661237        | FOR '(' for_control_expression_list ')' statement     %prec THEN
    12671238                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
     
    16341605declaration:                                                                                    // old & new style declarations
    16351606        c_declaration ';'
    1636                 {
    1637                         // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
    1638                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    1639                         //   printf( "\tattr %s\n", attr->name.c_str() );
    1640                         // } // for
    1641                 }
    16421607        | cfa_declaration ';'                                                           // CFA
    16431608        | static_assert                                                                         // C11
     
    18451810        basic_type_specifier
    18461811        | sue_type_specifier
    1847                 {
    1848                         // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    1849                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    1850                         //   printf( "\tattr %s\n", attr->name.c_str() );
    1851                         // } // for
    1852                 }
    18531812        | type_type_specifier
    18541813        ;
     
    20672026sue_declaration_specifier:                                                              // struct, union, enum + storage class + type specifier
    20682027        sue_type_specifier
    2069                 {
    2070                         // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2071                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2072                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2073                         // } // for
    2074                 }
    20752028        | declaration_qualifier_list sue_type_specifier
    20762029                { $$ = $2->addQualifiers( $1 ); }
     
    20832036sue_type_specifier:                                                                             // struct, union, enum + type specifier
    20842037        elaborated_type
    2085                 {
    2086                         // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2087                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2088                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2089                         // } // for
    2090                 }
    20912038        | type_qualifier_list
    20922039                { if ( $1->type != nullptr && $1->type->forall ) forall = true; } // remember generic type
     
    21612108elaborated_type:                                                                                // struct, union, enum
    21622109        aggregate_type
    2163                 {
    2164                         // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2165                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2166                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2167                         // } // for
    2168                 }
    21692110        | enum_type
    21702111        ;
     
    21862127                }
    21872128          '{' field_declaration_list_opt '}' type_parameters_opt
    2188                 {
    2189                         // printf( "aggregate_type1 %s\n", $3.str->c_str() );
    2190                         // if ( $2 )
    2191                         //      for ( Attribute * attr: reverseIterate( $2->attributes ) ) {
    2192                         //              printf( "copySpecifiers12 %s\n", attr->name.c_str() );
    2193                         //      } // for
    2194                         $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
    2195                         // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2196                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2197                         //      printf( "aggregate_type3 %s\n", attr->name.c_str() );
    2198                         // } // for
    2199                 }
     2129                { $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); }
    22002130        | aggregate_key attribute_list_opt TYPEDEFname          // unqualified type name
    22012131                {
     
    22052135          '{' field_declaration_list_opt '}' type_parameters_opt
    22062136                {
    2207                         // printf( "AGG3\n" );
    22082137                        DeclarationNode::newFromTypedef( $3 );
    22092138                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    22162145          '{' field_declaration_list_opt '}' type_parameters_opt
    22172146                {
    2218                         // printf( "AGG4\n" );
    22192147                        DeclarationNode::newFromTypeGen( $3, nullptr );
    22202148                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    22932221field_declaration:
    22942222        type_specifier field_declaring_list_opt ';'
    2295                 {
    2296                         // printf( "type_specifier1 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2297                         $$ = fieldDecl( $1, $2 );
    2298                         // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2299                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2300                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2301                         // } // for
    2302                 }
     2223                { $$ = fieldDecl( $1, $2 ); }
    23032224        | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
    23042225                { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
     
    23822303        ;
    23832304
    2384 enum_type:
     2305enum_type: // static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed );                                                                                         // enum
    23852306        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    23862307                { $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
     
    23972318                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    23982319
    2399                         $$ = DeclarationNode::newEnum( nullptr, $7, true, $3 )->addQualifiers( $5 );
    2400                 }
    2401         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
     2320                        $$ = DeclarationNode::newEnum( nullptr, $7, true ) ->addQualifiers( $5 )  -> addEnumBase( $3 );
     2321                }
     2322        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt // Question: why attributes/qualifier after identifier
    24022323                {
    24032324                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
     
    24062327          '{' enumerator_list comma_opt '}'
    24072328                {
    2408                         $$ = DeclarationNode::newEnum( $6, $10, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2329                        $$ = DeclarationNode::newEnum( $6, $10, true ) -> addQualifiers( $5 ) -> addQualifiers( $7 ) -> addEnumBase( $3 );
    24092330                }
    24102331        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
     
    24122333                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    24132334                        typedefTable.makeTypedef( *$6->name );
    2414                         $$ = DeclarationNode::newEnum( $6->name, $9, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2335                        $$ = DeclarationNode::newEnum( $6->name, $9, true ) -> addQualifiers( $5 ) -> addQualifiers( $7 ) -> addEnumBase( $3 );
    24152336                }
    24162337        | enum_type_nobody
     
    29092830        // empty
    29102831                { $$ = nullptr; forall = false; }
    2911         | WITH '(' tuple_expression_list ')' attribute_list_opt
    2912                 {
    2913                         $$ = $3; forall = false;
    2914                         if ( $5 ) {
    2915                                 SemanticError( yylloc, "Attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." );
    2916                                 $$ = nullptr;
    2917                         } // if
    2918                 }
     2832        | WITH '(' tuple_expression_list ')'
     2833                { $$ = $3; forall = false; }
    29192834        ;
    29202835
  • src/ResolvExpr/AlternativeFinder.cc

    r74ec742 r29d8c02  
    4242#include "SymTab/Indexer.h"        // for Indexer
    4343#include "SymTab/Mangler.h"        // for Mangler
    44 #include "SymTab/ValidateType.h"   // for validateType
     44#include "SymTab/Validate.h"       // for validateType
    4545#include "SynTree/Constant.h"      // for Constant
    4646#include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
  • src/ResolvExpr/Resolver.cc

    r74ec742 r29d8c02  
    427427                        // enumerator initializers should not use the enum type to initialize, since
    428428                        // the enum type is still incomplete at this point. Use signed int instead.
    429                         // TODO: BasicType::SignedInt may not longer be true
    430429                        currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    431430                }
     
    14781477                        // enum type is still incomplete at this point. Use `int` instead.
    14791478
    1480                         if (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base) {
     1479                        if (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base) { // const ast::PointerType &
     1480                                // const ast::Type * enumBase =  (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base.get());
     1481                                // const ast::PointerType * enumBaseAsPtr = dynamic_cast<const ast::PointerType *>(enumBase);
     1482
     1483                                // if ( enumBaseAsPtr ) {
     1484                                //      const ast::Type * pointerBase = enumBaseAsPtr->base.get();
     1485                                //      if ( dynamic_cast<const ast::BasicType *>(pointerBase) ) {
     1486                                //              objectDecl = fixObjectType(objectDecl, context);
     1487                                //              if (dynamic_cast<const ast::BasicType *>(pointerBase)->kind == ast::BasicType::Char)
     1488                                //              currentObject = ast::CurrentObject{
     1489                                //                      objectDecl->location,  new ast::PointerType{
     1490                                //                              new ast::BasicType{ ast::BasicType::Char }
     1491                                //                      } };
     1492                                //      } else {
     1493                                //              objectDecl = fixObjectType(objectDecl, context);
     1494                                //              currentObject = ast::CurrentObject{objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
     1495                                //      }
     1496                                // }
    14811497                                objectDecl = fixObjectType( objectDecl, context );
    14821498                                const ast::Type * enumBase =  (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base.get());
  • src/SymTab/Autogen.h

    r74ec742 r29d8c02  
    2121
    2222#include "AST/Decl.hpp"
     23#include "AST/Eval.hpp"
    2324#include "AST/Expr.hpp"
    2425#include "AST/Init.hpp"
     
    7071        template< typename OutIter >
    7172        ast::ptr< ast::Stmt > genCall(
    72                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    73                 const CodeLocation & loc, const std::string & fname, OutIter && out,
     73                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 
     74                const CodeLocation & loc, const std::string & fname, OutIter && out, 
    7475                const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
    7576
     
    127128        }
    128129
    129         /// inserts into out a generated call expression to function fname with arguments dstParam and
     130        /// inserts into out a generated call expression to function fname with arguments dstParam and 
    130131        /// srcParam. Should only be called with non-array types.
    131         /// optionally returns a statement which must be inserted prior to the containing loop, if
     132        /// optionally returns a statement which must be inserted prior to the containing loop, if 
    132133        /// there is one
    133134        template< typename OutIter >
    134         ast::ptr< ast::Stmt > genScalarCall(
    135                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    136                 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
     135        ast::ptr< ast::Stmt > genScalarCall( 
     136                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 
     137                const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type, 
    137138                const ast::Type * addCast = nullptr
    138139        ) {
     
    152153
    153154                if ( addCast ) {
    154                         // cast to T& with qualifiers removed, so that qualified objects can be constructed and
    155                         // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
    156                         // is considered a qualifier - for AddressExpr to resolve, its argument must have an
     155                        // cast to T& with qualifiers removed, so that qualified objects can be constructed and 
     156                        // destructed with the same functions as non-qualified objects. Unfortunately, lvalue 
     157                        // is considered a qualifier - for AddressExpr to resolve, its argument must have an 
    157158                        // lvalue-qualified type, so remove all qualifiers except lvalue.
    158159                        // xxx -- old code actually removed lvalue too...
    159160                        ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
    160161                        ast::ptr< ast::Type > castType = addCast;
    161                         ast::remove_qualifiers(
    162                                 castType,
     162                        ast::remove_qualifiers( 
     163                                castType, 
    163164                                ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
    164165                        dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
     
    180181
    181182                srcParam.clearArrayIndices();
    182 
     183               
    183184                return listInit;
    184185        }
     
    248249        }
    249250
    250         /// Store in out a loop which calls fname on each element of the array with srcParam and
     251        /// Store in out a loop which calls fname on each element of the array with srcParam and 
    251252        /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
    252253        template< typename OutIter >
    253254        void genArrayCall(
    254                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    255                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    256                 const ast::ArrayType * array, const ast::Type * addCast = nullptr,
    257                 LoopDirection forward = LoopForward
     255                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 
     256                const CodeLocation & loc, const std::string & fname, OutIter && out, 
     257                const ast::ArrayType * array, const ast::Type * addCast = nullptr, 
     258                LoopDirection forward = LoopForward 
    258259        ) {
    259260                static UniqueName indexName( "_index" );
     
    278279                } else {
    279280                        // generate: for ( int i = N-1; i >= 0; --i )
    280                         begin = ast::UntypedExpr::createCall( loc, "?-?",
    281                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
     281                        begin = ast::call(
     282                                loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
    282283                        end = ast::ConstantExpr::from_int( loc, 0 );
    283284                        cmp = "?>=?";
     
    285286                }
    286287
    287                 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
    288                         loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
     288                ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{ 
     289                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt }, 
    289290                        new ast::SingleInit{ loc, begin } };
    290291                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
    291 
    292                 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
    293                         loc, cmp, { indexVar, end } );
    294 
    295                 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
    296                         loc, update, { indexVar } );
    297 
    298                 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
    299                         loc, "?[?]", { dstParam, indexVar } );
    300 
    301                 // srcParam must keep track of the array indices to build the source parameter and/or
     292               
     293                ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
     294               
     295                ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
     296               
     297                ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
     298               
     299                // srcParam must keep track of the array indices to build the source parameter and/or
    302300                // array list initializer
    303301                srcParam.addArrayIndex( indexVar, array->dimension );
     
    305303                // for stmt's body, eventually containing call
    306304                ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
    307                 ast::ptr< ast::Stmt > listInit = genCall(
    308                         srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
     305                ast::ptr< ast::Stmt > listInit = genCall( 
     306                        srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast, 
    309307                        forward );
    310 
     308               
    311309                // block containing the stmt and index variable
    312310                ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
     
    330328        template< typename OutIter >
    331329        ast::ptr< ast::Stmt > genCall(
    332                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    333                 const CodeLocation & loc, const std::string & fname, OutIter && out,
     330                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 
     331                const CodeLocation & loc, const std::string & fname, OutIter && out, 
    334332                const ast::Type * type, const ast::Type * addCast, LoopDirection forward
    335333        ) {
    336334                if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
    337                         genArrayCall(
    338                                 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
     335                        genArrayCall( 
     336                                srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast, 
    339337                                forward );
    340338                        return {};
    341339                } else {
    342                         return genScalarCall(
     340                        return genScalarCall( 
    343341                                srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    344342                }
     
    379377        }
    380378
    381         static inline ast::ptr< ast::Stmt > genImplicitCall(
    382                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    383                 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
    384                 LoopDirection forward = LoopForward
     379        static inline ast::ptr< ast::Stmt > genImplicitCall( 
     380                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 
     381                const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj, 
     382                LoopDirection forward = LoopForward 
    385383        ) {
    386384                // unnamed bit fields are not copied as they cannot be accessed
     
    394392
    395393                std::vector< ast::ptr< ast::Stmt > > stmts;
    396                 genCall(
     394                genCall( 
    397395                        srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
    398396
     
    402400                        const ast::Stmt * callStmt = stmts.front();
    403401                        if ( addCast ) {
    404                                 // implicitly generated ctor/dtor calls should be wrapped so that later passes are
     402                                // implicitly generated ctor/dtor calls should be wrapped so that later passes are 
    405403                                // aware they were generated.
    406404                                callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
     
    419417// compile-command: "make install" //
    420418// End: //
     419
  • src/SymTab/Demangle.cc

    r74ec742 r29d8c02  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Demangle.cc -- Convert a mangled name into a human readable name.
     7// Demangler.cc --
    88//
    99// Author           : Rob Schluntz
  • src/SymTab/Mangler.h

    r74ec742 r29d8c02  
    111111}
    112112
     113extern "C" {
     114        char * cforall_demangle(const char *, int);
     115}
     116
    113117// Local Variables: //
    114118// tab-width: 4 //
  • src/SymTab/Validate.cc

    r74ec742 r29d8c02  
    1010// Created On       : Sun May 17 21:50:04 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 17 14:36:00 2022
    13 // Update Count     : 366
     12// Last Modified On : Fri Nov 12 11:00:00 2021
     13// Update Count     : 364
    1414//
    1515
     
    7474#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
    7575#include "SymTab/Autogen.h"            // for SizeType
    76 #include "SymTab/ValidateType.h"       // for decayEnumsAndPointers, decayFo...
    7776#include "SynTree/LinkageSpec.h"       // for C
    7877#include "SynTree/Attribute.h"         // for noAttributes, Attribute
     
    135134        };
    136135
     136        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
     137        struct EnumAndPointerDecay_old {
     138                void previsit( EnumDecl * aggregateDecl );
     139                void previsit( FunctionType * func );
     140        };
     141
     142        /// Associates forward declarations of aggregates with their definitions
     143        struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
     144                LinkReferenceToTypes_old( const Indexer * indexer );
     145                void postvisit( TypeInstType * typeInst );
     146
     147                void postvisit( EnumInstType * enumInst );
     148                void postvisit( StructInstType * structInst );
     149                void postvisit( UnionInstType * unionInst );
     150                void postvisit( TraitInstType * traitInst );
     151                void previsit( QualifiedType * qualType );
     152                void postvisit( QualifiedType * qualType );
     153
     154                void postvisit( EnumDecl * enumDecl );
     155                void postvisit( StructDecl * structDecl );
     156                void postvisit( UnionDecl * unionDecl );
     157                void postvisit( TraitDecl * traitDecl );
     158
     159                void previsit( StructDecl * structDecl );
     160                void previsit( UnionDecl * unionDecl );
     161
     162                void renameGenericParams( std::list< TypeDecl * > & params );
     163
     164          private:
     165                const Indexer * local_indexer;
     166
     167                typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
     168                typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
     169                typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
     170                ForwardEnumsType forwardEnums;
     171                ForwardStructsType forwardStructs;
     172                ForwardUnionsType forwardUnions;
     173                /// true if currently in a generic type body, so that type parameter instances can be renamed appropriately
     174                bool inGeneric = false;
     175        };
     176
    137177        /// Does early resolution on the expressions that give enumeration constants their values
    138178        struct ResolveEnumInitializers final : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveEnumInitializers>, public WithShortCircuiting {
     
    152192                void previsit( StructDecl * aggrDecl );
    153193                void previsit( UnionDecl * aggrDecl );
     194        };
     195
     196        // These structs are the sub-sub-passes of ForallPointerDecay_old.
     197
     198        struct TraitExpander_old final {
     199                void previsit( FunctionType * );
     200                void previsit( StructDecl * );
     201                void previsit( UnionDecl * );
     202        };
     203
     204        struct AssertionFixer_old final {
     205                void previsit( FunctionType * );
     206                void previsit( StructDecl * );
     207                void previsit( UnionDecl * );
     208        };
     209
     210        struct CheckOperatorTypes_old final {
     211                void previsit( ObjectDecl * );
     212        };
     213
     214        struct FixUniqueIds_old final {
     215                void previsit( DeclarationWithType * );
    154216        };
    155217
     
    295357
    296358        void validate_A( std::list< Declaration * > & translationUnit ) {
     359                PassVisitor<EnumAndPointerDecay_old> epc;
    297360                PassVisitor<HoistTypeDecls> hoistDecls;
    298361                {
     
    303366                        ReplaceTypedef::replaceTypedef( translationUnit );
    304367                        ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    305                         decayEnumsAndPointers( translationUnit ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
     368                        acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
    306369                }
    307370        }
    308371
    309372        void validate_B( std::list< Declaration * > & translationUnit ) {
     373                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
    310374                PassVisitor<FixQualifiedTypes> fixQual;
    311375                {
    312376                        Stats::Heap::newPass("validate-B");
    313377                        Stats::Time::BlockGuard guard("validate-B");
    314                         //linkReferenceToTypes( translationUnit );
     378                        acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    315379                        mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
    316380                        HoistStruct::hoistStruct( translationUnit );
     
    343407                        });
    344408                }
     409        }
     410
     411        static void decayForallPointers( std::list< Declaration * > & translationUnit ) {
     412                PassVisitor<TraitExpander_old> te;
     413                acceptAll( translationUnit, te );
     414                PassVisitor<AssertionFixer_old> af;
     415                acceptAll( translationUnit, af );
     416                PassVisitor<CheckOperatorTypes_old> cot;
     417                acceptAll( translationUnit, cot );
     418                PassVisitor<FixUniqueIds_old> fui;
     419                acceptAll( translationUnit, fui );
    345420        }
    346421
     
    421496        }
    422497
     498        void validateType( Type * type, const Indexer * indexer ) {
     499                PassVisitor<EnumAndPointerDecay_old> epc;
     500                PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
     501                PassVisitor<TraitExpander_old> te;
     502                PassVisitor<AssertionFixer_old> af;
     503                PassVisitor<CheckOperatorTypes_old> cot;
     504                PassVisitor<FixUniqueIds_old> fui;
     505                type->accept( epc );
     506                type->accept( lrt );
     507                type->accept( te );
     508                type->accept( af );
     509                type->accept( cot );
     510                type->accept( fui );
     511        }
     512
    423513        void HoistTypeDecls::handleType( Type * type ) {
    424514                // some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here
     
    613703        }
    614704
     705        void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) {
     706                // Set the type of each member of the enumeration to be EnumConstant
     707                for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
     708                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );
     709                        assert( obj );
     710                        obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
     711                } // for
     712        }
     713
     714        namespace {
     715                template< typename DWTList >
     716                void fixFunctionList( DWTList & dwts, bool isVarArgs, FunctionType * func ) {
     717                        auto nvals = dwts.size();
     718                        bool containsVoid = false;
     719                        for ( auto & dwt : dwts ) {
     720                                // fix each DWT and record whether a void was found
     721                                containsVoid |= fixFunction( dwt );
     722                        }
     723
     724                        // the only case in which "void" is valid is where it is the only one in the list
     725                        if ( containsVoid && ( nvals > 1 || isVarArgs ) ) {
     726                                SemanticError( func, "invalid type void in function type " );
     727                        }
     728
     729                        // one void is the only thing in the list; remove it.
     730                        if ( containsVoid ) {
     731                                delete dwts.front();
     732                                dwts.clear();
     733                        }
     734                }
     735        }
     736
     737        void EnumAndPointerDecay_old::previsit( FunctionType * func ) {
     738                // Fix up parameters and return types
     739                fixFunctionList( func->parameters, func->isVarArgs, func );
     740                fixFunctionList( func->returnVals, false, func );
     741        }
     742
     743        LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) : WithIndexer( false ) {
     744                if ( other_indexer ) {
     745                        local_indexer = other_indexer;
     746                } else {
     747                        local_indexer = &indexer;
     748                } // if
     749        }
     750
     751        void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {
     752                const EnumDecl * st = local_indexer->lookupEnum( enumInst->name );
     753                // it's not a semantic error if the enum is not found, just an implicit forward declaration
     754                if ( st ) {
     755                        enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node
     756                } // if
     757                if ( ! st || ! st->body ) {
     758                        // use of forward declaration
     759                        forwardEnums[ enumInst->name ].push_back( enumInst );
     760                } // if
     761        }
     762
     763        void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
     764                const StructDecl * st = local_indexer->lookupStruct( structInst->name );
     765                // it's not a semantic error if the struct is not found, just an implicit forward declaration
     766                if ( st ) {
     767                        structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node
     768                } // if
     769                if ( ! st || ! st->body ) {
     770                        // use of forward declaration
     771                        forwardStructs[ structInst->name ].push_back( structInst );
     772                } // if
     773        }
     774
     775        void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {
     776                const UnionDecl * un = local_indexer->lookupUnion( unionInst->name );
     777                // it's not a semantic error if the union is not found, just an implicit forward declaration
     778                if ( un ) {
     779                        unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node
     780                } // if
     781                if ( ! un || ! un->body ) {
     782                        // use of forward declaration
     783                        forwardUnions[ unionInst->name ].push_back( unionInst );
     784                } // if
     785        }
     786
     787        void LinkReferenceToTypes_old::previsit( QualifiedType * ) {
     788                visit_children = false;
     789        }
     790
     791        void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) {
     792                // linking only makes sense for the 'oldest ancestor' of the qualified type
     793                qualType->parent->accept( * visitor );
     794        }
     795
     796        template< typename Decl >
     797        void normalizeAssertions( std::list< Decl * > & assertions ) {
     798                // ensure no duplicate trait members after the clone
     799                auto pred = [](Decl * d1, Decl * d2) {
     800                        // only care if they're equal
     801                        DeclarationWithType * dwt1 = dynamic_cast<DeclarationWithType *>( d1 );
     802                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
     803                        if ( dwt1 && dwt2 ) {
     804                                if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     805                                        // std::cerr << "=========== equal:" << std::endl;
     806                                        // std::cerr << "d1: " << d1 << std::endl;
     807                                        // std::cerr << "d2: " << d2 << std::endl;
     808                                        return false;
     809                                }
     810                        }
     811                        return d1 < d2;
     812                };
     813                std::set<Decl *, decltype(pred)> unique_members( assertions.begin(), assertions.end(), pred );
     814                // if ( unique_members.size() != assertions.size() ) {
     815                //      std::cerr << "============different" << std::endl;
     816                //      std::cerr << unique_members.size() << " " << assertions.size() << std::endl;
     817                // }
     818
     819                std::list< Decl * > order;
     820                order.splice( order.end(), assertions );
     821                std::copy_if( order.begin(), order.end(), back_inserter( assertions ), [&]( Decl * decl ) {
     822                        return unique_members.count( decl );
     823                });
     824        }
     825
    615826        // expand assertions from trait instance, performing the appropriate type variable substitutions
    616827        template< typename Iterator >
     
    623834                // substitute trait decl parameters for instance parameters
    624835                applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
     836        }
     837
     838        void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
     839                if ( traitDecl->name == "sized" ) {
     840                        // "sized" is a special trait - flick the sized status on for the type variable
     841                        assertf( traitDecl->parameters.size() == 1, "Built-in trait 'sized' has incorrect number of parameters: %zd", traitDecl->parameters.size() );
     842                        TypeDecl * td = traitDecl->parameters.front();
     843                        td->set_sized( true );
     844                }
     845
     846                // move assertions from type parameters into the body of the trait
     847                for ( TypeDecl * td : traitDecl->parameters ) {
     848                        for ( DeclarationWithType * assert : td->assertions ) {
     849                                if ( TraitInstType * inst = dynamic_cast< TraitInstType * >( assert->get_type() ) ) {
     850                                        expandAssertions( inst, back_inserter( traitDecl->members ) );
     851                                } else {
     852                                        traitDecl->members.push_back( assert->clone() );
     853                                }
     854                        }
     855                        deleteAll( td->assertions );
     856                        td->assertions.clear();
     857                } // for
     858        }
     859
     860        void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
     861                // handle other traits
     862                const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );
     863                if ( ! traitDecl ) {
     864                        SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
     865                } // if
     866                if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
     867                        SemanticError( traitInst, "incorrect number of trait parameters: " );
     868                } // if
     869                traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node
     870
     871                // need to carry over the 'sized' status of each decl in the instance
     872                for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
     873                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
     874                        if ( ! expr ) {
     875                                SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
     876                        }
     877                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
     878                                TypeDecl * formalDecl = std::get<0>(p);
     879                                TypeDecl * instDecl = inst->baseType;
     880                                if ( formalDecl->get_sized() ) instDecl->set_sized( true );
     881                        }
     882                }
     883                // normalizeAssertions( traitInst->members );
     884        }
     885
     886        void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {
     887                // visit enum members first so that the types of self-referencing members are updated properly
     888                if ( enumDecl->body ) {
     889                        ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
     890                        if ( fwds != forwardEnums.end() ) {
     891                                for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
     892                                        (* inst)->baseEnum = enumDecl;
     893                                } // for
     894                                forwardEnums.erase( fwds );
     895                        } // if
     896                } // if
     897        }
     898
     899        void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) {
     900                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
     901                //   forall(otype T)
     902                //   struct Box {
     903                //     T x;
     904                //   };
     905                //   forall(otype T)
     906                //   void f(Box(T) b) {
     907                //     ...
     908                //   }
     909                // The T in Box and the T in f are different, so internally the naming must reflect that.
     910                GuardValue( inGeneric );
     911                inGeneric = ! params.empty();
     912                for ( TypeDecl * td : params ) {
     913                        td->name = "__" + td->name + "_generic_";
     914                }
     915        }
     916
     917        void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
     918                renameGenericParams( structDecl->parameters );
     919        }
     920
     921        void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
     922                renameGenericParams( unionDecl->parameters );
     923        }
     924
     925        void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {
     926                // visit struct members first so that the types of self-referencing members are updated properly
     927                // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
     928                if ( structDecl->body ) {
     929                        ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
     930                        if ( fwds != forwardStructs.end() ) {
     931                                for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
     932                                        (* inst)->baseStruct = structDecl;
     933                                } // for
     934                                forwardStructs.erase( fwds );
     935                        } // if
     936                } // if
     937        }
     938
     939        void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {
     940                if ( unionDecl->body ) {
     941                        ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
     942                        if ( fwds != forwardUnions.end() ) {
     943                                for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
     944                                        (* inst)->baseUnion = unionDecl;
     945                                } // for
     946                                forwardUnions.erase( fwds );
     947                        } // if
     948                } // if
     949        }
     950
     951        void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {
     952                // ensure generic parameter instances are renamed like the base type
     953                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
     954                if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {
     955                        if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) {
     956                                typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
     957                        } // if
     958                } // if
    625959        }
    626960
     
    651985                                                }
    652986                                        }
     987                                       
    653988                                }
    654989                        }
     
    7381073        void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
    7391074                forallFixer( aggrDecl->parameters, aggrDecl );
     1075        }
     1076
     1077        void TraitExpander_old::previsit( FunctionType * ftype ) {
     1078                expandTraits( ftype->forall );
     1079        }
     1080
     1081        void TraitExpander_old::previsit( StructDecl * aggrDecl ) {
     1082                expandTraits( aggrDecl->parameters );
     1083        }
     1084
     1085        void TraitExpander_old::previsit( UnionDecl * aggrDecl ) {
     1086                expandTraits( aggrDecl->parameters );
     1087        }
     1088
     1089        void AssertionFixer_old::previsit( FunctionType * ftype ) {
     1090                fixAssertions( ftype->forall, ftype );
     1091        }
     1092
     1093        void AssertionFixer_old::previsit( StructDecl * aggrDecl ) {
     1094                fixAssertions( aggrDecl->parameters, aggrDecl );
     1095        }
     1096
     1097        void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) {
     1098                fixAssertions( aggrDecl->parameters, aggrDecl );
     1099        }
     1100
     1101        void CheckOperatorTypes_old::previsit( ObjectDecl * object ) {
     1102                // ensure that operator names only apply to functions or function pointers
     1103                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     1104                        SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
     1105                }
     1106        }
     1107
     1108        void FixUniqueIds_old::previsit( DeclarationWithType * decl ) {
     1109                decl->fixUniqueId();
    7401110        }
    7411111
  • src/SymTab/Validate.h

    r74ec742 r29d8c02  
    1010// Author           : Richard C. Bilson
    1111// Created On       : Sun May 17 21:53:34 2015
    12 // Last Modified By : Andrew Beach
    13 // Last Modified On : Tue May 17 14:35:00 2022
    14 // Update Count     : 5
     12// Last Modified By : Peter A. Buhr
     13// Last Modified On : Sat Jul 22 09:46:07 2017
     14// Update Count     : 4
    1515//
    1616
     
    3333        /// Normalizes struct and function declarations
    3434        void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
     35        void validateType( Type *type, const Indexer *indexer );
    3536
    3637        // Sub-passes of validate.
     
    4142        void validate_E( std::list< Declaration * > &translationUnit );
    4243        void validate_F( std::list< Declaration * > &translationUnit );
     44
     45        const ast::Type * validateType(
     46                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
    4347} // namespace SymTab
    4448
  • src/SymTab/demangler.cc

    r74ec742 r29d8c02  
    1 #include "Demangle.h"
     1#include "Mangler.h"
    22#include <iostream>
    33#include <fstream>
  • src/SymTab/module.mk

    r74ec742 r29d8c02  
    1111## Created On       : Mon Jun  1 17:49:17 2015
    1212## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:46:00 2022
    14 ## Update Count     : 5
     13## Last Modified On : Thr Aug 10 16:08:00 2017
     14## Update Count     : 4
    1515###############################################################################
    1616
    1717SRC_SYMTAB = \
    18         SymTab/Autogen.cc \
    19         SymTab/Autogen.h \
    20         SymTab/FixFunction.cc \
    21         SymTab/FixFunction.h \
    22         SymTab/Indexer.cc \
    23         SymTab/Indexer.h \
    24         SymTab/Mangler.cc \
    25         SymTab/ManglerCommon.cc \
    26         SymTab/Mangler.h \
    27         SymTab/ValidateType.cc \
    28         SymTab/ValidateType.h
     18      SymTab/Autogen.cc \
     19      SymTab/Autogen.h \
     20      SymTab/FixFunction.cc \
     21      SymTab/FixFunction.h \
     22      SymTab/Indexer.cc \
     23      SymTab/Indexer.h \
     24      SymTab/Mangler.cc \
     25      SymTab/ManglerCommon.cc \
     26      SymTab/Mangler.h \
     27      SymTab/Validate.cc \
     28      SymTab/Validate.h
    2929
    30 SRC += $(SRC_SYMTAB) \
    31         SymTab/Validate.cc \
    32         SymTab/Validate.h
    33 
    34 SRCDEMANGLE += $(SRC_SYMTAB) \
    35         SymTab/Demangle.cc \
    36         SymTab/Demangle.h
     30SRC += $(SRC_SYMTAB)
     31SRCDEMANGLE += $(SRC_SYMTAB) SymTab/Demangle.cc
  • src/SynTree/module.mk

    r74ec742 r29d8c02  
    2424      SynTree/AttrType.cc \
    2525      SynTree/BaseSyntaxNode.h \
    26       SynTree/BaseSyntaxNode.cc \
    2726      SynTree/BasicType.cc \
    2827      SynTree/CommaExpr.cc \
  • src/Tuples/TupleExpansion.cc

    r74ec742 r29d8c02  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 17 15:02:00 2022
    13 // Update Count     : 25
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 23:45:51 2019
     13// Update Count     : 24
    1414//
    1515
     
    367367                return nullptr;
    368368        }
     369
     370        namespace {
     371                /// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
     372                struct ImpurityDetector : public WithShortCircuiting {
     373                        ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {}
     374
     375                        void previsit( const ApplicationExpr * appExpr ) {
     376                                visit_children = false;
     377                                if ( const DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     378                                        if ( function->linkage == LinkageSpec::Intrinsic ) {
     379                                                if ( function->name == "*?" || function->name == "?[?]" ) {
     380                                                        // intrinsic dereference, subscript are pure, but need to recursively look for impurity
     381                                                        visit_children = true;
     382                                                        return;
     383                                                }
     384                                        }
     385                                }
     386                                maybeImpure = true;
     387                        }
     388                        void previsit( const UntypedExpr * ) { maybeImpure = true; visit_children = false; }
     389                        void previsit( const UniqueExpr * ) {
     390                                if ( ignoreUnique ) {
     391                                        // bottom out at unique expression.
     392                                        // The existence of a unique expression doesn't change the purity of an expression.
     393                                        // That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
     394                                        visit_children = false;
     395                                        return;
     396                                }
     397                        }
     398
     399                        bool maybeImpure = false;
     400                        bool ignoreUnique;
     401                };
     402        } // namespace
     403
     404        bool maybeImpure( const Expression * expr ) {
     405                PassVisitor<ImpurityDetector> detector( false );
     406                expr->accept( detector );
     407                return detector.pass.maybeImpure;
     408        }
     409
     410        bool maybeImpureIgnoreUnique( const Expression * expr ) {
     411                PassVisitor<ImpurityDetector> detector( true );
     412                expr->accept( detector );
     413                return detector.pass.maybeImpure;
     414        }
    369415} // namespace Tuples
    370416
  • src/Tuples/Tuples.cc

    r74ec742 r29d8c02  
    1010// Created On       : Mon Jun 17 14:41:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon May 16 16:15:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Tue Jun 18  9:31:00 2019
     13// Update Count     : 1
    1414//
    1515
     
    1818#include "AST/Pass.hpp"
    1919#include "AST/LinkageSpec.hpp"
    20 #include "Common/PassVisitor.h"
    2120#include "InitTweak/InitTweak.h"
    2221
     
    2423
    2524namespace {
    26         /// Checks if impurity (read: side-effects) may exist in a piece of code.
    27         /// Currently gives a very crude approximation, wherein any function
    28         /// call expression means the code may be impure.
    29         struct ImpurityDetector_old : public WithShortCircuiting {
    30                 bool const ignoreUnique;
    31                 bool maybeImpure;
    32 
    33                 ImpurityDetector_old( bool ignoreUnique ) :
    34                         ignoreUnique( ignoreUnique ), maybeImpure( false )
    35                 {}
    36 
    37                 void previsit( const ApplicationExpr * appExpr ) {
    38                         visit_children = false;
    39                         if ( const DeclarationWithType * function =
    40                                         InitTweak::getFunction( appExpr ) ) {
    41                                 if ( function->linkage == LinkageSpec::Intrinsic ) {
    42                                         if ( function->name == "*?" || function->name == "?[?]" ) {
    43                                                 // intrinsic dereference, subscript are pure,
    44                                                 // but need to recursively look for impurity
    45                                                 visit_children = true;
    46                                                 return;
    47                                         }
    48                                 }
    49                         }
    50                         maybeImpure = true;
    51                 }
    52 
    53                 void previsit( const UntypedExpr * ) {
    54                         maybeImpure = true;
    55                         visit_children = false;
    56                 }
    57 
    58                 void previsit( const UniqueExpr * ) {
    59                         if ( ignoreUnique ) {
    60                                 // bottom out at unique expression.
    61                                 // The existence of a unique expression doesn't change the purity of an expression.
    62                                 // That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
    63                                 visit_children = false;
    64                                 return;
    65                         }
    66                 }
    67         };
    68 
    69         bool detectImpurity( const Expression * expr, bool ignoreUnique ) {
    70                 PassVisitor<ImpurityDetector_old> detector( ignoreUnique );
    71                 expr->accept( detector );
    72                 return detector.pass.maybeImpure;
    73         }
    74 
    7525        /// Determines if impurity (read: side-effects) may exist in a piece of code. Currently gives
    7626        /// a very crude approximation, wherein any function call expression means the code may be
    7727        /// impure.
    7828    struct ImpurityDetector : public ast::WithShortCircuiting {
    79                 bool result = false;
     29                bool maybeImpure = false;
    8030
    8131                void previsit( ast::ApplicationExpr const * appExpr ) {
     
    8636                                }
    8737                        }
    88                         result = true; visit_children = false;
     38                        maybeImpure = true; visit_children = false;
    8939                }
    9040                void previsit( ast::UntypedExpr const * ) {
    91                         result = true; visit_children = false;
     41                        maybeImpure = true; visit_children = false;
    9242                }
    9343        };
    94 
    9544        struct ImpurityDetectorIgnoreUnique : public ImpurityDetector {
    9645                using ImpurityDetector::previsit;
     
    9948                }
    10049        };
     50
     51        template<typename Detector>
     52        bool detectImpurity( const ast::Expr * expr ) {
     53                ast::Pass<Detector> detector;
     54                expr->accept( detector );
     55                return detector.core.maybeImpure;
     56        }
    10157} // namespace
    10258
    10359bool maybeImpure( const ast::Expr * expr ) {
    104         return ast::Pass<ImpurityDetector>::read( expr );
     60        return detectImpurity<ImpurityDetector>( expr );
    10561}
    10662
    10763bool maybeImpureIgnoreUnique( const ast::Expr * expr ) {
    108         return ast::Pass<ImpurityDetectorIgnoreUnique>::read( expr );
    109 }
    110 
    111 bool maybeImpure( const Expression * expr ) {
    112         return detectImpurity( expr, false );
    113 }
    114 
    115 bool maybeImpureIgnoreUnique( const Expression * expr ) {
    116         return detectImpurity( expr, true );
     64        return detectImpurity<ImpurityDetectorIgnoreUnique>( expr );
    11765}
    11866
  • src/Tuples/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Mon May 17 15:00:00 2022
    14 ## Update Count     : 3
     12## Last Modified By : Henry Xue
     13## Last Modified On : Mon Aug 23 15:36:09 2021
     14## Update Count     : 2
    1515###############################################################################
    1616
     
    2424        Tuples/Tuples.h
    2525
     26
    2627SRC += $(SRC_TUPLES)
    27 
    2828SRCDEMANGLE += $(SRC_TUPLES)
  • src/Validate/Autogen.cpp

    r74ec742 r29d8c02  
    350350                name,
    351351                std::move( type_params ),
    352                 std::move( assertions ),
    353352                std::move( params ),
    354353                std::move( returns ),
     
    361360                // Auto-generated routines are inline to avoid conflicts.
    362361                ast::Function::Specs( ast::Function::Inline ) );
     362        decl->assertions = std::move( assertions );
    363363        decl->fixUniqueId();
    364364        return decl;
  • src/Validate/ForallPointerDecay.cpp

    r74ec742 r29d8c02  
    1010// Created On       : Tue Dec  7 16:15:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Sat Apr 23 13:10:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Fri Feb 11 10:59:00 2022
     13// Update Count     : 0
    1414//
    1515
     
    237237}
    238238
    239 std::vector<ast::ptr<ast::DeclWithType>> expandAssertions(
    240                 std::vector<ast::ptr<ast::DeclWithType>> const & old ) {
    241         return TraitExpander::expandAssertions( old );
    242 }
    243 
    244239} // namespace Validate
    245240
  • src/Validate/ForallPointerDecay.hpp

    r74ec742 r29d8c02  
    1010// Created On       : Tue Dec  7 16:15:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Sat Apr 23 13:13:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Tue Dec  8 11:50:00 2021
     13// Update Count     : 0
    1414//
    1515
    1616#pragma once
    1717
    18 #include <vector>
    19 #include "AST/Node.hpp"
    20 
    2118namespace ast {
    22         class DeclWithType;
    2319        class TranslationUnit;
    2420}
     
    3127void decayForallPointers( ast::TranslationUnit & transUnit );
    3228
    33 /// Expand all traits in an assertion list.
    34 std::vector<ast::ptr<ast::DeclWithType>> expandAssertions(
    35         std::vector<ast::ptr<ast::DeclWithType>> const & );
    36 
    3729}
    3830
  • src/Validate/GenericParameter.cpp

    r74ec742 r29d8c02  
    1010// Created On       : Fri Mar 21 10:02:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 22 16:43:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Wed Apr 13 10:09:00 2022
     13// Update Count     : 0
    1414//
    1515
     
    2222#include "AST/TranslationUnit.hpp"
    2323#include "AST/Type.hpp"
    24 #include "Validate/NoIdSymbolTable.hpp"
    2524
    2625namespace Validate {
     
    139138// --------------------------------------------------------------------------
    140139
    141 struct TranslateDimensionCore :
    142                 public WithNoIdSymbolTable, public ast::WithGuards {
     140// A SymbolTable that only has the operations used in the Translate Dimension
     141// pass. More importantly, it doesn't have some methods that should no be
     142// called by the Pass template (lookupId and addId).
     143class NoIdSymbolTable {
     144        ast::SymbolTable base;
     145public:
     146#       define FORWARD_X( func, types_and_names, just_names ) \
     147        inline auto func types_and_names -> decltype( base.func just_names ) { \
     148                return base.func just_names ; \
     149        }
     150#       define FORWARD_0( func )         FORWARD_X( func, (),             () )
     151#       define FORWARD_1( func, type )   FORWARD_X( func, (type arg),     (arg) )
     152#       define FORWARD_2( func, t0, t1 ) FORWARD_X( func, (t0 a0, t1 a1), (a0, a1) )
     153
     154        FORWARD_0( enterScope )
     155        FORWARD_0( leaveScope )
     156        FORWARD_1( lookupType, const std::string &        )
     157        FORWARD_1( addType   , const ast::NamedTypeDecl * )
     158        FORWARD_1( addStruct , const ast::StructDecl *    )
     159        FORWARD_1( addEnum   , const ast::EnumDecl *      )
     160        FORWARD_1( addUnion  , const ast::UnionDecl *     )
     161        FORWARD_1( addTrait  , const ast::TraitDecl *     )
     162        FORWARD_2( addWith   , const std::vector< ast::ptr<ast::Expr> > &, const ast::Decl * )
     163};
     164
     165struct TranslateDimensionCore : public ast::WithGuards {
     166        NoIdSymbolTable symtab;
    143167
    144168        // SUIT: Struct- or Union- InstType
  • src/Validate/module.mk

    r74ec742 r29d8c02  
    1010## Author           : Rob Schluntz
    1111## Created On       : Fri Jul 27 10:10:10 2018
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tue May 17 14:59:00 2022
    14 ## Update Count     : 3
     12## Last Modified By : Rob Schluntz
     13## Last Modified On : Fri Jul 27 10:10:26 2018
     14## Update Count     : 2
    1515###############################################################################
    1616
    1717SRC_VALIDATE = \
    18         Validate/FindSpecialDecls.cc \
    19         Validate/FindSpecialDecls.h
    20 
    21 SRC += $(SRC_VALIDATE) \
    2218        Validate/Autogen.cpp \
    2319        Validate/Autogen.hpp \
    2420        Validate/CompoundLiteral.cpp \
    2521        Validate/CompoundLiteral.hpp \
    26         Validate/EliminateTypedef.cpp \
    27         Validate/EliminateTypedef.hpp \
    28         Validate/FindSpecialDeclsNew.cpp \
    29         Validate/FixQualifiedTypes.cpp \
    30         Validate/FixQualifiedTypes.hpp \
    3122        Validate/ForallPointerDecay.cpp \
    3223        Validate/ForallPointerDecay.hpp \
     
    3526        Validate/HandleAttributes.cc \
    3627        Validate/HandleAttributes.h \
    37         Validate/HoistStruct.cpp \
    38         Validate/HoistStruct.hpp \
    3928        Validate/InitializerLength.cpp \
    4029        Validate/InitializerLength.hpp \
    4130        Validate/LabelAddressFixer.cpp \
    4231        Validate/LabelAddressFixer.hpp \
    43         Validate/NoIdSymbolTable.hpp \
    4432        Validate/ReturnCheck.cpp \
    45         Validate/ReturnCheck.hpp
     33        Validate/ReturnCheck.hpp \
     34        Validate/FindSpecialDeclsNew.cpp \
     35        Validate/FindSpecialDecls.cc \
     36        Validate/FindSpecialDecls.h
    4637
     38SRC += $(SRC_VALIDATE)
    4739SRCDEMANGLE += $(SRC_VALIDATE)
  • src/Virtual/module.mk

    r74ec742 r29d8c02  
    1111## Created On       : Tus Jul 25 10:18:00 2017
    1212## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tus May 17 14:59:00 2022
    14 ## Update Count     : 1
     13## Last Modified On : Tus Jul 25 10:18:00 2017
     14## Update Count     : 0
    1515###############################################################################
    1616
    17 SRC += \
    18         Virtual/ExpandCasts.cc \
    19         Virtual/ExpandCasts.h \
    20         Virtual/Tables.cc \
    21         Virtual/Tables.h
     17SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h \
     18        Virtual/Tables.cc Virtual/Tables.h
     19
     20SRCDEMANGLE += Virtual/Tables.cc
  • src/main.cc

    r74ec742 r29d8c02  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 29  9:52:00 2022
    13 // Update Count     : 673
     12// Last Modified On : Wed Apr 13 11:11:00 2022
     13// Update Count     : 672
    1414//
    1515
     
    7070#include "ResolvExpr/Resolver.h"            // for resolve
    7171#include "SymTab/Validate.h"                // for validate
    72 #include "SymTab/ValidateType.h"            // for linkReferenceToTypes
    7372#include "SynTree/LinkageSpec.h"            // for Spec, Cforall, Intrinsic
    7473#include "SynTree/Declaration.h"            // for Declaration
     
    7675#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    7776#include "Validate/Autogen.hpp"             // for autogenerateRoutines
     77#include "Validate/GenericParameter.hpp"    // for fillGenericParameters, tr...
     78#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     79#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
    7880#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    79 #include "Validate/EliminateTypedef.hpp"    // for eliminateTypedef
    80 #include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
    81 #include "Validate/FixQualifiedTypes.hpp"   // for fixQualifiedTypes
    82 #include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
    83 #include "Validate/GenericParameter.hpp"    // for fillGenericParameters, tr...
    84 #include "Validate/HoistStruct.hpp"         // for hoistStruct
    8581#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
    8682#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
     
    332328                // add the assignment statement after the initialization of a type parameter
    333329                PASS( "Validate-A", SymTab::validate_A( translationUnit ) );
    334 
    335                 // Must happen before auto-gen, because it uses the sized flag.
    336                 PASS( "Link Reference To Types", SymTab::linkReferenceToTypes( translationUnit ) );
     330                PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
    337331
    338332                CodeTools::fillLocations( translationUnit );
     
    348342
    349343                        forceFillCodeLocations( transUnit );
    350 
    351                         // Must happen after Link References To Types,
    352                         // because aggregate members are accessed.
    353                         PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
    354 
    355                         PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
    356                         PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
    357344
    358345                        // Check as early as possible. Can't happen before
     
    451438                        translationUnit = convert( move( transUnit ) );
    452439                } else {
    453                         PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
    454440                        PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
    455441                        PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
  • tests/.expect/forall.txt

    r74ec742 r29d8c02  
    1 forall.cfa:244:25: warning: Compiled
     1forall.cfa:242:25: warning: Compiled
  • tests/forall.cfa

    r74ec742 r29d8c02  
    1 //
     1// 
    22// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 //
    7 // forall.cfa --
    8 //
     6// 
     7// forall.cfa -- 
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Wed May  9 08:48:15 2018
     
    1212// Last Modified On : Sat Jun  5 10:06:08 2021
    1313// Update Count     : 36
    14 //
     14// 
    1515
    1616void g1() {
     
    4545}
    4646
    47 // commented this out since it is not clearly meaningful
    48 // and not really representable in the ast
    49 // typedef forall ( T ) int (* f)( int );
     47typedef forall ( T ) int (* f)( int );
    5048
    5149forall( T )
     
    172170}
    173171
    174 forall( T | { T ?+?( T, T ); } ) forall( S | { T ?+?( T, S ); } )
     172forall( T | { T ?+?( T, T ); } ) forall( S | { T ?+?( T, S ); } ) 
    175173struct XW { T t; };
    176174XW(int,int) xww;
  • tests/include/.expect/includes.nast.txt

    r74ec742 r29d8c02  
    1 include/includes.cfa:169:25: warning: Compiled
     1include/includes.cfa:153:25: warning: Compiled
  • tests/include/includes.cfa

    r74ec742 r29d8c02  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 16:36:44 2022
    13 // Update Count     : 776
     12// Last Modified On : Thu Feb  3 22:06:07 2022
     13// Update Count     : 774
    1414//
    1515
     
    3232#include <crypt.h>
    3333#include <ctype.h>
    34 #if __has_include( "curses.h" )
    35 #include <curses.h>                                                                             // may not be installed
    36 #endif
     34//#include <curses.h>                                                                           // may not be installed
    3735#include <dirent.h>
    3836#include <dlfcn.h>
     
    4341#include <errno.h>
    4442#include <error.h>
    45 #if __has_include( "eti.h" )
    46 #include <eti.h>                                                                                // may not be installed, comes with ncurses
    47 #endif
     43//#include <eti.h>                                                                              // may not be installed, comes with ncurses
    4844#include <execinfo.h>
    4945#include <expat.h>
     
    5450#include <fmtmsg.h>
    5551#include <fnmatch.h>
    56 #if __has_include( "form.h" )
    57 #include <form.h>                                                                               // may not be installed, comes with ncurses
    58 #endif
     52//#include <form.h>                                                                             // may not be installed, comes with ncurses
    5953#include <fstab.h>
    6054#include <fts.h>
     
    8478#include <mcheck.h>
    8579#include <memory.h>
    86 #if __has_include( "menu.h" )
    87 #include <menu.h>                                                                               // may not be installed, comes with ncurses
    88 #endif
     80//#include <menu.h>                                                                             // may not be installed, comes with ncurses
    8981#include <mntent.h>
    9082#include <monetary.h>
    9183#include <mqueue.h>
    92 #if __has_include( "ncurses_dll.h" )
    93 #include <ncurses_dll.h>                                                                // may not be installed, comes with ncurses
    94 #endif
     84//#include <ncurses_dll.h>                                                              // may not be installed, comes with ncurses
    9585#include <netdb.h>
    9686#include <nl_types.h>
    9787#include <nss.h>
    9888#include <obstack.h>
    99 #if __has_include( "panel.h" )
    100 #include <panel.h>                                                                              // may not be installed, comes with ncurses
    101 #endif
     89//#include <panel.h>                                                                            // may not be installed, comes with ncurses
    10290#include <paths.h>
    10391#include <poll.h>
     
    130118#include <syslog.h>
    131119#include <tar.h>
    132 #if __has_include( "term.h" )
    133 #include <term.h>                                                                               // may not be installed, comes with ncurses
    134 #include <termcap.h>                                                                    // may not be installed, comes with ncurses
    135 #endif
     120//#include <term.h>                                                                             // may not be installed, comes with ncurses
     121//#include <termcap.h>                                                                  // may not be installed, comes with ncurses
    136122#include <termio.h>
    137123#include <termios.h>
     
    145131#include <ucontext.h>
    146132#include <ulimit.h>
    147 #if __has_include( "unctrl.h" )
    148 #include <unctrl.h>                                                                             // may not be installed, comes with ncurses
    149 #endif
     133//#include <unctrl.h>                                                                           // may not be installed, comes with ncurses
    150134#include <unistd.h>
    151135#include <utime.h>
  • tests/pybin/settings.py

    r74ec742 r29d8c02  
    201201        global output_width
    202202        output_width = max(map(lambda t: len(t.target()), tests))
    203         # 35 is the maximum width of the name field before we get line wrapping.
    204         output_width = min(output_width, 35)
  • tests/pybin/test_run.py

    r74ec742 r29d8c02  
    4343                return os.path.normpath( os.path.join(settings.BUILDDIR, self.path, self.name) )
    4444
    45         def format_target(self, width):
    46                 target = self.target()
    47                 length = len(target)
    48                 if length < width:
    49                         return '{0:{width}}'.format(target, width=width)
    50                 elif length == width:
    51                         return target
    52                 else:
    53                         return '...' + target[3-width:]
    54 
    5545        @staticmethod
    5646        def valid_name(name):
  • tests/test.py

    r74ec742 r29d8c02  
    132132        parser.add_argument('--install', help='Run all tests based on installed binaries or tree binaries', type=comma_separated(yes_no), default='no')
    133133        parser.add_argument('--continue', help='When multiple specifications are passed (debug/install/arch), sets whether or not to continue if the last specification failed', type=yes_no, default='yes', dest='continue_')
    134         parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180)
     134        parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=120)
    135135        parser.add_argument('--global-timeout', help='Maximum cumulative duration in seconds after the ALL tests are considered to have timed out', type=int, default=7200)
    136136        parser.add_argument('--timeout-with-gdb', help='Instead of killing the command when it times out, orphan it and print process id to allow gdb to attach', type=yes_no, default="no")
     
    252252        try :
    253253                # print formated name
    254                 name_txt = t.format_target(width=settings.output_width) + '  '
     254                name_txt = '{0:{width}}  '.format(t.target(), width=settings.output_width)
    255255
    256256                retcode, error, duration = run_single_test(t)
  • tests/unified_locking/.expect/locks.txt

    r74ec742 r29d8c02  
    2323Start Test 12: locked condition variable wait/notify with front()
    2424Done Test 12
    25 Start Test 13: fast block lock and fast cond var single wait/notify
    26 Done Test 13
  • tests/unified_locking/locks.cfa

    r74ec742 r29d8c02  
    1818condition_variable( linear_backoff_then_block_lock ) c_l;
    1919
    20 fast_block_lock f;
    21 fast_cond_var( fast_block_lock ) f_c_f;
    22 
    2320thread T_C_M_WS1 {};
    2421
     
    10299                }
    103100                unlock(l);
    104         }
    105 }
    106 
    107 thread T_F_C_F_WS1 {};
    108 
    109 void main( T_F_C_F_WS1 & this ) {
    110         for (unsigned int i = 0; i < num_times; i++) {
    111                 lock(f);
    112                 if(empty(f_c_f) && i != num_times - 1) {
    113                         wait(f_c_f,f);
    114                 }else{
    115                         notify_one(f_c_f);
    116                         unlock(f);
    117                 }
    118101        }
    119102}
     
    339322        }
    340323        printf("Done Test 12\n");
    341 
    342         printf("Start Test 13: fast block lock and fast cond var single wait/notify\n");
    343         {
    344                 T_F_C_F_WS1 t1[2];
    345         }
    346         printf("Done Test 13\n");
    347        
    348 }
     324}
Note: See TracChangeset for help on using the changeset viewer.