Changes in / [139775e:55acc3a]


Ignore:
Files:
2 added
10 deleted
46 edited

Legend:

Unmodified
Added
Removed
  • benchmark/readyQ/cycle.cfa

    r139775e r55acc3a  
    11#include "rq_bench.hfa"
    22
    3 struct Partner {
     3thread Partner {
     4        Partner * partner;
    45        unsigned long long count;
    5         unsigned long long blocks;
    6         bench_sem self;
    7         bench_sem * next;
    86};
    97
    108void ?{}( Partner & this ) {
    11         this.count = this.blocks = 0;
     9        ((thread&)this){ bench_cluster };
    1210}
    1311
    14 thread BThrd {
    15         Partner & partner;
    16 };
    17 
    18 void ?{}( BThrd & this, Partner * partner ) {
    19         ((thread&)this){ bench_cluster };
    20         &this.partner = partner;
    21 }
    22 
    23 void ^?{}( BThrd & mutex this ) {}
    24 
    25 void main( BThrd & thrd ) with(thrd.partner) {
    26         count = 0;
     12void main( Partner & this ) {
     13        this.count = 0;
    2714        for() {
    28                 blocks += wait( self );
    29                 post( *next );
    30                 count ++;
     15                park();
     16                unpark( *this.partner );
     17                this.count ++;
    3118                if( clock_mode && stop) break;
    32                 if(!clock_mode && count >= stop_count) break;
     19                if(!clock_mode && this.count >= stop_count) break;
    3320        }
    3421
     
    4633        {
    4734                unsigned long long global_counter = 0;
    48                 unsigned long long global_blocks  = 0;
    4935                unsigned tthreads = nthreads * ring_size;
    5036                Time start, end;
     
    5238                {
    5339                        threads_left = tthreads;
    54                         BThrd * threads[tthreads];
    55                         Partner thddata[tthreads];
     40                        Partner threads[tthreads];
    5641                        for(i; tthreads) {
    5742                                unsigned pi = (i + nthreads) % tthreads;
    58                                 thddata[i].next = &thddata[pi].self;
    59                         }
    60                         for(int i = 0; i < tthreads; i++) {
    61                                 threads[i] = malloc();
    62                                 (*threads[i]){ &thddata[i] };
     43                                threads[i].partner = &threads[pi];
    6344                        }
    6445                        printf("Starting\n");
     
    6849
    6950                        for(i; nthreads) {
    70                                 post( thddata[i].self );
     51                                unpark( threads[i] );
    7152                        }
    7253                        wait(start, is_tty);
     
    7758
    7859                        for(i; tthreads) {
    79                                 Partner & partner = join( *threads[i] ).partner;
    80                                 global_counter += partner.count;
    81                                 global_blocks  += partner.blocks;
    82                                 delete(threads[i]);
     60                                global_counter += join( threads[i] ).count;
    8361                        }
    8462                }
    8563
    86                 printf("Duration (ms)        : %'ld\n", (end - start)`dms);
    87                 printf("Number of processors : %'d\n", nprocs);
    88                 printf("Number of threads    : %'d\n", tthreads);
    89                 printf("Cycle size (# thrds) : %'d\n", ring_size);
    90                 printf("Total Operations(ops): %'15llu\n", global_counter);
    91                 printf("Total blocks         : %'15llu\n", global_blocks);
    92                 printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / (end - start)`ds);
    93                 printf("ns per ops           : %'18.2lf\n", (end - start)`dns / global_counter);
    94                 printf("Ops per threads      : %'15llu\n", global_counter / tthreads);
    95                 printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
    96                 printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`ds);
    97                 printf("ns per ops/procs     : %'18.2lf\n", (end - start)`dns / (global_counter / nprocs));
     64                printf("Duration (ms)       : %'ld\n", (end - start)`ms);
     65                printf("Number of processors: %'d\n", nprocs);
     66                printf("Number of threads   : %'d\n", tthreads);
     67                printf("Cycle size (# thrds): %'d\n", ring_size);
     68                printf("Yields per second   : %'18.2lf\n", ((double)global_counter) / (end - start)`s);
     69                printf("ns per yields       : %'18.2lf\n", ((double)(end - start)`ns) / global_counter);
     70                printf("Total yields        : %'15llu\n", global_counter);
     71                printf("Yields per threads  : %'15llu\n", global_counter / tthreads);
     72                printf("Yields per procs    : %'15llu\n", global_counter / nprocs);
     73                printf("Yields/sec/procs    : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s);
     74                printf("ns per yields/procs : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs));
    9875                fflush(stdout);
    9976        }
  • benchmark/readyQ/cycle.cpp

    r139775e r55acc3a  
    1 
    2 #include "rq_bench.hpp"
    3 
    4 struct Partner {
    5         unsigned long long count  = 0;
    6         unsigned long long blocks = 0;
    7         bench_sem self;
    8         bench_sem * next;
    9 };
    10 
    11 void partner_main( Partner * self ) {
    12         self->count = 0;
    13         for(;;) {
    14                 self->blocks += self->self.wait();
    15                 self->next->post();
    16                 self->count ++;
    17                 if( clock_mode && stop) break;
    18                 if(!clock_mode && self->count >= stop_count) break;
    19         }
    20 
    21         __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST);
    22 }
    23 
    24 int main(int argc, char * argv[]) {
    25         unsigned ring_size = 2;
    26         option_t opt[] = {
    27                 BENCH_OPT,
    28                 { 'r', "ringsize", "Number of threads in a cycle", ring_size }
    29         };
    30         BENCH_OPT_PARSE("cforall cycle benchmark");
    31 
    32         {
    33                 unsigned long long global_counter = 0;
    34                 unsigned long long global_blocks  = 0;
    35                 unsigned tthreads = nthreads * ring_size;
    36                 uint64_t start, end;
    37                 FibreInit(1, nprocs);
    38                 {
    39                         threads_left = tthreads;
    40                         Fibre * threads[tthreads];
    41                         Partner thddata[tthreads];
    42                         for(int i = 0; i < tthreads; i++) {
    43                                 unsigned pi = (i + nthreads) % tthreads;
    44                                 thddata[i].next = &thddata[pi].self;
    45                         }
    46                         for(int i = 0; i < tthreads; i++) {
    47                                 threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(partner_main), &thddata[i] );
    48                         }
    49                         printf("Starting\n");
    50 
    51                         bool is_tty = isatty(STDOUT_FILENO);
    52                         start = getTimeNsec();
    53 
    54                         for(int i = 0; i < nthreads; i++) {
    55                                 thddata[i].self.post();
    56                         }
    57                         wait(start, is_tty);
    58 
    59                         stop = true;
    60                         end = getTimeNsec();
    61                         printf("\nDone\n");
    62 
    63                         for(int i = 0; i < tthreads; i++) {
    64                                 fibre_join( threads[i], nullptr );
    65                                 global_counter += thddata[i].count;
    66                                 global_blocks  += thddata[i].blocks;
    67                         }
    68                 }
    69 
    70                 printf("Duration (ms)        : %'ld\n", to_miliseconds(end - start));
    71                 printf("Number of processors : %'d\n", nprocs);
    72                 printf("Number of threads    : %'d\n", tthreads);
    73                 printf("Cycle size (# thrds) : %'d\n", ring_size);
    74                 printf("Total Operations(ops): %'15llu\n", global_counter);
    75                 printf("Total blocks         : %'15llu\n", global_blocks);
    76                 printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / to_fseconds(end - start));
    77                 printf("ns per ops           : %'18.2lf\n", ((double)(end - start)) / global_counter);
    78                 printf("Ops per threads      : %'15llu\n", global_counter / tthreads);
    79                 printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
    80                 printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / to_fseconds(end - start));
    81                 printf("ns per ops/procs     : %'18.2lf\n", ((double)(end - start)) / (global_counter / nprocs));
    82                 fflush(stdout);
    83         }
    84 
    85         return 0;
    86 }
  • benchmark/readyQ/cycle.go

    r139775e r55acc3a  
    22
    33import (
     4        "bufio"
    45        "flag"
    56        "fmt"
     7        "os"
     8        "runtime"
    69        "sync/atomic"
    710        "time"
     
    912        "golang.org/x/text/message"
    1013)
     14
     15var clock_mode bool
     16var threads_left int64
     17var stop int32
     18var duration float64
     19var stop_count uint64
     20
     21func fflush(f *bufio.Writer) {
     22        defer f.Flush()
     23        f.Write([]byte("\r"))
     24}
     25
     26func wait(start time.Time, is_tty bool) {
     27        f := bufio.NewWriter(os.Stdout)
     28        tdur := time.Duration(duration)
     29        for true {
     30                time.Sleep(100 * time.Millisecond)
     31                end := time.Now()
     32                delta := end.Sub(start)
     33                if is_tty {
     34                        fmt.Printf(" %.1f",delta.Seconds())
     35                        fflush(f)
     36                }
     37                if clock_mode && delta >= (tdur * time.Second) {
     38                        break
     39                } else if !clock_mode && atomic.LoadInt64(&threads_left) == 0 {
     40                        break
     41                }
     42        }
     43}
    1144
    1245func partner(result chan uint64, mine chan int, next chan int) {
     
    2558
    2659func main() {
     60        var nprocs int
     61        var nthreads int
    2762        var ring_size int
    2863
     64        nprocsOpt := flag.Int("p", 1, "The number of processors")
     65        nthreadsOpt := flag.Int("t", 1, "The number of threads")
    2966        ring_sizeOpt := flag.Int("r", 2, "The number of threads per cycles")
     67        durationOpt := flag.Float64("d", 0, "Duration of the experiment in seconds")
     68        stopOpt := flag.Uint64("i", 0, "Duration of the experiment in iterations")
    3069
    31         bench_init()
     70        flag.Parse()
    3271
     72        nprocs = *nprocsOpt
     73        nthreads = *nthreadsOpt
    3374        ring_size = *ring_sizeOpt
     75        duration = *durationOpt
     76        stop_count = *stopOpt
    3477
     78        if duration > 0 && stop_count > 0 {
     79                panic(fmt.Sprintf("--duration and --iterations cannot be used together\n"))
     80        } else if duration > 0 {
     81                clock_mode = true
     82                stop_count = 0xFFFFFFFFFFFFFFFF
     83                fmt.Printf("Running for %f seconds\n", duration)
     84        } else if stop_count > 0 {
     85                clock_mode = false
     86                fmt.Printf("Running for %d iterations\n", stop_count)
     87        } else {
     88                duration = 5
     89                clock_mode = true
     90                fmt.Printf("Running for %f seconds\n", duration)
     91        }
     92
     93        runtime.GOMAXPROCS(nprocs)
    3594        tthreads := nthreads * ring_size
    3695        threads_left = int64(tthreads)
     
    67126
    68127        p := message.NewPrinter(language.English)
    69         p.Printf("Duration (ms)        : %f\n", delta.Seconds());
    70         p.Printf("Number of processors : %d\n", nprocs);
    71         p.Printf("Number of threads    : %d\n", tthreads);
    72         p.Printf("Cycle size (# thrds) : %d\n", ring_size);
    73         p.Printf("Total Operations(ops): %15d\n", global_counter)
    74         p.Printf("Ops per second       : %18.2f\n", float64(global_counter) / delta.Seconds())
    75         p.Printf("ns per ops           : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
    76         p.Printf("Ops per threads      : %15d\n", global_counter / uint64(tthreads))
    77         p.Printf("Ops per procs        : %15d\n", global_counter / uint64(nprocs))
    78         p.Printf("Ops/sec/procs        : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
    79         p.Printf("ns per ops/procs    : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
     128        p.Printf("Duration (ms)       : %f\n", delta.Seconds());
     129        p.Printf("Number of processors: %d\n", nprocs);
     130        p.Printf("Number of threads   : %d\n", tthreads);
     131        p.Printf("Cycle size (# thrds): %d\n", ring_size);
     132        p.Printf("Yields per second   : %18.2f\n", float64(global_counter) / delta.Seconds())
     133        p.Printf("ns per yields       : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
     134        p.Printf("Total yields        : %15d\n", global_counter)
     135        p.Printf("Yields per threads  : %15d\n", global_counter / uint64(tthreads))
     136        p.Printf("Yields per procs    : %15d\n", global_counter / uint64(nprocs))
     137        p.Printf("Yields/sec/procs    : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
     138        p.Printf("ns per yields/procs : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
    80139
    81140}
  • benchmark/readyQ/rq_bench.hfa

    r139775e r55acc3a  
    6666
    6767void ^?{}( BenchCluster & this ) {
    68         adelete( this.procs );
     68        adelete( this.nprocs, this.procs );
    6969        ^(this.cl){};
    7070}
     
    8787        }
    8888}
    89 
    90 struct __attribute__((aligned(128))) bench_sem {
    91         struct $thread * volatile ptr;
    92 };
    93 
    94 static inline {
    95         void  ?{}(bench_sem & this) {
    96                 this.ptr = 0p;
    97         }
    98 
    99         void ^?{}(bench_sem & this) {}
    100 
    101         bool wait(bench_sem & this) {
    102                 for() {
    103                         struct $thread * expected = this.ptr;
    104                         if(expected == 1p) {
    105                                 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    106                                         return false;
    107                                 }
    108                         }
    109                         else {
    110                                 /* paranoid */ verify( expected == 0p );
    111                                 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    112                                         park();
    113                                         return true;
    114                                 }
    115                         }
    116 
    117                 }
    118         }
    119 
    120         bool post(bench_sem & this) {
    121                 for() {
    122                         struct $thread * expected = this.ptr;
    123                         if(expected == 1p) return false;
    124                         if(expected == 0p) {
    125                                 if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    126                                         return false;
    127                                 }
    128                         }
    129                         else {
    130                                 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    131                                         unpark( expected );
    132                                         return true;
    133                                 }
    134                         }
    135                 }
    136         }
    137 }
  • benchmark/rmit.py

    r139775e r55acc3a  
    1010
    1111import argparse
    12 import datetime
    1312import itertools
    1413import os
     
    102101        return nopts
    103102
    104 def actions_eta(actions):
    105         time = 0
    106         for a in actions:
    107                 i = 0
    108                 while i < len(a):
    109                         if a[i] == '-d':
    110                                 i += 1
    111                                 if i != len(a):
    112                                         time += int(a[i])
    113                         i += 1
    114         return time
    115 
    116103if __name__ == "__main__":
    117104        # ================================================================================
     
    173160        # ================================================================================
    174161        # Prepare to run
    175 
    176         # find expected time
    177         time = actions_eta(actions)
    178         print("Running {} trials{}".format(len(actions), "" if time == 0 else " (expecting to take {}".format(str(datetime.timedelta(seconds=int(time)))) ))
    179 
    180162        random.shuffle(actions)
     163
     164        print("Running {} trials".format(len(actions)))
    181165        result = []
    182166
     
    225209                        d = [r[0], r[1]]
    226210                        for k in headers[2:]:
    227                                 try:
    228                                         d.append(r[2][k])
    229                                 except:
    230                                         d.append(0.0)
     211                                d.append(r[2][k])
    231212
    232213                        data.append(d)
  • configure.ac

    r139775e r55acc3a  
    2828# New AST toggling support
    2929AH_TEMPLATE([CFA_USE_NEW_AST],[Sets whether or not to use the new-ast, this is adefault value and can be overrided by --old-ast and --new-ast])
    30 DEFAULT_NEW_AST="False"
    3130AC_ARG_ENABLE(new-ast,
    3231        [  --enable-new-ast     whether or not to use new ast as the default AST algorithm],
    3332        [case "${enableval}" in
    34                 yes) newast=true ; DEFAULT_NEW_AST="True"  ;;
    35                 no)  newast=false; DEFAULT_NEW_AST="False" ;;
     33                yes) newast=true ;;
     34                no)  newast=false ;;
    3635                *) AC_MSG_ERROR([bad value ${enableval} for --enable-new-ast]) ;;
    3736        esac],[newast=false])
    3837AC_DEFINE_UNQUOTED([CFA_USE_NEW_AST], $newast)
    39 AC_SUBST(DEFAULT_NEW_AST)
    4038
    4139#==============================================================================
  • libcfa/src/concurrency/alarm.cfa

    r139775e r55acc3a  
    4545//=============================================================================================
    4646
    47 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period) with( this ) {
     47void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period ) with( this ) {
    4848        this.thrd = thrd;
    4949        this.alarm = alarm;
    5050        this.period = period;
    5151        set = false;
    52         type = User;
     52        kernel_alarm = false;
    5353}
    5454
     
    5858        this.period = period;
    5959        set = false;
    60         type = Kernel;
    61 }
    62 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) with( this ) {
    63         this.thrd = thrd;
    64         this.alarm = alarm;
    65         this.period = period;
    66         this.callback = callback;
    67         set = false;
    68         type = Callback;
     60        kernel_alarm = true;
    6961}
    7062
  • libcfa/src/concurrency/alarm.hfa

    r139775e r55acc3a  
    3939//=============================================================================================
    4040
    41 enum alarm_type{ Kernel = 0, User = 1, Callback = 2 };
    42 
    43 struct alarm_node_t;
    44 
    45 typedef void (*Alarm_Callback)(alarm_node_t & );
    46 
    4741struct alarm_node_t {
    4842        Time alarm;                             // time when alarm goes off
     
    5650        };
    5751
    58         Alarm_Callback callback;
    59 
    6052        bool set                :1;             // whether or not the alarm has be registered
    61         enum alarm_type type;           // true if this is not a user defined alarm
     53        bool kernel_alarm       :1;             // true if this is not a user defined alarm
    6254};
    6355DLISTED_MGD_IMPL_OUT(alarm_node_t)
     
    6557void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period );
    6658void ?{}( alarm_node_t & this, processor   * proc, Time alarm, Duration period );
    67 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback );
    6859void ^?{}( alarm_node_t & this );
    6960
  • libcfa/src/concurrency/coroutine.cfa

    r139775e r55acc3a  
    134134void ^?{}($coroutine& this) {
    135135        if(this.state != Halted && this.state != Start && this.state != Primed) {
    136                 $coroutine * src = active_coroutine();
     136                $coroutine * src = TL_GET( this_thread )->curr_cor;
    137137                $coroutine * dst = &this;
    138138
     
    240240
    241241        struct $coroutine * __cfactx_cor_finish(void) {
    242                 struct $coroutine * cor = active_coroutine();
     242                struct $coroutine * cor = kernelTLS.this_thread->curr_cor;
    243243
    244244                if(cor->state == Primed) {
  • libcfa/src/concurrency/coroutine.hfa

    r139775e r55acc3a  
    6363void prime(T & cor);
    6464
    65 static inline struct $coroutine * active_coroutine() { return active_thread()->curr_cor; }
     65static inline struct $coroutine * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
    6666
    6767//-----------------------------------------------------------------------------
     
    8787
    8888        // set new coroutine that task is executing
    89         active_thread()->curr_cor = dst;
     89        TL_GET( this_thread )->curr_cor = dst;
    9090
    9191        // context switch to specified coroutine
     
    112112                // will also migrate which means this value will
    113113                // stay in syn with the TLS
    114                 $coroutine * src = active_coroutine();
     114                $coroutine * src = TL_GET( this_thread )->curr_cor;
    115115
    116116                assertf( src->last != 0,
     
    138138        // will also migrate which means this value will
    139139        // stay in syn with the TLS
    140         $coroutine * src = active_coroutine();
     140        $coroutine * src = TL_GET( this_thread )->curr_cor;
    141141        $coroutine * dst = get_coroutine(cor);
    142142
    143143        if( unlikely(dst->context.SP == 0p) ) {
    144                 active_thread()->curr_cor = dst;
     144                TL_GET( this_thread )->curr_cor = dst;
    145145                __stack_prepare(&dst->stack, 65000);
    146146                __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine);
    147                 active_thread()->curr_cor = src;
     147                TL_GET( this_thread )->curr_cor = src;
    148148        }
    149149
     
    175175        // will also migrate which means this value will
    176176        // stay in syn with the TLS
    177         $coroutine * src = active_coroutine();
     177        $coroutine * src = TL_GET( this_thread )->curr_cor;
    178178
    179179        // not resuming self ?
  • libcfa/src/concurrency/exception.cfa

    r139775e r55acc3a  
    7272        void * stop_param;
    7373
    74         struct $thread * this_thread = active_thread();
     74        struct $thread * this_thread = TL_GET( this_thread );
    7575        if ( &this_thread->self_cor != this_thread->curr_cor ) {
    7676                struct $coroutine * cor = this_thread->curr_cor;
  • libcfa/src/concurrency/io.cfa

    r139775e r55acc3a  
    7676
    7777        static inline bool next( __leaderlock_t & this ) {
    78                 /* paranoid */ verify( ! __preemption_enabled() );
     78                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    7979                struct $thread * nextt;
    8080                for() {
     
    168168        // This is NOT thread-safe
    169169        static [int, bool] __drain_io( & struct __io_data ring ) {
    170                 /* paranoid */ verify( ! __preemption_enabled() );
     170                /* paranoid */ verify( !kernelTLS.preemption_state.enabled );
    171171
    172172                unsigned to_submit = 0;
     
    404404                                        return;
    405405                                }
    406                                 /* paranoid */ verify( ! __preemption_enabled() );
     406                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    407407                                __STATS__( true,
    408408                                        io.submit_q.leader += 1;
     
    442442
    443443                        #if defined(LEADER_LOCK)
    444                                 /* paranoid */ verify( ! __preemption_enabled() );
     444                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    445445                                next(ring.submit_q.submit_lock);
    446446                        #else
  • libcfa/src/concurrency/io/setup.cfa

    r139775e r55acc3a  
    149149                id.full_proc = false;
    150150                id.id = doregister(&id);
    151                 __cfaabi_tls.this_proc_id = &id;
    152151                __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" );
    153152
     
    179178                                __cfadbg_print_safe(io_core, "Kernel I/O : Unparking io poller %p\n", io_ctx);
    180179                                #if !defined( __CFA_NO_STATISTICS__ )
    181                                         __cfaabi_tls.this_stats = io_ctx->self.curr_cluster->stats;
     180                                        kernelTLS.this_stats = io_ctx->self.curr_cluster->stats;
    182181                                #endif
    183                                 post( io_ctx->sem );
     182                                __post( io_ctx->sem, &id );
    184183                        }
    185184                }
     
    236235                        if( thrd.state == Ready || thrd.preempted != __NO_PREEMPTION ) {
    237236
    238                                 ready_schedule_lock();
     237                                ready_schedule_lock( (struct __processor_id_t *)active_processor() );
    239238
    240239                                        // This is the tricky case
     
    254253                                        thrd.preempted = __NO_PREEMPTION;
    255254
    256                                 ready_schedule_unlock();
     255                                ready_schedule_unlock( (struct __processor_id_t *)active_processor() );
    257256
    258257                                // Pretend like the thread was blocked all along
     
    276275                        }
    277276                } else {
    278                         post( this.thrd.sem );
     277                        unpark( &thrd );
    279278                }
    280279
  • libcfa/src/concurrency/kernel.cfa

    r139775e r55acc3a  
    108108static $thread * __next_thread_slow(cluster * this);
    109109static void __run_thread(processor * this, $thread * dst);
    110 static void __wake_one(cluster * cltr);
     110static void __wake_one(struct __processor_id_t * id, cluster * cltr);
    111111
    112112static void push  (__cluster_idles & idles, processor & proc);
     
    122122        // Because of a bug, we couldn't initialized the seed on construction
    123123        // Do it here
    124         __cfaabi_tls.rand_seed ^= rdtscl();
    125         __cfaabi_tls.ready_rng.fwd_seed = 25214903917_l64u * (rdtscl() ^ (uintptr_t)&runner);
     124        kernelTLS.rand_seed ^= rdtscl();
     125        kernelTLS.ready_rng.fwd_seed = 25214903917_l64u * (rdtscl() ^ (uintptr_t)&runner);
    126126        __tls_rand_advance_bck();
    127127
     
    217217                // and it make sense for it to be set in all other cases except here
    218218                // fake it
    219                 __cfaabi_tls.this_thread = mainThread;
     219                kernelTLS.this_thread = mainThread;
    220220        }
    221221
     
    230230// from the processor coroutine to the target thread
    231231static void __run_thread(processor * this, $thread * thrd_dst) {
    232         /* paranoid */ verify( ! __preemption_enabled() );
     232        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    233233        /* paranoid */ verifyf( thrd_dst->state == Ready || thrd_dst->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", thrd_dst->state, thrd_dst->preempted);
    234234        /* paranoid */ verifyf( thrd_dst->link.next == 0p, "Expected null got %p", thrd_dst->link.next );
     
    247247
    248248                // Update global state
    249                 kernelTLS().this_thread = thrd_dst;
    250 
    251                 /* paranoid */ verify( ! __preemption_enabled() );
    252                 /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
     249                kernelTLS.this_thread = thrd_dst;
     250
     251                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     252                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    253253                /* paranoid */ verify( thrd_dst->context.SP );
    254254                /* paranoid */ verify( thrd_dst->state != Halted );
     
    267267                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
    268268                /* paranoid */ verify( thrd_dst->context.SP );
    269                 /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
    270                 /* paranoid */ verify( ! __preemption_enabled() );
     269                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
     270                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    271271
    272272                // Reset global state
    273                 kernelTLS().this_thread = 0p;
     273                kernelTLS.this_thread = 0p;
    274274
    275275                // We just finished running a thread, there are a few things that could have happened.
     
    282282                if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
    283283                        // The thread was preempted, reschedule it and reset the flag
    284                         __schedule_thread( thrd_dst );
     284                        __schedule_thread( (__processor_id_t*)this, thrd_dst );
    285285                        break RUNNING;
    286286                }
     
    315315        proc_cor->state = Active;
    316316
    317         /* paranoid */ verify( ! __preemption_enabled() );
     317        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    318318}
    319319
    320320// KERNEL_ONLY
    321321void returnToKernel() {
    322         /* paranoid */ verify( ! __preemption_enabled() );
    323         $coroutine * proc_cor = get_coroutine(kernelTLS().this_processor->runner);
    324         $thread * thrd_src = kernelTLS().this_thread;
     322        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     323        $coroutine * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
     324        $thread * thrd_src = kernelTLS.this_thread;
    325325
    326326        #if !defined(__CFA_NO_STATISTICS__)
    327                 struct processor * last_proc = kernelTLS().this_processor;
     327                struct processor * last_proc = kernelTLS.this_processor;
    328328        #endif
    329329
     
    345345
    346346        #if !defined(__CFA_NO_STATISTICS__)
    347                 if(last_proc != kernelTLS().this_processor) {
     347                if(last_proc != kernelTLS.this_processor) {
    348348                        __tls_stats()->ready.threads.migration++;
    349349                }
    350350        #endif
    351351
    352         /* paranoid */ verify( ! __preemption_enabled() );
     352        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    353353        /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too small.\n", thrd_src );
    354354        /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too large.\n", thrd_src );
     
    358358// Scheduler routines
    359359// KERNEL ONLY
    360 void __schedule_thread( $thread * thrd ) {
    361         /* paranoid */ verify( ! __preemption_enabled() );
     360void __schedule_thread( struct __processor_id_t * id, $thread * thrd ) {
    362361        /* paranoid */ verify( thrd );
    363362        /* paranoid */ verify( thrd->state != Halted );
    364         /* paranoid */ verify( kernelTLS().this_proc_id );
     363        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    365364        /* paranoid */ #if defined( __CFA_WITH_VERIFY__ )
    366365        /* paranoid */  if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
     
    375374        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    376375
    377         ready_schedule_lock();
     376        ready_schedule_lock  ( id );
    378377                push( thrd->curr_cluster, thrd );
    379                 __wake_one(thrd->curr_cluster);
    380         ready_schedule_unlock();
    381 
    382         /* paranoid */ verify( ! __preemption_enabled() );
     378                __wake_one(id, thrd->curr_cluster);
     379        ready_schedule_unlock( id );
     380
     381        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    383382}
    384383
    385384// KERNEL ONLY
    386385static inline $thread * __next_thread(cluster * this) with( *this ) {
    387         /* paranoid */ verify( ! __preemption_enabled() );
    388         /* paranoid */ verify( kernelTLS().this_proc_id );
    389 
    390         ready_schedule_lock();
     386        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     387
     388        ready_schedule_lock  ( (__processor_id_t*)kernelTLS.this_processor );
    391389                $thread * thrd = pop( this );
    392         ready_schedule_unlock();
    393 
    394         /* paranoid */ verify( kernelTLS().this_proc_id );
    395         /* paranoid */ verify( ! __preemption_enabled() );
     390        ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor );
     391
     392        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    396393        return thrd;
    397394}
     
    399396// KERNEL ONLY
    400397static inline $thread * __next_thread_slow(cluster * this) with( *this ) {
    401         /* paranoid */ verify( ! __preemption_enabled() );
    402         /* paranoid */ verify( kernelTLS().this_proc_id );
    403 
    404         ready_schedule_lock();
     398        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     399
     400        ready_schedule_lock  ( (__processor_id_t*)kernelTLS.this_processor );
    405401                $thread * thrd = pop_slow( this );
    406         ready_schedule_unlock();
    407 
    408         /* paranoid */ verify( kernelTLS().this_proc_id );
    409         /* paranoid */ verify( ! __preemption_enabled() );
     402        ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor );
     403
     404        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    410405        return thrd;
    411406}
    412407
    413 void unpark( $thread * thrd ) {
    414         if( !thrd ) return;
    415 
     408// KERNEL ONLY unpark with out disabling interrupts
     409void __unpark(  struct __processor_id_t * id, $thread * thrd ) {
    416410        int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
    417411        switch(old_ticket) {
     
    423417                        /* paranoid */ verify( thrd->state == Blocked );
    424418
    425                         {
    426                                 /* paranoid */ verify( publicTLS_get(this_proc_id) );
    427                                 bool full = publicTLS_get(this_proc_id)->full_proc;
    428                                 if(full) disable_interrupts();
    429 
    430                                 /* paranoid */ verify( ! __preemption_enabled() );
    431 
    432                                 // Wake lost the race,
    433                                 __schedule_thread( thrd );
    434 
    435                                 /* paranoid */ verify( ! __preemption_enabled() );
    436 
    437                                 if(full) enable_interrupts( __cfaabi_dbg_ctx );
    438                                 /* paranoid */ verify( publicTLS_get(this_proc_id) );
    439                         }
    440 
     419                        // Wake lost the race,
     420                        __schedule_thread( id, thrd );
    441421                        break;
    442422                default:
     
    446426}
    447427
     428void unpark( $thread * thrd ) {
     429        if( !thrd ) return;
     430
     431        disable_interrupts();
     432        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd );
     433        enable_interrupts( __cfaabi_dbg_ctx );
     434}
     435
    448436void park( void ) {
    449         /* paranoid */ verify( __preemption_enabled() );
     437        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    450438        disable_interrupts();
    451         /* paranoid */ verify( ! __preemption_enabled() );
    452         /* paranoid */ verify( kernelTLS().this_thread->preempted == __NO_PREEMPTION );
     439        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     440        /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION );
    453441
    454442        returnToKernel();
    455443
    456         /* paranoid */ verify( ! __preemption_enabled() );
     444        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    457445        enable_interrupts( __cfaabi_dbg_ctx );
    458         /* paranoid */ verify( __preemption_enabled() );
     446        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    459447
    460448}
     
    465453        // Should never return
    466454        void __cfactx_thrd_leave() {
    467                 $thread * thrd = active_thread();
     455                $thread * thrd = TL_GET( this_thread );
    468456                $monitor * this = &thrd->self_mon;
    469457
     
    474462
    475463                thrd->state = Halted;
    476                 if( TICKET_RUNNING != thrd->ticket ) { abort( "Thread terminated with pending unpark" ); }
     464
    477465                if( thrd != this->owner || this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); }
    478466
    479467                // Leave the thread
    480                 /* paranoid */ verify( ! __preemption_enabled() );
     468                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    481469                returnToKernel();
    482470                abort();
     
    488476// KERNEL ONLY
    489477bool force_yield( __Preemption_Reason reason ) {
    490         /* paranoid */ verify( __preemption_enabled() );
     478        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    491479        disable_interrupts();
    492         /* paranoid */ verify( ! __preemption_enabled() );
    493 
    494         $thread * thrd = kernelTLS().this_thread;
     480        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     481
     482        $thread * thrd = kernelTLS.this_thread;
    495483        /* paranoid */ verify(thrd->state == Active);
    496484
     
    506494        }
    507495
    508         /* paranoid */ verify( ! __preemption_enabled() );
     496        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    509497        enable_interrupts_noPoll();
    510         /* paranoid */ verify( __preemption_enabled() );
     498        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    511499
    512500        return preempted;
     
    517505//=============================================================================================
    518506// Wake a thread from the front if there are any
    519 static void __wake_one(cluster * this) {
    520         /* paranoid */ verify( ! __preemption_enabled() );
    521         /* paranoid */ verify( ready_schedule_islocked() );
     507static void __wake_one(struct __processor_id_t * id, cluster * this) {
     508        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     509        /* paranoid */ verify( ready_schedule_islocked( id ) );
    522510
    523511        // Check if there is a sleeping processor
     
    537525        #endif
    538526
    539         /* paranoid */ verify( ready_schedule_islocked() );
    540         /* paranoid */ verify( ! __preemption_enabled() );
     527        /* paranoid */ verify( ready_schedule_islocked( id ) );
     528        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    541529
    542530        return;
     
    548536
    549537        disable_interrupts();
    550                 /* paranoid */ verify( ! __preemption_enabled() );
     538                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    551539                post( this->idle );
    552540        enable_interrupts( __cfaabi_dbg_ctx );
     
    554542
    555543static void push  (__cluster_idles & this, processor & proc) {
    556         /* paranoid */ verify( ! __preemption_enabled() );
     544        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    557545        lock( this );
    558546                this.idle++;
     
    561549                insert_first(this.list, proc);
    562550        unlock( this );
    563         /* paranoid */ verify( ! __preemption_enabled() );
     551        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    564552}
    565553
    566554static void remove(__cluster_idles & this, processor & proc) {
    567         /* paranoid */ verify( ! __preemption_enabled() );
     555        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    568556        lock( this );
    569557                this.idle--;
     
    572560                remove(proc);
    573561        unlock( this );
    574         /* paranoid */ verify( ! __preemption_enabled() );
     562        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    575563}
    576564
     
    616604        }
    617605
    618         return __cfaabi_tls.this_thread;
     606        return kernelTLS.this_thread;
    619607}
    620608
     
    641629
    642630int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) {
    643         return get_coroutine(kernelTLS().this_thread) == get_coroutine(mainThread) ? 4 : 2;
     631        return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2;
    644632}
    645633
     
    673661        if ( count < 0 ) {
    674662                // queue current task
    675                 append( waiting, active_thread() );
     663                append( waiting, kernelTLS.this_thread );
    676664
    677665                // atomically release spin lock and block
     
    723711                void __cfaabi_dbg_record_lock(__spinlock_t & this, const char prev_name[]) {
    724712                        this.prev_name = prev_name;
    725                         this.prev_thrd = kernelTLS().this_thread;
     713                        this.prev_thrd = kernelTLS.this_thread;
    726714                }
    727715        }
     
    740728                this.print_halts = true;
    741729        }
    742 
    743         void print_stats_now( cluster & this, int flags ) {
    744                 __print_stats( this.stats, this.print_stats, true, this.name, (void*)&this );
    745         }
    746730#endif
    747731// Local Variables: //
  • libcfa/src/concurrency/kernel.hfa

    r139775e r55acc3a  
    275275static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
    276276
    277 static inline struct processor * active_processor() { return publicTLS_get( this_processor ); } // UNSAFE
    278 static inline struct cluster   * active_cluster  () { return publicTLS_get( this_processor )->cltr; }
     277static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE
     278static inline struct cluster   * active_cluster  () { return TL_GET( this_processor )->cltr; }
    279279
    280280#if !defined(__CFA_NO_STATISTICS__)
    281         void print_stats_now( cluster & this, int flags );
    282 
    283281        static inline void print_stats_at_exit( cluster & this, int flags ) {
    284282                this.print_stats |= flags;
  • libcfa/src/concurrency/kernel/fwd.hfa

    r139775e r55acc3a  
    3535        extern "Cforall" {
    3636                extern __attribute__((aligned(128))) thread_local struct KernelThreadData {
    37                         struct $thread          * volatile this_thread;
    38                         struct processor        * volatile this_processor;
    39                         struct __processor_id_t * volatile this_proc_id;
    40                         struct __stats_t        * volatile this_stats;
     37                        struct $thread    * volatile this_thread;
     38                        struct processor  * volatile this_processor;
     39                        struct __stats_t  * volatile this_stats;
    4140
    4241                        struct {
     
    5554                                uint64_t bck_seed;
    5655                        } ready_rng;
    57                 } __cfaabi_tls __attribute__ ((tls_model ( "initial-exec" )));
     56                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    5857
    59                 extern bool __preemption_enabled();
    6058
    61                 static inline KernelThreadData & kernelTLS( void ) {
    62                         /* paranoid */ verify( ! __preemption_enabled() );
    63                         return __cfaabi_tls;
    64                 }
    65 
    66                 extern uintptr_t __cfatls_get( unsigned long int member );
    67                 // #define publicTLS_get( member ) ((typeof(__cfaabi_tls.member))__cfatls_get( __builtin_offsetof(KernelThreadData, member) ))
    68                 #define publicTLS_get( member ) (__cfaabi_tls.member)
    69                 // extern forall(otype T) T __cfatls_get( T * member, T value );
    70                 // #define publicTLS_set( member, value ) __cfatls_set( (typeof(member)*)__builtin_offsetof(KernelThreadData, member), value );
    7159
    7260                static inline uint64_t __tls_rand() {
    7361                        #if defined(__SIZEOF_INT128__)
    74                                 return __lehmer64( kernelTLS().rand_seed );
     62                                return __lehmer64( kernelTLS.rand_seed );
    7563                        #else
    76                                 return __xorshift64( kernelTLS().rand_seed );
     64                                return __xorshift64( kernelTLS.rand_seed );
    7765                        #endif
    7866                }
     
    8674                static inline unsigned __tls_rand_fwd() {
    8775
    88                         kernelTLS().ready_rng.fwd_seed = (A * kernelTLS().ready_rng.fwd_seed + C) & (M - 1);
    89                         return kernelTLS().ready_rng.fwd_seed >> D;
     76                        kernelTLS.ready_rng.fwd_seed = (A * kernelTLS.ready_rng.fwd_seed + C) & (M - 1);
     77                        return kernelTLS.ready_rng.fwd_seed >> D;
    9078                }
    9179
    9280                static inline unsigned __tls_rand_bck() {
    93                         unsigned int r = kernelTLS().ready_rng.bck_seed >> D;
    94                         kernelTLS().ready_rng.bck_seed = AI * (kernelTLS().ready_rng.bck_seed - C) & (M - 1);
     81                        unsigned int r = kernelTLS.ready_rng.bck_seed >> D;
     82                        kernelTLS.ready_rng.bck_seed = AI * (kernelTLS.ready_rng.bck_seed - C) & (M - 1);
    9583                        return r;
    9684                }
     
    10391
    10492                static inline void __tls_rand_advance_bck(void) {
    105                         kernelTLS().ready_rng.bck_seed = kernelTLS().ready_rng.fwd_seed;
     93                        kernelTLS.ready_rng.bck_seed = kernelTLS.ready_rng.fwd_seed;
    10694                }
    10795        }
    10896
     97        #if 0 // def __ARM_ARCH
     98                // function prototypes are only really used by these macros on ARM
     99                void disable_global_interrupts();
     100                void enable_global_interrupts();
    109101
     102                #define TL_GET( member ) ( { __typeof__( kernelTLS.member ) target; \
     103                        disable_global_interrupts(); \
     104                        target = kernelTLS.member; \
     105                        enable_global_interrupts(); \
     106                        target; } )
     107                #define TL_SET( member, value ) disable_global_interrupts(); \
     108                        kernelTLS.member = value; \
     109                        enable_global_interrupts();
     110        #else
     111                #define TL_GET( member ) kernelTLS.member
     112                #define TL_SET( member, value ) kernelTLS.member = value;
     113        #endif
    110114
    111115        extern void disable_interrupts();
     
    116120                extern void park( void );
    117121                extern void unpark( struct $thread * this );
    118                 static inline struct $thread * active_thread () {
    119                         struct $thread * t = publicTLS_get( this_thread );
    120                         /* paranoid */ verify( t );
    121                         return t;
    122                 }
     122                static inline struct $thread * active_thread () { return TL_GET( this_thread ); }
    123123
    124124                extern bool force_yield( enum __Preemption_Reason );
     
    139139                #if !defined(__CFA_NO_STATISTICS__)
    140140                        static inline struct __stats_t * __tls_stats() {
    141                                 /* paranoid */ verify( ! __preemption_enabled() );
    142                                 /* paranoid */ verify( kernelTLS().this_stats );
    143                                 return kernelTLS().this_stats;
     141                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     142                                /* paranoid */ verify( kernelTLS.this_stats );
     143                                return kernelTLS.this_stats;
    144144                        }
    145145
  • libcfa/src/concurrency/kernel/startup.cfa

    r139775e r55acc3a  
    118118//-----------------------------------------------------------------------------
    119119// Global state
    120 thread_local struct KernelThreadData __cfaabi_tls __attribute__ ((tls_model ( "initial-exec" ))) @= {
     120thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) @= {
    121121        NULL,                                                                                           // cannot use 0p
    122         NULL,
    123122        NULL,
    124123        NULL,
     
    156155// Kernel boot procedures
    157156static void __kernel_startup(void) {
    158         /* paranoid */ verify( ! __preemption_enabled() );
     157        verify( ! kernelTLS.preemption_state.enabled );
    159158        __cfadbg_print_safe(runtime_core, "Kernel : Starting\n");
    160159
     
    212211
    213212        //initialize the global state variables
    214         __cfaabi_tls.this_processor = mainProcessor;
    215         __cfaabi_tls.this_proc_id   = (__processor_id_t*)mainProcessor;
    216         __cfaabi_tls.this_thread    = mainThread;
     213        kernelTLS.this_processor = mainProcessor;
     214        kernelTLS.this_thread    = mainThread;
    217215
    218216        #if !defined( __CFA_NO_STATISTICS__ )
    219                 __cfaabi_tls.this_stats = (__stats_t *)& storage_mainProcStats;
    220                 __init_stats( __cfaabi_tls.this_stats );
     217                kernelTLS.this_stats = (__stats_t *)& storage_mainProcStats;
     218                __init_stats( kernelTLS.this_stats );
    221219        #endif
    222220
     
    229227        // Add the main thread to the ready queue
    230228        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    231         __schedule_thread(mainThread);
     229        __schedule_thread((__processor_id_t *)mainProcessor, mainThread);
    232230
    233231        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
    234232        // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that
    235233        // mainThread is on the ready queue when this call is made.
    236         __kernel_first_resume( __cfaabi_tls.this_processor );
     234        __kernel_first_resume( kernelTLS.this_processor );
    237235
    238236
     
    251249        __cfadbg_print_safe(runtime_core, "Kernel : Started\n--------------------------------------------------\n\n");
    252250
    253         /* paranoid */ verify( ! __preemption_enabled() );
     251        verify( ! kernelTLS.preemption_state.enabled );
    254252        enable_interrupts( __cfaabi_dbg_ctx );
    255         /* paranoid */ verify( __preemption_enabled() );
    256 
     253        verify( TL_GET( preemption_state.enabled ) );
    257254}
    258255
     
    263260        mainCluster->io.ctxs = 0p;
    264261
    265         /* paranoid */ verify( __preemption_enabled() );
     262        /* paranoid */ verify( TL_GET( preemption_state.enabled ) );
    266263        disable_interrupts();
    267         /* paranoid */ verify( ! __preemption_enabled() );
     264        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    268265
    269266        __cfadbg_print_safe(runtime_core, "\n--------------------------------------------------\nKernel : Shutting down\n");
     
    273270        // which is currently here
    274271        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    275         __kernel_last_resume( __cfaabi_tls.this_processor );
     272        __kernel_last_resume( kernelTLS.this_processor );
    276273        mainThread->self_cor.state = Halted;
    277274
     
    322319                __stats_t local_stats;
    323320                __init_stats( &local_stats );
    324                 __cfaabi_tls.this_stats = &local_stats;
     321                kernelTLS.this_stats = &local_stats;
    325322        #endif
    326323
    327324        processor * proc = (processor *) arg;
    328         __cfaabi_tls.this_processor = proc;
    329         __cfaabi_tls.this_proc_id   = (__processor_id_t*)proc;
    330         __cfaabi_tls.this_thread    = 0p;
    331         __cfaabi_tls.preemption_state.[enabled, disable_count] = [false, 1];
     325        kernelTLS.this_processor = proc;
     326        kernelTLS.this_thread    = 0p;
     327        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
    332328        // SKULLDUGGERY: We want to create a context for the processor coroutine
    333329        // which is needed for the 2-step context switch. However, there is no reason
     
    341337
    342338        //Set global state
    343         __cfaabi_tls.this_thread = 0p;
     339        kernelTLS.this_thread = 0p;
    344340
    345341        //We now have a proper context from which to schedule threads
     
    371367        $coroutine * dst = get_coroutine(this->runner);
    372368
    373         /* paranoid */ verify( ! __preemption_enabled() );
    374 
    375         __cfaabi_tls.this_thread->curr_cor = dst;
     369        verify( ! kernelTLS.preemption_state.enabled );
     370
     371        kernelTLS.this_thread->curr_cor = dst;
    376372        __stack_prepare( &dst->stack, 65000 );
    377373        __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine);
    378374
    379         /* paranoid */ verify( ! __preemption_enabled() );
     375        verify( ! kernelTLS.preemption_state.enabled );
    380376
    381377        dst->last = &src->self_cor;
     
    395391        /* paranoid */ verify(src->state == Active);
    396392
    397         /* paranoid */ verify( ! __preemption_enabled() );
     393        verify( ! kernelTLS.preemption_state.enabled );
    398394}
    399395
     
    403399        $coroutine * dst = get_coroutine(this->runner);
    404400
    405         /* paranoid */ verify( ! __preemption_enabled() );
    406         /* paranoid */ verify( dst->starter == src );
    407         /* paranoid */ verify( dst->context.SP );
     401        verify( ! kernelTLS.preemption_state.enabled );
     402        verify( dst->starter == src );
     403        verify( dst->context.SP );
    408404
    409405        // SKULLDUGGERY in debug the processors check that the
     
    547543
    548544                P( terminated );
    549                 /* paranoid */ verify( active_processor() != &this);
     545                verify( kernelTLS.this_processor != &this);
    550546        }
    551547
     
    697693#if defined(__CFA_WITH_VERIFY__)
    698694static bool verify_fwd_bck_rng(void) {
    699         __cfaabi_tls.ready_rng.fwd_seed = 25214903917_l64u * (rdtscl() ^ (uintptr_t)&verify_fwd_bck_rng);
     695        kernelTLS.ready_rng.fwd_seed = 25214903917_l64u * (rdtscl() ^ (uintptr_t)&verify_fwd_bck_rng);
    700696
    701697        unsigned values[10];
  • libcfa/src/concurrency/kernel_private.hfa

    r139775e r55acc3a  
    3333}
    3434
    35 void __schedule_thread( $thread * )
     35void __schedule_thread( struct __processor_id_t *, $thread * )
    3636#if defined(NDEBUG) || (!defined(__CFA_DEBUG__) && !defined(__CFA_VERIFY__))
    37         __attribute__((nonnull (1)))
     37        __attribute__((nonnull (2)))
    3838#endif
    3939;
    40 
    41 extern bool __preemption_enabled();
    4240
    4341//release/wake-up the following resources
     
    6563)
    6664
     65// KERNEL ONLY unpark with out disabling interrupts
     66void __unpark( struct __processor_id_t *, $thread * thrd );
     67
    6768#define TICKET_BLOCKED (-1) // thread is blocked
    6869#define TICKET_RUNNING ( 0) // thread is running
    6970#define TICKET_UNBLOCK ( 1) // thread should ignore next block
     71
     72static inline bool __post(single_sem & this, struct __processor_id_t * id) {
     73        for() {
     74                struct $thread * expected = this.ptr;
     75                if(expected == 1p) return false;
     76                if(expected == 0p) {
     77                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     78                                return false;
     79                        }
     80                }
     81                else {
     82                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     83                                __unpark( id, expected );
     84                                return true;
     85                        }
     86                }
     87        }
     88}
    7089
    7190//-----------------------------------------------------------------------------
     
    182201// Reader side : acquire when using the ready queue to schedule but not
    183202//  creating/destroying queues
    184 static inline void ready_schedule_lock(void) with(*__scheduler_lock) {
    185         /* paranoid */ verify( ! __preemption_enabled() );
    186         /* paranoid */ verify( kernelTLS().this_proc_id );
    187 
    188         unsigned iproc = kernelTLS().this_proc_id->id;
    189         /*paranoid*/ verify(data[iproc].handle == kernelTLS().this_proc_id);
     203static inline void ready_schedule_lock( struct __processor_id_t * proc) with(*__scheduler_lock) {
     204        unsigned iproc = proc->id;
     205        /*paranoid*/ verify(data[iproc].handle == proc);
    190206        /*paranoid*/ verify(iproc < ready);
    191207
     
    209225}
    210226
    211 static inline void ready_schedule_unlock(void) with(*__scheduler_lock) {
    212         /* paranoid */ verify( ! __preemption_enabled() );
    213         /* paranoid */ verify( kernelTLS().this_proc_id );
    214 
    215         unsigned iproc = kernelTLS().this_proc_id->id;
    216         /*paranoid*/ verify(data[iproc].handle == kernelTLS().this_proc_id);
     227static inline void ready_schedule_unlock( struct __processor_id_t * proc) with(*__scheduler_lock) {
     228        unsigned iproc = proc->id;
     229        /*paranoid*/ verify(data[iproc].handle == proc);
    217230        /*paranoid*/ verify(iproc < ready);
    218231        /*paranoid*/ verify(data[iproc].lock);
     
    226239
    227240#ifdef __CFA_WITH_VERIFY__
    228         static inline bool ready_schedule_islocked(void) {
    229                 /* paranoid */ verify( ! __preemption_enabled() );
    230                 /*paranoid*/ verify( kernelTLS().this_proc_id );
    231                 __processor_id_t * proc = kernelTLS().this_proc_id;
     241        static inline bool ready_schedule_islocked( struct __processor_id_t * proc) {
    232242                return __scheduler_lock->data[proc->id].owned;
    233243        }
  • libcfa/src/concurrency/locks.cfa

    r139775e r55acc3a  
    1515                this.t = t;
    1616                this.lock = 0p;
    17                 this.listed = false;
    1817        }
    1918
     
    2221                this.info = info;
    2322                this.lock = 0p;
    24                 this.listed = false;
    2523        }
    2624
     
    7674
    7775void lock( blocking_lock & this ) with( this ) {
    78         $thread * thrd = active_thread();
    7976        lock( lock __cfaabi_dbg_ctx2 );
    80         if ( owner == thrd && !multi_acquisition) {
     77        if ( owner == kernelTLS.this_thread && !multi_acquisition) {
    8178                fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead
    82         exit(EXIT_FAILURE);
    83         } else if ( owner != 0p && owner != thrd ) {
    84                 append( blocked_threads, thrd );
     79                exit(EXIT_FAILURE);
     80        } else if ( owner != 0p && owner != kernelTLS.this_thread ) {
     81                append( blocked_threads, kernelTLS.this_thread );
    8582                wait_count++;
    8683                unlock( lock );
    87                 park( );
    88         } else if ( owner == thrd && multi_acquisition ) {
     84                park( __cfaabi_dbg_ctx );
     85        } else if ( owner == kernelTLS.this_thread && multi_acquisition ) {
    8986                recursion_count++;
    9087                unlock( lock );
    9188        } else {
    92                 owner = thrd;
     89                owner = kernelTLS.this_thread;
    9390                recursion_count = 1;
    9491                unlock( lock );
     
    9794
    9895bool try_lock( blocking_lock & this ) with( this ) {
    99         $thread * thrd = active_thread();
    10096        bool ret = false;
    10197        lock( lock __cfaabi_dbg_ctx2 );
    10298        if ( owner == 0p ) {
    103                 owner = thrd;
     99                owner = kernelTLS.this_thread;
    104100                if ( multi_acquisition ) recursion_count = 1;
    105101                ret = true;
    106         } else if ( owner == thrd && multi_acquisition ) {
     102        } else if ( owner == kernelTLS.this_thread && multi_acquisition ) {
    107103                recursion_count++;
    108104                ret = true;
     
    117113                fprintf( stderr, "There was an attempt to release a lock that isn't held" );
    118114                return;
    119         } else if ( strict_owner && active_thread() ) {
     115        } else if ( strict_owner && owner != kernelTLS.this_thread ) {
    120116                fprintf( stderr, "A thread other than the owner attempted to release an owner lock" );
    121117                return;
     
    127123                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    128124                wait_count--;
    129                 unpark( thrd );
     125                unpark( thrd __cfaabi_dbg_ctx2 );
    130126        }
    131127        unlock( lock );
     
    154150                owner = t;
    155151                if ( multi_acquisition ) recursion_count = 1;
    156                 #if !defined( __CFA_NO_STATISTICS__ )
    157                         kernelTLS.this_stats = t->curr_cluster->stats;
    158                 #endif
    159                 unpark( t );
     152                unpark( t __cfaabi_dbg_ctx2 );
    160153                unlock( lock );
    161154        }
     
    166159        if ( owner == 0p ){ // no owner implies lock isn't held
    167160                fprintf( stderr, "A lock that is not held was passed to a synchronization lock" );
    168         } else if ( strict_owner && active_thread() ) {
     161        } else if ( strict_owner && owner != kernelTLS.this_thread ) {
    169162                fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" );
    170163        } else {
     
    173166                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    174167                wait_count--;
    175                 unpark( thrd );
     168                unpark( thrd __cfaabi_dbg_ctx2 );
    176169        }
    177170        unlock( lock );
     
    182175///////////////////////////////////////////////////////////////////
    183176
    184 // This is temporary until an inheritance bug is fixed
     177// In an ideal world this may not be necessary
     178// Is it possible for nominal inheritance to inherit traits??
     179// If that occurs we would avoid all this extra code
    185180
    186181void lock( mutex_lock & this ){
     
    233228
    234229///////////////////////////////////////////////////////////////////
    235 //// condition variable
     230//// Synchronization Locks
    236231///////////////////////////////////////////////////////////////////
    237232
    238233forall(dtype L | is_blocking_lock(L)) {
    239 
    240         void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
    241         // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
    242             lock( cond->lock __cfaabi_dbg_ctx2 );
    243             if ( (*i)->listed ) {                       // is thread on queue
    244                 info_thread(L) * copy = *i;
    245                         remove( cond->blocked_threads, i );              //remove this thread O(1)
    246                         cond->wait_count--;
    247                         if( !copy->lock ) {
    248                                 unlock( cond->lock );
    249                                 #if !defined( __CFA_NO_STATISTICS__ )
    250                                         #warning unprotected access to tls TODO discuss this
    251                                         kernelTLS.this_stats = copy->t->curr_cluster->stats;
    252                                 #endif
    253                                 unpark( copy->t );
    254                 } else {
    255                         add_(*copy->lock, copy->t);                     // call lock's add_
    256                 }
    257             }
    258             unlock( cond->lock );
    259         }
    260 
    261         void alarm_node_wrap_cast( alarm_node_t & a ) {
    262                 timeout_handler( (alarm_node_wrap(L) &)a );
    263         }
    264 
    265         void ?{}( condition_variable(L) & this ){
     234        void ?{}( synchronization_lock(L) & this, bool reacquire_after_signal ){
    266235                this.lock{};
    267236                this.blocked_threads{};
    268237                this.count = 0;
     238                this.reacquire_after_signal = reacquire_after_signal;
     239        }
     240
     241        void ^?{}( synchronization_lock(L) & this ){
     242                // default
     243        }
     244
     245        void ?{}( condition_variable(L) & this ){
     246                ((synchronization_lock(L) &)this){ true };
    269247        }
    270248
     
    273251        }
    274252
    275         void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) {
    276                 this.alarm_node{ thrd, alarm, period, callback };
    277         }
    278 
    279         void ^?{}( alarm_node_wrap(L) & this ) {
    280                 // default
    281         }
    282 
    283         bool notify_one( condition_variable(L) & this ) with( this ) {
     253        void ?{}( thread_queue(L) & this ){
     254                ((synchronization_lock(L) &)this){ false };
     255        }
     256
     257        void ^?{}( thread_queue(L) & this ){
     258                // default
     259        }
     260
     261        bool notify_one( synchronization_lock(L) & this ) with( this ) {
    284262                lock( lock __cfaabi_dbg_ctx2 );
    285263                bool ret = !!blocked_threads;
    286264                info_thread(L) * popped = pop_head( blocked_threads );
    287                 popped->listed = false;
    288265                if(popped != 0p) {
    289                         count--;
    290                         if (popped->lock) {
     266                        if( reacquire_after_signal ){
    291267                                add_(*popped->lock, popped->t);
    292268                        } else {
    293                                 unpark(popped->t);
     269                                unpark(
     270                                        popped->t __cfaabi_dbg_ctx2
     271                                );
    294272                        }
    295273                }
     
    298276        }
    299277
    300         bool notify_all( condition_variable(L) & this ) with(this) {
     278        bool notify_all( synchronization_lock(L) & this ) with(this) {
    301279                lock( lock __cfaabi_dbg_ctx2 );
    302280                bool ret = blocked_threads ? true : false;
    303281                while( blocked_threads ) {
    304282                        info_thread(L) * popped = pop_head( blocked_threads );
    305                         popped->listed = false;
    306283                        if(popped != 0p){
    307                                 count--;
    308                                 if (popped->lock) {
     284                                if( reacquire_after_signal ){
    309285                                        add_(*popped->lock, popped->t);
    310286                                } else {
    311                                         unpark(popped->t);
     287                                        unpark(
     288                                                popped->t __cfaabi_dbg_ctx2
     289                                        );
    312290                                }
    313291                        }
     
    317295        }
    318296
    319         uintptr_t front( condition_variable(L) & this ) with(this) {
    320                 if(!blocked_threads) return NULL;
    321                 return peek(blocked_threads)->info;
    322         }
    323 
    324         bool empty( condition_variable(L) & this ) with(this) {
     297        uintptr_t front( synchronization_lock(L) & this ) with(this) {
     298                return (*peek(blocked_threads)).info;
     299        }
     300
     301        bool empty( synchronization_lock(L) & this ) with(this) {
    325302                return blocked_threads ? false : true;
    326303        }
    327304
    328         int counter( condition_variable(L) & this ) with(this) {
     305        int counter( synchronization_lock(L) & this ) with(this) {
    329306                return count;
    330307        }
    331308
    332         // helper for wait()'s' without a timeout
    333         void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
     309        void queue_info_thread( synchronization_lock(L) & this, info_thread(L) & i ) with(this) {
     310                lock( lock __cfaabi_dbg_ctx2 );
     311                append( blocked_threads, &i );
     312                count++;
     313                unlock( lock );
     314                park( __cfaabi_dbg_ctx );
     315        }
     316
     317
     318        void wait( synchronization_lock(L) & this ) with(this) {
     319                info_thread( L ) i = { kernelTLS.this_thread };
     320                queue_info_thread( this, i );
     321        }
     322
     323        void wait( synchronization_lock(L) & this, uintptr_t info ) with(this) {
     324                info_thread( L ) i = { kernelTLS.this_thread, info };
     325                queue_info_thread( this, i );
     326        }
     327        // I still need to implement the time delay wait routines
     328        bool wait( synchronization_lock(L) & this, Duration duration ) with(this) {
     329                timeval tv = { time(0) };
     330                Time t = { tv };
     331                return wait( this, t + duration );
     332        }
     333
     334        bool wait( synchronization_lock(L) & this, uintptr_t info, Duration duration ) with(this) {
     335                // TODO: ADD INFO
     336                return wait( this, duration );
     337        }
     338
     339        bool wait( synchronization_lock(L) & this, Time time ) with(this) {
     340                return false; //default
     341        }
     342
     343        bool wait( synchronization_lock(L) & this, uintptr_t info, Time time ) with(this) {
     344                // TODO: ADD INFO
     345                return wait( this, time );
     346        }
     347
     348        void queue_info_thread_unlock( synchronization_lock(L) & this, L & l, info_thread(L) & i ) with(this) {
    334349                lock( lock __cfaabi_dbg_ctx2 );
    335350                append( this.blocked_threads, &i );
    336351                count++;
    337                 i.listed = true;
    338                 size_t recursion_count;
    339                 if (i.lock) {
    340                         recursion_count = get_recursion_count(*i.lock);
    341                         remove_( *i.lock );
    342                 }
    343 
    344                 unlock( lock );
    345                 park( ); // blocks here
    346 
    347                 if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking
    348         }
    349 
    350         // helper for wait()'s' with a timeout
    351         void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) {
    352                 lock( lock __cfaabi_dbg_ctx2 );
    353 
    354                 info_thread(L) * queue_ptr = &info;
    355 
    356                 alarm_node_wrap(L) node_wrap = { info.t, t, 0`s, alarm_node_wrap_cast };
    357                 node_wrap.cond = &this;
    358                 node_wrap.i = &queue_ptr;
    359 
    360                 register_self( &node_wrap.alarm_node );
    361 
    362                 append( blocked_threads, queue_ptr );
    363                 info.listed = true;
    364                 count++;
    365 
    366                 size_t recursion_count;
    367                 if (info.lock) {
    368                         recursion_count = get_recursion_count(*info.lock);
    369                         remove_( *info.lock );
    370                 }
    371 
    372                 unlock( lock );
    373                 park();
    374 
    375                 if (info.lock) set_recursion_count(*info.lock, recursion_count);
    376         }
    377 
    378         void wait( condition_variable(L) & this ) with(this) {
    379                 info_thread( L ) i = { active_thread() };
    380                 queue_info_thread( this, i );
    381         }
    382 
    383         void wait( condition_variable(L) & this, uintptr_t info ) with(this) {
    384                 info_thread( L ) i = { active_thread(), info };
    385                 queue_info_thread( this, i );
    386         }
    387 
    388         void wait( condition_variable(L) & this, Duration duration ) with(this) {
    389                 info_thread( L ) i = { active_thread() };
    390                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    391         }
    392 
    393         void wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) {
    394                 info_thread( L ) i = { active_thread(), info };
    395                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    396         }
    397 
    398         void wait( condition_variable(L) & this, Time time ) with(this) {
    399                 info_thread( L ) i = { active_thread() };
    400                 queue_info_thread_timeout(this, i, time);
    401         }
    402 
    403         void wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) {
    404                 info_thread( L ) i = { active_thread(), info };
    405                 queue_info_thread_timeout(this, i, time);
    406         }
    407 
    408         void wait( condition_variable(L) & this, L & l ) with(this) {
    409                 info_thread(L) i = { active_thread() };
    410352                i.lock = &l;
    411                 queue_info_thread( this, i );
    412         }
    413 
    414         void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) {
    415                 info_thread(L) i = { active_thread(), info };
    416                 i.lock = &l;
    417                 queue_info_thread( this, i );
    418         }
    419 
    420         void wait( condition_variable(L) & this, L & l, Duration duration ) with(this) {
    421                 info_thread(L) i = { active_thread() };
    422                 i.lock = &l;
    423                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    424         }
    425 
    426         void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
    427                 info_thread(L) i = { active_thread(), info };
    428                 i.lock = &l;
    429                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    430         }
    431 
    432         void wait( condition_variable(L) & this, L & l, Time time ) with(this) {
    433                 info_thread(L) i = { active_thread() };
    434                 i.lock = &l;
    435                 queue_info_thread_timeout(this, i, time );
    436         }
    437 
    438         void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) {
    439                 info_thread(L) i = { active_thread(), info };
    440                 i.lock = &l;
    441                 queue_info_thread_timeout(this, i, time );
    442         }
    443 }
     353                size_t recursion_count = get_recursion_count(l);
     354                remove_( l );
     355                unlock( lock );
     356                park( __cfaabi_dbg_ctx ); // blocks here
     357
     358                set_recursion_count(l, recursion_count); // resets recursion count here after waking
     359        }
     360
     361        void wait( synchronization_lock(L) & this, L & l ) with(this) {
     362                info_thread(L) i = { kernelTLS.this_thread };
     363                queue_info_thread_unlock( this, l, i );
     364        }
     365
     366        void wait( synchronization_lock(L) & this, L & l, uintptr_t info ) with(this) {
     367                info_thread(L) i = { kernelTLS.this_thread, info };
     368                queue_info_thread_unlock( this, l, i );
     369        }
     370
     371        bool wait( synchronization_lock(L) & this, L & l, Duration duration ) with(this) {
     372                timeval tv = { time(0) };
     373                Time t = { tv };
     374                return wait( this, l, t + duration );
     375        }
     376
     377        bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
     378                // TODO: ADD INFO
     379                return wait( this, l, duration );
     380        }
     381
     382        bool wait( synchronization_lock(L) & this, L & l, Time time ) with(this) {
     383                return false; //default
     384        }
     385
     386        bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Time time ) with(this) {
     387                // TODO: ADD INFO
     388                return wait( this, l, time );
     389        }
     390}
     391
     392///////////////////////////////////////////////////////////////////
     393//// condition lock alternative approach
     394///////////////////////////////////////////////////////////////////
     395
     396// the solution below is less efficient but does not require the lock to have a specific add/remove routine
     397
     398///////////////////////////////////////////////////////////////////
     399//// is_simple_lock
     400///////////////////////////////////////////////////////////////////
     401
     402forall(dtype L | is_simple_lock(L)) {
     403        void ?{}( condition_lock(L) & this ){
     404                // default
     405        }
     406
     407        void ^?{}( condition_lock(L) & this ){
     408                // default
     409        }
     410
     411        bool notify_one( condition_lock(L) & this ) with(this) {
     412                return notify_one( c_var );
     413        }
     414
     415        bool notify_all( condition_lock(L) & this ) with(this) {
     416                return notify_all( c_var );
     417        }
     418
     419        void wait( condition_lock(L) & this, L & l ) with(this) {
     420                lock( m_lock );
     421                size_t recursion = get_recursion_count( l );
     422                unlock( l );
     423                wait( c_var, m_lock );
     424                lock( l );
     425                set_recursion_count( l , recursion );
     426                unlock( m_lock );
     427        }
     428}
  • libcfa/src/concurrency/locks.hfa

    r139775e r55acc3a  
    1 #pragma once
    2 
    31#include <stdbool.h>
    42
     
    1210#include "time.hfa"
    1311#include <sys/time.h>
    14 #include "alarm.hfa"
    1512
    1613///////////////////////////////////////////////////////////////////
     
    3532                info_thread(L) * next;
    3633                L * lock;
    37                 bool listed;                                    // true if info_thread is on queue, false otherwise;
    3834        };
    3935
     
    123119///////////////////////////////////////////////////////////////////
    124120forall(dtype L | is_blocking_lock(L)) {
    125         struct condition_variable {
     121        struct synchronization_lock {
    126122                // Spin lock used for mutual exclusion
    127123                __spinlock_t lock;
     
    132128                // Count of current blocked threads
    133129                int count;
    134         };
     130
     131                // If true threads will reacquire the lock they block on upon waking
     132                bool reacquire_after_signal;
     133        };
     134
     135        struct condition_variable {
     136                inline synchronization_lock(L);
     137        };
     138
     139        struct thread_queue {
     140                inline synchronization_lock(L);
     141        };
     142
     143
     144        void ?{}( synchronization_lock(L) & this, bool multi_acquisition, bool strict_owner );
     145        void ^?{}( synchronization_lock(L) & this );
    135146
    136147        void ?{}( condition_variable(L) & this );
    137148        void ^?{}( condition_variable(L) & this );
    138149
    139         struct alarm_node_wrap {
    140                 alarm_node_t alarm_node;
    141 
    142                 condition_variable(L) * cond;
    143 
    144                 info_thread(L) ** i;
    145         };
    146 
    147         void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback );
    148         void ^?{}( alarm_node_wrap(L) & this );
    149 
    150         void alarm_node_callback( alarm_node_wrap(L) & this );
    151 
    152         void alarm_node_wrap_cast( alarm_node_t & a );
    153 
    154         bool notify_one( condition_variable(L) & this );
    155         bool notify_all( condition_variable(L) & this );
    156 
    157         uintptr_t front( condition_variable(L) & this );
    158 
    159         bool empty( condition_variable(L) & this );
    160         int counter( condition_variable(L) & this );
    161 
    162         // TODO: look into changing timout routines to return bool showing if signalled or woken by kernel
    163         void wait( condition_variable(L) & this );
    164         void wait( condition_variable(L) & this, uintptr_t info );
    165         void wait( condition_variable(L) & this, Duration duration );
    166         void wait( condition_variable(L) & this, uintptr_t info, Duration duration );
    167         void wait( condition_variable(L) & this, Time time );
    168         void wait( condition_variable(L) & this, uintptr_t info, Time time );
    169 
    170         void wait( condition_variable(L) & this, L & l );
    171         void wait( condition_variable(L) & this, L & l, uintptr_t info );
    172         void wait( condition_variable(L) & this, L & l, Duration duration );
    173         void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );
    174         void wait( condition_variable(L) & this, L & l, Time time );
    175         void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time );
     150        void ?{}( thread_queue(L) & this );
     151        void ^?{}( thread_queue(L) & this );
     152
     153        bool notify_one( synchronization_lock(L) & this );
     154        bool notify_all( synchronization_lock(L) & this );
     155
     156        uintptr_t front( synchronization_lock(L) & this );
     157
     158        bool empty( synchronization_lock(L) & this );
     159        int counter( synchronization_lock(L) & this );
     160
     161        // wait functions that are not passed a mutex lock
     162        void wait( synchronization_lock(L) & this );
     163        void wait( synchronization_lock(L) & this, uintptr_t info );
     164        bool wait( synchronization_lock(L) & this, Duration duration );
     165        bool wait( synchronization_lock(L) & this, uintptr_t info, Duration duration );
     166        bool wait( synchronization_lock(L) & this, Time time );
     167        bool wait( synchronization_lock(L) & this, uintptr_t info, Time time );
     168
     169        // wait functions that are passed a lock
     170        bool notify_one( synchronization_lock(L) & this, L & l );
     171        bool notify_all( synchronization_lock(L) & this, L & l );
     172
     173        void wait( synchronization_lock(L) & this, L & l );
     174        void wait( synchronization_lock(L) & this, L & l, uintptr_t info );
     175        bool wait( synchronization_lock(L) & this, L & l, Duration duration );
     176        bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Duration duration );
     177        bool wait( synchronization_lock(L) & this, L & l, Time time );
     178        bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Time time );
    176179}
     180
     181///////////////////////////////////////////////////////////////////
     182//// condition lock alternative approach
     183///////////////////////////////////////////////////////////////////
     184
     185
     186///////////////////////////////////////////////////////////////////
     187//// is_simple_lock
     188///////////////////////////////////////////////////////////////////
     189
     190trait is_simple_lock(dtype L | sized(L)) {
     191        void lock( L & );               // For synchronization locks to use when acquiring
     192        void unlock( L & );    // For synchronization locks to use when releasing
     193        size_t get_recursion_count( L & ); // to get recursion count for cond lock to reset after waking
     194        void set_recursion_count( L &, size_t recursion ); // to set recursion count after getting signalled;
     195};
     196
     197forall(dtype L | is_simple_lock(L)) {
     198        struct condition_lock {
     199                // Spin lock used for mutual exclusion
     200                mutex_lock m_lock;
     201
     202                condition_variable( mutex_lock ) c_var;
     203        };
     204
     205        void ?{}( condition_lock(L) & this );
     206        void ^?{}( condition_lock(L) & this );
     207
     208        bool notify_one( condition_lock(L) & this );
     209        bool notify_all( condition_lock(L) & this );
     210        void wait( condition_lock(L) & this, L & l );
     211}
  • libcfa/src/concurrency/monitor.cfa

    r139775e r55acc3a  
    8282// Enter single monitor
    8383static void __enter( $monitor * this, const __monitor_group_t & group ) {
    84         $thread * thrd = active_thread();
    85 
    8684        // Lock the monitor spinlock
    8785        lock( this->lock __cfaabi_dbg_ctx2 );
     86        // Interrupts disable inside critical section
     87        $thread * thrd = kernelTLS.this_thread;
    8888
    8989        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     
    126126                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    127127
    128                 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     128                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    129129                return;
    130130        }
     
    132132        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    133133
    134         /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     134        /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    135135        /* paranoid */ verify( this->lock.lock );
    136136
     
    141141
    142142static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
    143         $thread * thrd = active_thread();
    144 
    145143        // Lock the monitor spinlock
    146144        lock( this->lock __cfaabi_dbg_ctx2 );
     145        // Interrupts disable inside critical section
     146        $thread * thrd = kernelTLS.this_thread;
    147147
    148148        __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     
    155155                __set_owner( this, thrd );
    156156
    157                 verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     157                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    158158
    159159                unlock( this->lock );
     
    174174                this->owner = thrd;
    175175
    176                 verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     176                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    177177
    178178                unlock( this->lock );
     
    200200
    201201                // Release the next thread
    202                 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     202                /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    203203                unpark( urgent->owner->waiting_thread );
    204204
     
    207207
    208208                // Some one was waiting for us, enter
    209                 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     209                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    210210        }
    211211        else {
     
    224224                park();
    225225
    226                 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     226                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    227227                return;
    228228        }
     
    237237        lock( this->lock __cfaabi_dbg_ctx2 );
    238238
    239         __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", active_thread(), this, this->owner);
    240 
    241         /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     239        __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
     240
     241        /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    242242
    243243        // Leaving a recursion level, decrement the counter
     
    270270void __dtor_leave( $monitor * this, bool join ) {
    271271        __cfaabi_dbg_debug_do(
    272                 if( active_thread() != this->owner ) {
    273                         abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, active_thread(), this->owner);
     272                if( TL_GET( this_thread ) != this->owner ) {
     273                        abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
    274274                }
    275275                if( this->recursion != 1  && !join ) {
     
    287287        /* paranoid */ verify( this->lock.lock );
    288288        /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    289         /* paranoid */ verify( ! __preemption_enabled() );
     289        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    290290        /* paranoid */ verify( thrd->state == Halted );
    291291        /* paranoid */ verify( this->recursion == 1 );
     
    303303        // Unpark the next owner if needed
    304304        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    305         /* paranoid */ verify( ! __preemption_enabled() );
     305        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    306306        /* paranoid */ verify( thrd->state == Halted );
    307307        unpark( new_owner );
     
    327327// Sorts monitors before entering
    328328void ?{}( monitor_guard_t & this, $monitor * m [], __lock_size_t count, fptr_t func ) {
    329         $thread * thrd = active_thread();
     329        $thread * thrd = TL_GET( this_thread );
    330330
    331331        // Store current array
     
    362362
    363363        // Restore thread context
    364         active_thread()->monitors = this.prev;
     364        TL_GET( this_thread )->monitors = this.prev;
    365365}
    366366
     
    369369void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
    370370        // optimization
    371         $thread * thrd = active_thread();
     371        $thread * thrd = TL_GET( this_thread );
    372372
    373373        // Store current array
     
    392392
    393393        // Restore thread context
    394         active_thread()->monitors = this.prev;
     394        TL_GET( this_thread )->monitors = this.prev;
    395395}
    396396
     
    432432
    433433        // Create the node specific to this wait operation
    434         wait_ctx( active_thread(), user_info );
     434        wait_ctx( TL_GET( this_thread ), user_info );
    435435
    436436        // Append the current wait operation to the ones already queued on the condition
     
    483483        //Some more checking in debug
    484484        __cfaabi_dbg_debug_do(
    485                 $thread * this_thrd = active_thread();
     485                $thread * this_thrd = TL_GET( this_thread );
    486486                if ( this.monitor_count != this_thrd->monitors.size ) {
    487487                        abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     
    531531
    532532        // Create the node specific to this wait operation
    533         wait_ctx_primed( active_thread(), 0 )
     533        wait_ctx_primed( kernelTLS.this_thread, 0 )
    534534
    535535        //save contexts
     
    630630
    631631                                // Create the node specific to this wait operation
    632                                 wait_ctx_primed( active_thread(), 0 );
     632                                wait_ctx_primed( kernelTLS.this_thread, 0 );
    633633
    634634                                // Save monitor states
     
    682682
    683683        // Create the node specific to this wait operation
    684         wait_ctx_primed( active_thread(), 0 );
     684        wait_ctx_primed( kernelTLS.this_thread, 0 );
    685685
    686686        monitor_save;
     
    688688
    689689        for( __lock_size_t i = 0; i < count; i++) {
    690                 verify( monitors[i]->owner == active_thread() );
     690                verify( monitors[i]->owner == kernelTLS.this_thread );
    691691        }
    692692
     
    724724static inline void __set_owner( $monitor * monitors [], __lock_size_t count, $thread * owner ) {
    725725        /* paranoid */ verify ( monitors[0]->lock.lock );
    726         /* paranoid */ verifyf( monitors[0]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[0]->owner, monitors[0]->recursion, monitors[0] );
     726        /* paranoid */ verifyf( monitors[0]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[0]->owner, monitors[0]->recursion, monitors[0] );
    727727        monitors[0]->owner        = owner;
    728728        monitors[0]->recursion    = 1;
    729729        for( __lock_size_t i = 1; i < count; i++ ) {
    730730                /* paranoid */ verify ( monitors[i]->lock.lock );
    731                 /* paranoid */ verifyf( monitors[i]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[i]->owner, monitors[i]->recursion, monitors[i] );
     731                /* paranoid */ verifyf( monitors[i]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[i]->owner, monitors[i]->recursion, monitors[i] );
    732732                monitors[i]->owner        = owner;
    733733                monitors[i]->recursion    = 0;
     
    755755                //regardless of if we are ready to baton pass,
    756756                //we need to set the monitor as in use
    757                 /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     757                /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    758758                __set_owner( this,  urgent->owner->waiting_thread );
    759759
     
    764764        // Get the next thread in the entry_queue
    765765        $thread * new_owner = pop_head( this->entry_queue );
    766         /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     766        /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    767767        /* paranoid */ verify( !new_owner || new_owner->link.next == 0p );
    768768        __set_owner( this, new_owner );
     
    892892
    893893static inline void brand_condition( condition & this ) {
    894         $thread * thrd = active_thread();
     894        $thread * thrd = TL_GET( this_thread );
    895895        if( !this.monitors ) {
    896896                // __cfaabi_dbg_print_safe( "Branding\n" );
  • libcfa/src/concurrency/mutex.cfa

    r139775e r55acc3a  
    4040        lock( lock __cfaabi_dbg_ctx2 );
    4141        if( is_locked ) {
    42                 append( blocked_threads, active_thread() );
     42                append( blocked_threads, kernelTLS.this_thread );
    4343                unlock( lock );
    4444                park();
     
    8686        lock( lock __cfaabi_dbg_ctx2 );
    8787        if( owner == 0p ) {
    88                 owner = active_thread();
     88                owner = kernelTLS.this_thread;
    8989                recursion_count = 1;
    9090                unlock( lock );
    9191        }
    92         else if( owner == active_thread() ) {
     92        else if( owner == kernelTLS.this_thread ) {
    9393                recursion_count++;
    9494                unlock( lock );
    9595        }
    9696        else {
    97                 append( blocked_threads, active_thread() );
     97                append( blocked_threads, kernelTLS.this_thread );
    9898                unlock( lock );
    9999                park();
     
    105105        lock( lock __cfaabi_dbg_ctx2 );
    106106        if( owner == 0p ) {
    107                 owner = active_thread();
     107                owner = kernelTLS.this_thread;
    108108                recursion_count = 1;
    109109                ret = true;
    110110        }
    111         else if( owner == active_thread() ) {
     111        else if( owner == kernelTLS.this_thread ) {
    112112                recursion_count++;
    113113                ret = true;
     
    159159void wait(condition_variable & this) {
    160160        lock( this.lock __cfaabi_dbg_ctx2 );
    161         append( this.blocked_threads, active_thread() );
     161        append( this.blocked_threads, kernelTLS.this_thread );
    162162        unlock( this.lock );
    163163        park();
     
    167167void wait(condition_variable & this, L & l) {
    168168        lock( this.lock __cfaabi_dbg_ctx2 );
    169         append( this.blocked_threads, active_thread() );
     169        append( this.blocked_threads, kernelTLS.this_thread );
    170170        unlock(l);
    171171        unlock(this.lock);
  • libcfa/src/concurrency/preemption.cfa

    r139775e r55acc3a  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Nov  6 07:42:13 2020
    13 // Update Count     : 54
     12// Last Modified On : Wed Aug 26 16:46:03 2020
     13// Update Count     : 53
    1414//
    1515
     
    3838// FwdDeclarations : timeout handlers
    3939static void preempt( processor   * this );
    40 static void timeout( $thread * this );
     40static void timeout( struct __processor_id_t * id, $thread * this );
    4141
    4242// FwdDeclarations : Signal handlers
     
    9191
    9292// Tick one frame of the Discrete Event Simulation for alarms
    93 static void tick_preemption(void) {
     93static void tick_preemption( struct __processor_id_t * id ) {
    9494        alarm_node_t * node = 0p;                                                       // Used in the while loop but cannot be declared in the while condition
    9595        alarm_list_t * alarms = &event_kernel->alarms;          // Local copy for ease of reading
     
    105105
    106106                // Check if this is a kernel
    107                 if( node->type == Kernel ) {
     107                if( node->kernel_alarm ) {
    108108                        preempt( node->proc );
    109109                }
    110                 else if( node->type == User ) {
    111                         timeout( node->thrd );
    112                 }
    113110                else {
    114                         node->callback(*node);
     111                        timeout( id, node->thrd );
    115112                }
    116113
     
    163160// Kernel Signal Tools
    164161//=============================================================================================
    165 // In a user-level threading system, there are handful of thread-local variables where this problem occurs on the ARM.
    166 //
    167 // For each kernel thread running user-level threads, there is a flag variable to indicate if interrupts are
    168 // enabled/disabled for that kernel thread. Therefore, this variable is made thread local.
    169 //
    170 // For example, this code fragment sets the state of the "interrupt" variable in thread-local memory.
    171 //
    172 // _Thread_local volatile int interrupts;
    173 // int main() {
    174 //     interrupts = 0; // disable interrupts }
    175 //
    176 // which generates the following code on the ARM
    177 //
    178 // (gdb) disassemble main
    179 // Dump of assembler code for function main:
    180 //    0x0000000000000610 <+0>:  mrs     x1, tpidr_el0
    181 //    0x0000000000000614 <+4>:  mov     w0, #0x0                        // #0
    182 //    0x0000000000000618 <+8>:  add     x1, x1, #0x0, lsl #12
    183 //    0x000000000000061c <+12>: add     x1, x1, #0x10
    184 //    0x0000000000000620 <+16>: str     wzr, [x1]
    185 //    0x0000000000000624 <+20>: ret
    186 //
    187 // The mrs moves a pointer from coprocessor register tpidr_el0 into register x1.  Register w0 is set to 0. The two adds
    188 // increase the TLS pointer with the displacement (offset) 0x10, which is the location in the TSL of variable
    189 // "interrupts".  Finally, 0 is stored into "interrupts" through the pointer in register x1 that points into the
    190 // TSL. Now once x1 has the pointer to the location of the TSL for kernel thread N, it can be be preempted at a
    191 // user-level and the user thread is put on the user-level ready-queue. When the preempted thread gets to the front of
    192 // the user-level ready-queue it is run on kernel thread M. It now stores 0 into "interrupts" back on kernel thread N,
    193 // turning off interrupt on the wrong kernel thread.
    194 //
    195 // On the x86, the following code is generated for the same code fragment.
    196 //
    197 // (gdb) disassemble main
    198 // Dump of assembler code for function main:
    199 //    0x0000000000400420 <+0>:  movl   $0x0,%fs:0xfffffffffffffffc
    200 //    0x000000000040042c <+12>: xor    %eax,%eax
    201 //    0x000000000040042e <+14>: retq
    202 //
    203 // and there is base-displacement addressing used to atomically reset variable "interrupts" off of the TSL pointer in
    204 // register "fs".
    205 //
    206 // Hence, the ARM has base-displacement address for the general purpose registers, BUT not to the coprocessor
    207 // registers. As a result, generating the address for the write into variable "interrupts" is no longer atomic.
    208 //
    209 // Note this problem does NOT occur when just using multiple kernel threads because the preemption ALWAYS restarts the
    210 // thread on the same kernel thread.
    211 //
    212 // The obvious question is why does ARM use a coprocessor register to store the TSL pointer given that coprocessor
    213 // registers are second-class registers with respect to the instruction set. One possible answer is that they did not
    214 // want to dedicate one of the general registers to hold the TLS pointer and there was a free coprocessor register
    215 // available.
    216 
    217 //----------
    218 // special case for preemption since used often
    219 bool __preemption_enabled() {
    220         // create a assembler label before
    221         // marked as clobber all to avoid movement
    222         asm volatile("__cfaasm_check_before:":::"memory");
    223 
    224         // access tls as normal
    225         bool enabled = __cfaabi_tls.preemption_state.enabled;
    226 
    227         // create a assembler label after
    228         // marked as clobber all to avoid movement
    229         asm volatile("__cfaasm_check_after:":::"memory");
    230         return enabled;
    231 }
    232 
    233 //----------
    234 // Get data from the TLS block
    235 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems
    236 uintptr_t __cfatls_get( unsigned long int offset ) {
    237         // create a assembler label before
    238         // marked as clobber all to avoid movement
    239         asm volatile("__cfaasm_get_before:":::"memory");
    240 
    241         // access tls as normal (except for pointer arithmetic)
    242         uintptr_t val = *(uintptr_t*)((uintptr_t)&__cfaabi_tls + offset);
    243 
    244         // create a assembler label after
    245         // marked as clobber all to avoid movement
    246         asm volatile("__cfaasm_get_after:":::"memory");
    247         return val;
    248 }
     162
     163__cfaabi_dbg_debug_do( static thread_local void * last_interrupt = 0; )
    249164
    250165extern "C" {
    251166        // Disable interrupts by incrementing the counter
    252167        void disable_interrupts() {
    253                 // create a assembler label before
    254                 // marked as clobber all to avoid movement
    255                 asm volatile("__cfaasm_disable_before:":::"memory");
    256 
    257                 with( __cfaabi_tls.preemption_state ) {
     168                with( kernelTLS.preemption_state ) {
    258169                        #if GCC_VERSION > 50000
    259170                        static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     
    272183                        verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    273184                }
    274 
    275                 // create a assembler label after
    276                 // marked as clobber all to avoid movement
    277                 asm volatile("__cfaasm_disable_after:":::"memory");
    278185        }
    279186
     
    281188        // If counter reaches 0, execute any pending __cfactx_switch
    282189        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    283                 // create a assembler label before
    284                 // marked as clobber all to avoid movement
    285                 asm volatile("__cfaasm_enable_before:":::"memory");
    286 
    287                 processor   * proc = __cfaabi_tls.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
     190                processor   * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
    288191                /* paranoid */ verify( proc );
    289192
    290                 with( __cfaabi_tls.preemption_state ){
     193                with( kernelTLS.preemption_state ){
    291194                        unsigned short prev = disable_count;
    292195                        disable_count -= 1;
     
    315218                // For debugging purposes : keep track of the last person to enable the interrupts
    316219                __cfaabi_dbg_debug_do( proc->last_enable = caller; )
    317 
    318                 // create a assembler label after
    319                 // marked as clobber all to avoid movement
    320                 asm volatile("__cfaasm_enable_after:":::"memory");
    321220        }
    322221
     
    324223        // Don't execute any pending __cfactx_switch even if counter reaches 0
    325224        void enable_interrupts_noPoll() {
    326                 // create a assembler label before
    327                 // marked as clobber all to avoid movement
    328                 asm volatile("__cfaasm_nopoll_before:":::"memory");
    329 
    330                 unsigned short prev = __cfaabi_tls.preemption_state.disable_count;
    331                 __cfaabi_tls.preemption_state.disable_count -= 1;
     225                unsigned short prev = kernelTLS.preemption_state.disable_count;
     226                kernelTLS.preemption_state.disable_count -= 1;
    332227                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    333228                if( prev == 1 ) {
    334229                        #if GCC_VERSION > 50000
    335                         static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");
     230                        static_assert(__atomic_always_lock_free(sizeof(kernelTLS.preemption_state.enabled), &kernelTLS.preemption_state.enabled), "Must be lock-free");
    336231                        #endif
    337232                        // Set enabled flag to true
    338233                        // should be atomic to avoid preemption in the middle of the operation.
    339234                        // use memory order RELAXED since there is no inter-thread on this variable requirements
    340                         __atomic_store_n(&__cfaabi_tls.preemption_state.enabled, true, __ATOMIC_RELAXED);
     235                        __atomic_store_n(&kernelTLS.preemption_state.enabled, true, __ATOMIC_RELAXED);
    341236
    342237                        // Signal the compiler that a fence is needed but only for signal handlers
    343238                        __atomic_signal_fence(__ATOMIC_RELEASE);
    344239                }
    345 
    346                 // create a assembler label after
    347                 // marked as clobber all to avoid movement
    348                 asm volatile("__cfaasm_nopoll_after:":::"memory");
    349240        }
    350241}
     
    379270
    380271// reserved for future use
    381 static void timeout( $thread * this ) {
     272static void timeout( struct __processor_id_t * id, $thread * this ) {
    382273        #if !defined( __CFA_NO_STATISTICS__ )
    383                 kernelTLS().this_stats = this->curr_cluster->stats;
     274                kernelTLS.this_stats = this->curr_cluster->stats;
    384275        #endif
    385         unpark( this );
     276        __unpark( id, this );
    386277}
    387278
     
    392283static inline bool preemption_ready() {
    393284        // Check if preemption is safe
    394         bool ready = __cfaabi_tls.preemption_state.enabled && ! __cfaabi_tls.preemption_state.in_progress;
     285        bool ready = kernelTLS.preemption_state.enabled && ! kernelTLS.preemption_state.in_progress;
    395286
    396287        // Adjust the pending flag accordingly
    397         __cfaabi_tls.this_processor->pending_preemption = !ready;
     288        kernelTLS.this_processor->pending_preemption = !ready;
    398289        return ready;
    399290}
     
    409300
    410301        // Start with preemption disabled until ready
    411         __cfaabi_tls.preemption_state.enabled = false;
    412         __cfaabi_tls.preemption_state.disable_count = 1;
     302        kernelTLS.preemption_state.enabled = false;
     303        kernelTLS.preemption_state.disable_count = 1;
    413304
    414305        // Initialize the event kernel
     
    468359// Kernel Signal Handlers
    469360//=============================================================================================
    470 struct asm_region {
    471         void * before;
    472         void * after;
    473 };
    474 
    475 //-----------------------------------------------------------------------------
    476 // Some assembly required
    477 #if defined( __i386 )
    478         #define __cfaasm_label( label ) \
    479                 ({ \
    480                         struct asm_region region; \
    481                         asm( \
    482                                 "movl $__cfaasm_" #label "_before, %[vb]\n\t" \
    483                                 "movl $__cfaasm_" #label "_after , %[va]\n\t" \
    484                                  : [vb]"=r"(region.before), [vb]"=r"(region.before) \
    485                         ); \
    486                         region; \
    487                 });
    488 #elif defined( __x86_64 )
    489         #ifdef __PIC__
    490                 #define PLT "@PLT"
    491         #else
    492                 #define PLT ""
    493         #endif
    494         #define __cfaasm_label( label ) \
    495                 ({ \
    496                         struct asm_region region; \
    497                         asm( \
    498                                 "movq $__cfaasm_" #label "_before" PLT ", %[vb]\n\t" \
    499                                 "movq $__cfaasm_" #label "_after"  PLT ", %[va]\n\t" \
    500                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    501                         ); \
    502                         region; \
    503                 });
    504 #elif defined( __aarch64__ )
    505         #error __cfaasm_label undefined for arm
    506 #else
    507         #error unknown hardware architecture
    508 #endif
    509 
    510 __cfaabi_dbg_debug_do( static thread_local void * last_interrupt = 0; )
    511361
    512362// Context switch signal handler
    513363// Receives SIGUSR1 signal and causes the current thread to yield
    514364static void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    515         void * ip = (void *)(cxt->uc_mcontext.CFA_REG_IP);
    516         __cfaabi_dbg_debug_do( last_interrupt = ip; )
     365        __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); )
    517366
    518367        // SKULLDUGGERY: if a thread creates a processor and the immediately deletes it,
     
    520369        // before the kernel thread has even started running. When that happens, an interrupt
    521370        // with a null 'this_processor' will be caught, just ignore it.
    522         if(! __cfaabi_tls.this_processor ) return;
     371        if(! kernelTLS.this_processor ) return;
    523372
    524373        choose(sfp->si_value.sival_int) {
    525374                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
    526                 case PREEMPT_TERMINATE: verify( __atomic_load_n( &__cfaabi_tls.this_processor->do_terminate, __ATOMIC_SEQ_CST ) );
     375                case PREEMPT_TERMINATE: verify( __atomic_load_n( &kernelTLS.this_processor->do_terminate, __ATOMIC_SEQ_CST ) );
    527376                default:
    528377                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     
    532381        if( !preemption_ready() ) { return; }
    533382
    534         struct asm_region region;
    535         region = __cfaasm_label( get     ); if( ip >= region.before && ip <= region.after ) return;
    536         region = __cfaasm_label( check   ); if( ip >= region.before && ip <= region.after ) return;
    537         region = __cfaasm_label( disable ); if( ip >= region.before && ip <= region.after ) return;
    538         region = __cfaasm_label( enable  ); if( ip >= region.before && ip <= region.after ) return;
    539         region = __cfaasm_label( nopoll  ); if( ip >= region.before && ip <= region.after ) return;
    540 
    541         __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", __cfaabi_tls.this_processor, __cfaabi_tls.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) );
     383        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", kernelTLS.this_processor, kernelTLS.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) );
    542384
    543385        // Sync flag : prevent recursive calls to the signal handler
    544         __cfaabi_tls.preemption_state.in_progress = true;
     386        kernelTLS.preemption_state.in_progress = true;
    545387
    546388        // Clear sighandler mask before context switching.
     
    552394        }
    553395
     396        // TODO: this should go in finish action
    554397        // Clear the in progress flag
    555         __cfaabi_tls.preemption_state.in_progress = false;
     398        kernelTLS.preemption_state.in_progress = false;
    556399
    557400        // Preemption can occur here
     
    570413        id.full_proc = false;
    571414        id.id = doregister(&id);
    572         __cfaabi_tls.this_proc_id = &id;
    573415
    574416        // Block sigalrms to control when they arrive
     
    616458                        // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" );
    617459                        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    618                         tick_preemption();
     460                        tick_preemption( &id );
    619461                        unlock( event_kernel->lock );
    620462                        break;
     
    638480
    639481void __cfaabi_check_preemption() {
    640         bool ready = __preemption_enabled();
     482        bool ready = kernelTLS.preemption_state.enabled;
    641483        if(!ready) { abort("Preemption should be ready"); }
    642484
     
    661503#ifdef __CFA_WITH_VERIFY__
    662504bool __cfaabi_dbg_in_kernel() {
    663         return !__preemption_enabled();
     505        return !kernelTLS.preemption_state.enabled;
    664506}
    665507#endif
  • libcfa/src/concurrency/ready_queue.cfa

    r139775e r55acc3a  
    150150//  queues or removing them.
    151151uint_fast32_t ready_mutate_lock( void ) with(*__scheduler_lock) {
    152         /* paranoid */ verify( ! __preemption_enabled() );
     152        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    153153
    154154        // Step 1 : lock global lock
     
    166166        }
    167167
    168         /* paranoid */ verify( ! __preemption_enabled() );
     168        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    169169        return s;
    170170}
    171171
    172172void ready_mutate_unlock( uint_fast32_t last_s ) with(*__scheduler_lock) {
    173         /* paranoid */ verify( ! __preemption_enabled() );
     173        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    174174
    175175        // Step 1 : release local locks
     
    188188        __atomic_store_n(&lock, (bool)false, __ATOMIC_RELEASE);
    189189
    190         /* paranoid */ verify( ! __preemption_enabled() );
     190        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    191191}
    192192
     
    252252                preferred =
    253253                        //*
    254                         kernelTLS().this_processor ? kernelTLS().this_processor->id * 4 : -1;
     254                        kernelTLS.this_processor ? kernelTLS.this_processor->id * 4 : -1;
    255255                        /*/
    256256                        thrd->link.preferred * 4;
     
    331331                // Don't bother trying locally too much
    332332                int local_tries = 8;
    333                 preferred = kernelTLS().this_processor->id * 4;
     333                preferred = kernelTLS.this_processor->id * 4;
    334334        #endif
    335335
  • libcfa/src/concurrency/thread.cfa

    r139775e r55acc3a  
    127127        verify( this_thrd->context.SP );
    128128
    129         __schedule_thread( this_thrd );
     129        __schedule_thread( (__processor_id_t *)kernelTLS.this_processor, this_thrd);
    130130        enable_interrupts( __cfaabi_dbg_ctx );
    131131}
  • src/AST/Convert.cpp

    r139775e r55acc3a  
    2525#include "AST/Init.hpp"
    2626#include "AST/Stmt.hpp"
    27 #include "AST/TranslationUnit.hpp"
    2827#include "AST/TypeSubstitution.hpp"
    2928
     
    14051404};
    14061405
    1407 std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
     1406std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
    14081407        ConverterNewToOld c;
    14091408        std::list< Declaration * > decls;
    1410         for(auto d : translationUnit.decls) {
     1409        for(auto d : translationUnit) {
    14111410                decls.emplace_back( c.decl( d ) );
    14121411        }
     
    28042803#undef GET_ACCEPT_1
    28052804
    2806 ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit ) {
     2805std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit ) {
    28072806        ConverterOldToNew c;
    2808         ast::TranslationUnit unit;
     2807        std::list< ast::ptr< ast::Decl > > decls;
    28092808        for(auto d : translationUnit) {
    28102809                d->accept( c );
    2811                 unit.decls.emplace_back( c.decl() );
     2810                decls.emplace_back( c.decl() );
    28122811        }
    28132812        deleteAll(translationUnit);
    2814         return unit;
     2813        return decls;
    28152814}
  • src/AST/Convert.hpp

    r139775e r55acc3a  
    1818#include <list>
    1919
     20#include "AST/Node.hpp"
     21
    2022class Declaration;
    2123namespace ast {
    22         class TranslationUnit;
     24        class Decl;
    2325};
    2426
    25 std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit );
    26 ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit );
     27std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit );
     28std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit );
  • src/AST/Fwd.hpp

    r139775e r55acc3a  
    137137typedef unsigned int UniqueId;
    138138
    139 class TranslationUnit;
    140 // TODO: Get from the TranslationUnit:
    141139extern Type * sizeType;
    142140extern FunctionDecl * dereferenceOperator;
  • src/AST/Pass.hpp

    r139775e r55acc3a  
    103103        /// Construct and run a pass on a translation unit.
    104104        template< typename... Args >
    105         static void run( TranslationUnit & decls, Args &&... args ) {
     105        static void run( std::list< ptr<Decl> > & decls, Args &&... args ) {
    106106                Pass<core_t> visitor( std::forward<Args>( args )... );
    107107                accept_all( decls, visitor );
     
    119119        // Versions of the above for older compilers.
    120120        template< typename... Args >
    121         static void run( TranslationUnit & decls ) {
     121        static void run( std::list< ptr<Decl> > & decls ) {
    122122                Pass<core_t> visitor;
    123123                accept_all( decls, visitor );
     
    303303void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor );
    304304
    305 template<typename core_t>
    306 void accept_all( ast::TranslationUnit &, ast::Pass<core_t> & visitor );
    307 
    308305//-------------------------------------------------------------------------------------------------
    309306// PASS ACCESSORIES
  • src/AST/Pass.impl.hpp

    r139775e r55acc3a  
    2020#include <unordered_map>
    2121
    22 #include "AST/TranslationUnit.hpp"
    2322#include "AST/TypeSubstitution.hpp"
    2423
     
    431430        pass_visitor_stats.depth--;
    432431        if ( !errors.isEmpty() ) { throw errors; }
    433 }
    434 
    435 template< typename core_t >
    436 inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
    437         return ast::accept_all( unit.decls, visitor );
    438432}
    439433
     
    680674const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
    681675        VISIT_START( node );
    682         VISIT(
     676        VISIT({
    683677                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
    684678                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     
    687681                        if ( leaveScope ) __pass::symtab::leave(core, 0);
    688682                });
    689                 ValueGuard< bool > guard2( atFunctionTop );
    690                 atFunctionTop = false;
     683                ValueGuard< bool > guard2( inFunction );
    691684                guard_scope guard3 { *this };
     685                inFunction = false;
    692686                maybe_accept( node, &CompoundStmt::kids );
    693         )
     687        })
    694688        VISIT_END( CompoundStmt, node );
    695689}
  • src/AST/Pass.proto.hpp

    r139775e r55acc3a  
    2222template<typename core_t>
    2323class Pass;
    24 
    25 class TranslationUnit;
    2624
    2725struct PureVisitor;
  • src/InitTweak/FixGlobalInit.cc

    r139775e r55acc3a  
    109109        }
    110110
    111         void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
     111        void fixGlobalInit(std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary) {
    112112                ast::Pass<GlobalFixer_new> fixer;
    113113                accept_all(translationUnit, fixer);
     
    119119                                ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});
    120120
    121                         translationUnit.decls.emplace_back( initFunction );
     121                        translationUnit.emplace_back( initFunction );
    122122                } // if
    123123
     
    128128                                ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});
    129129
    130                         translationUnit.decls.emplace_back(destroyFunction);
     130                        translationUnit.emplace_back(destroyFunction);
    131131                } // if
    132132        }
     
    183183                        } // if
    184184                        if ( const ast::Stmt * ctor = ctorInit->ctor ) {
    185                                 addDataSectionAttribute(mutDecl);
    186185                                initStmts.push_back( ctor );
    187186                                mutDecl->init = nullptr;
  • src/InitTweak/FixGlobalInit.h

    r139775e r55acc3a  
    2929        /// function is for library code.
    3030        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
    31         void fixGlobalInit( ast::TranslationUnit & translationUnit, bool inLibrary );
     31        void fixGlobalInit( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary );
    3232} // namespace
    3333
  • src/InitTweak/FixInit.h

    r139775e r55acc3a  
    1919#include <string>  // for string
    2020
     21#include <AST/Fwd.hpp>
     22
    2123class Declaration;
    22 namespace ast {
    23         class TranslationUnit;
    24 }
    2524
    2625namespace InitTweak {
     
    2827        void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
    2928
    30         void fix( ast::TranslationUnit & translationUnit, bool inLibrary);
     29        void fix( std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary);
    3130} // namespace
    3231
  • src/InitTweak/FixInitNew.cpp

    r139775e r55acc3a  
    179179        /// expand each object declaration to use its constructor after it is declared.
    180180        struct FixInit : public ast::WithStmtsToAdd<> {
    181                 static void fixInitializers( ast::TranslationUnit &translationUnit );
     181                static void fixInitializers( std::list< ast::ptr<ast::Decl> > &translationUnit );
    182182
    183183                const ast::DeclWithType * postvisit( const ast::ObjectDecl *objDecl );
     
    225225} // namespace
    226226
    227 void fix( ast::TranslationUnit & translationUnit, bool inLibrary ) {
     227void fix( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary ) {
    228228        ast::Pass<SelfAssignChecker>::run( translationUnit );
    229229
     
    308308        }
    309309
    310         void FixInit::fixInitializers( ast::TranslationUnit & translationUnit ) {
     310        void FixInit::fixInitializers( std::list< ast::ptr<ast::Decl> > & translationUnit ) {
    311311                ast::Pass<FixInit> fixer;
    312312
     
    314314                // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
    315315                SemanticErrorException errors;
    316                 for ( auto i = translationUnit.decls.begin(); i != translationUnit.decls.end(); ++i ) {
     316                for ( auto i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    317317                        try {
    318318                                // maybeAccept( *i, fixer ); translationUnit should never contain null
    319319                                *i = (*i)->accept(fixer);
    320                                 translationUnit.decls.splice( i, fixer.core.staticDtorDecls );
     320                                translationUnit.splice( i, fixer.core.staticDtorDecls );
    321321                        } catch( SemanticErrorException &e ) {
    322322                                errors.append( e );
     
    864864                        if ( const ast::Stmt * ctor = ctorInit->ctor ) {
    865865                                if ( objDecl->storage.is_static ) {
    866                                         addDataSectionAttribute(objDecl);
    867866                                        // originally wanted to take advantage of gcc nested functions, but
    868867                                        // we get memory errors with this approach. To remedy this, the static
     
    948947                                                objDecl->name = objDecl->name + staticNamer.newName();
    949948                                                objDecl->mangleName = Mangle::mangle( objDecl );
    950                                                 objDecl->init = nullptr;
    951949
    952950                                                // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
  • src/InitTweak/InitTweak.cc

    r139775e r55acc3a  
    11131113        }
    11141114
    1115         void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
    1116                 auto strLitT = new ast::PointerType(new ast::BasicType(ast::BasicType::Char));
    1117                 objDecl->attributes.push_back(new ast::Attribute("section", {new ast::ConstantExpr(objDecl->location, strLitT, "\".data#\"", std::nullopt)}));
    1118         }
    1119 
    11201115}
  • src/InitTweak/InitTweak.h

    r139775e r55acc3a  
    119119        void addDataSectonAttribute( ObjectDecl * objDecl );
    120120
    121         void addDataSectionAttribute( ast::ObjectDecl * objDecl );
    122 
    123121        class InitExpander_old {
    124122        public:
  • src/ResolvExpr/Resolver.cc

    r139775e r55acc3a  
    12741274        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
    12751275
    1276         void resolve( ast::TranslationUnit& translationUnit ) {
     1276        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    12771277                ast::Pass< Resolver_new >::run( translationUnit );
    12781278        }
  • src/ResolvExpr/Resolver.h

    r139775e r55acc3a  
    3535        class StmtExpr;
    3636        class SymbolTable;
    37         class TranslationUnit;
    3837        class Type;
    3938        class TypeEnvironment;
     
    5655
    5756        /// Checks types and binds syntactic constructs to typed representations
    58         void resolve( ast::TranslationUnit& translationUnit );
     57        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
    5958        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    6059        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
     
    7069                const ast::Expr * untyped, const ast::SymbolTable & symtab);
    7170        /// Resolves a constructor init expression
    72         ast::ptr< ast::Init > resolveCtorInit(
     71        ast::ptr< ast::Init > resolveCtorInit( 
    7372                const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
    7473        /// Resolves a statement expression
    75         ast::ptr< ast::Expr > resolveStmtExpr(
     74        ast::ptr< ast::Expr > resolveStmtExpr( 
    7675                const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
    7776} // namespace ResolvExpr
  • tests/Makefile.am

    r139775e r55acc3a  
    5353
    5454# adjust CC to current flags
    55 CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS} ${AST_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS} ${AST_FLAGS})
     55CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
    5656CFACC = $(CC)
    5757
     
    6060
    6161# adjusted CC but without the actual distcc call
    62 CFACCLOCAL = $(if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS} ${AST_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS} ${AST_FLAGS})
     62CFACCLOCAL = $(if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
    6363CFACCLINK = $(CFACCLOCAL) -quiet $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'))
    6464
  • tests/config.py.in

    r139775e r55acc3a  
    99HOSTARCH = "@host_cpu@"
    1010DISTRIBUTE = @HAS_DISTCC@
    11 NEWAST = @DEFAULT_NEW_AST@
  • tests/pybin/settings.py

    r139775e r55acc3a  
    8585        def filter(self, tests):
    8686                return [test for test in tests if not test.arch or self.target == test.arch]
     87                return True if not arch else self.target == arch
    8788
    8889        @staticmethod
     
    9697                self.flags  = """DEBUG_FLAGS=%s""" % ("-debug -O0" if value else "-nodebug -O2")
    9798                self.path   = "debug" if value else "nodebug"
    98 
    99 class AST:
    100         def __init__(self, ast):
    101                 if ast == "new":
    102                         self.target = ast
    103                         self.string = "New AST"
    104                         self.flags  = """AST_FLAGS=-XCFA,--new-ast"""
    105                 elif ast == "old":
    106                         self.target = ast
    107                         self.string = "Old AST"
    108                         self.flags  = """AST_FLAGS=-XCFA,--old-ast"""
    109                 elif ast == None:
    110                         self.target = "new" if config.NEWAST else "old"
    111                         self.string = "Default AST (%s)" % self.target
    112                         self.flags  = """AST_FLAGS="""
    113                 else:
    114                         print("""ERROR: Invalid ast configuration, must be "old", "new" or left unspecified, was %s""" % (value), file=sys.stderr)
    115                         sys.exit(1)
    116 
    117         def filter(self, tests):
    118 
    119                 return [test for test in tests if not test.astv or self.target == test.astv]
    12099
    121100class Install:
     
    141120
    142121def init( options ):
    143         global all_ast
    144122        global all_arch
    145123        global all_debug
    146124        global all_install
    147         global ast
    148125        global arch
     126        global archive
     127        global continue_
    149128        global debug
    150         global archive
    151         global install
    152 
    153         global continue_
    154129        global dry_run
    155130        global generating
     131        global install
    156132        global make
    157133        global output_width
     
    159135        global timeout2gdb
    160136
    161         all_ast      = [AST(o)          for o in list(dict.fromkeys(options.ast    ))] if options.ast  else [AST(None)]
    162137        all_arch     = [Architecture(o) for o in list(dict.fromkeys(options.arch   ))] if options.arch else [Architecture(None)]
    163138        all_debug    = [Debug(o)        for o in list(dict.fromkeys(options.debug  ))]
  • tests/pybin/test_run.py

    r139775e r55acc3a  
    1111                self.path = ''
    1212                self.arch = ''
    13                 self.astv = ''
    1413
    1514        def toString(self):
    16                 return "{:25s} ({:5s} arch, {:s} ast: {:s})".format( self.name, self.arch if self.arch else "Any", self.astv if self.astv else "Any", self.target() )
     15                return "{:25s} ({:5s} {:s})".format( self.name, self.arch if self.arch else "Any", self.target() )
    1716
    1817        def prepare(self):
     
    2120
    2221        def expect(self):
    23                 arch = '' if not self.arch else ".%s" % self.arch
    24                 astv = '' if not self.astv else ".nast" if self.astv == "new" else ".oast"
    25                 return os.path.normpath( os.path.join(settings.SRCDIR  , self.path, ".expect", "%s%s%s.txt" % (self.name,astv,arch)) )
     22                return os.path.normpath( os.path.join(settings.SRCDIR  , self.path, ".expect", "%s%s.txt" % (self.name,'' if not self.arch else ".%s" % self.arch)) )
    2623
    2724        def error_log(self):
     
    4845
    4946        @staticmethod
    50         def new_target(target, arch, astv):
     47        def new_target(target, arch):
    5148                test = Test()
    5249                test.name = os.path.basename(target)
    5350                test.path = os.path.relpath (os.path.dirname(target), settings.SRCDIR)
    5451                test.arch = arch.target if arch else ''
    55                 test.astv = astv.target if astv else ''
    5652                return test
    5753
  • tests/pybin/tools.py

    r139775e r55acc3a  
    181181                '-s' if silent else None,
    182182                test_param,
    183                 settings.ast.flags,
    184183                settings.arch.flags,
    185184                settings.debug.flags,
  • tests/test.py

    r139775e r55acc3a  
    2424
    2525        def match_test(path):
    26                 match = re.search("^%s\/([\w\/\-_]*).expect\/([\w\-_]+)(\.nast|\.oast)?(\.[\w\-_]+)?\.txt$" % settings.SRCDIR, path)
     26                match = re.search("^%s\/([\w\/\-_]*).expect\/([\w\-_]+)(\.[\w\-_]+)?\.txt$" % settings.SRCDIR, path)
    2727                if match :
    2828                        test = Test()
    2929                        test.name = match.group(2)
    3030                        test.path = match.group(1)
    31                         test.arch = match.group(4)[1:] if match.group(4) else None
    32 
    33                         astv = match.group(3)[1:] if match.group(3) else None
    34                         if astv == 'oast':
    35                                 test.astv = 'old'
    36                         elif astv == 'nast':
    37                                 test.astv = 'new'
    38                         elif astv:
    39                                 print('ERROR: "%s", expect file has astv but it is not "nast" or "oast"' % testname, file=sys.stderr)
    40                                 sys.exit(1)
    41 
     31                        test.arch = match.group(3)[1:] if match.group(3) else None
    4232                        expected.append(test)
    4333
     
    7666        if options.regenerate_expected :
    7767                for testname in options.tests :
    78                         testname = os.path.normpath( os.path.join(settings.SRCDIR, testname) )
    79 
     68                        testname = canonical_path( testname )
    8069                        # first check if this is a valid name to regenerate
    8170                        if Test.valid_name(testname):
    8271                                # this is a valid name, let's check if it already exists
    8372                                found = [test for test in all_tests if canonical_path( test.target() ) == testname]
    84                                 setup = itertools.product(settings.all_arch if options.arch else [None], settings.all_ast if options.ast else [None])
    8573                                if not found:
    86                                         # it's a new name, create it according to the name and specified architecture/ast version
    87                                         tests.extend( [Test.new_target(testname, arch, ast) for arch, ast in setup] )
     74                                        # it's a new name, create it according to the name and specified architecture
     75                                        if options.arch:
     76                                                # user specified one or multiple architectures, assume the tests will have architecture specific results
     77                                                tests.extend( [Test.new_target(testname, arch) for arch in settings.all_arch] )
     78                                        else:
     79                                                # user didn't specify an architecture, just create a cross platform test
     80                                                tests.append( Test.new_target( testname, None ) )
    8881                                elif len(found) == 1 and not found[0].arch:
    8982                                        # we found a single test, the user better be wanting to create a cross platform test
    9083                                        if options.arch:
    9184                                                print('ERROR: "%s", test has no specified architecture but --arch was specified, ignoring it' % testname, file=sys.stderr)
    92                                         elif options.ast:
    93                                                 print('ERROR: "%s", test has no specified ast version but --ast was specified, ignoring it' % testname, file=sys.stderr)
    9485                                        else:
    9586                                                tests.append( found[0] )
    9687                                else:
    9788                                        # this test is already cross platform, just add a test for each platform the user asked
    98                                         tests.extend( [Test.new_target(testname, arch, ast) for arch, ast in setup] )
     89                                        tests.extend( [Test.new_target(testname, arch) for arch in settings.all_arch] )
    9990
    10091                                        # print a warning if it users didn't ask for a specific architecture
    10192                                        if not options.arch:
    10293                                                print('WARNING: "%s", test has architecture specific expected files but --arch was not specified, regenerating only for current host' % testname, file=sys.stderr)
    103 
    104 
    105                                         # print a warning if it users didn't ask for a specific ast version
    106                                         if not options.ast:
    107                                                 print('WARNING: "%s", test has ast version specific expected files but --ast was not specified, regenerating only for current ast' % testname, file=sys.stderr)
    10894
    10995                        else :
     
    126112        # create a parser with the arguments for the tests script
    127113        parser = argparse.ArgumentParser(description='Script which runs cforall tests')
    128         parser.add_argument('--ast', help='Test for specific ast', type=comma_separated(str), default=None)
    129         parser.add_argument('--arch', help='Test for specific architecture', type=comma_separated(str), default=None)
    130114        parser.add_argument('--debug', help='Run all tests in debug or release', type=comma_separated(yes_no), default='yes')
    131115        parser.add_argument('--install', help='Run all tests based on installed binaries or tree binaries', type=comma_separated(yes_no), default='no')
     116        parser.add_argument('--arch', help='Test for specific architecture', type=comma_separated(str), default=None)
    132117        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_')
    133118        parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=120)
     
    266251        except KeyboardInterrupt:
    267252                return False, ""
    268         # except Exception as ex:
    269         #       print("Unexpected error in worker thread running {}: {}".format(t.target(), ex), file=sys.stderr)
    270         #       sys.stderr.flush()
    271         #       return False, ""
     253        except Exception as ex:
     254                print("Unexpected error in worker thread running {}: {}".format(t.target(), ex), file=sys.stderr)
     255                sys.stderr.flush()
     256                return False, ""
    272257
    273258
     
    377362                # for each build configurations, run the test
    378363                with Timed() as total_dur:
    379                         for ast, arch, debug, install in itertools.product(settings.all_ast, settings.all_arch, settings.all_debug, settings.all_install):
    380                                 settings.ast     = ast
     364                        for arch, debug, install in itertools.product(settings.all_arch, settings.all_debug, settings.all_install):
    381365                                settings.arch    = arch
    382366                                settings.debug   = debug
     
    385369                                # filter out the tests for a different architecture
    386370                                # tests are the same across debug/install
    387                                 local_tests = settings.ast.filter( tests )
    388                                 local_tests = settings.arch.filter( local_tests )
     371                                local_tests = settings.arch.filter( tests )
    389372                                options.jobs, forceJobs = job_count( options, local_tests )
    390373                                settings.update_make_cmd(forceJobs, options.jobs)
     
    394377
    395378                                # print configuration
    396                                 print('%s %i tests on %i cores (%s:%s - %s)' % (
     379                                print('%s %i tests on %i cores (%s:%s)' % (
    397380                                        'Regenerating' if settings.generating else 'Running',
    398381                                        len(local_tests),
    399382                                        options.jobs,
    400                                         settings.ast.string,
    401383                                        settings.arch.string,
    402384                                        settings.debug.string
    403385                                ))
    404                                 if not local_tests :
    405                                         print('WARNING: No tests for this configuration')
    406                                         continue
    407386
    408387                                # otherwise run all tests and make sure to return the correct error code
  • tools/stat.py

    r139775e r55acc3a  
    1 #!/usr/bin/python3
     1#!/usr/bin/python
    22
    33import sys
     
    1717                avg = numpy.mean  (content)
    1818                std = numpy.std   (content)
    19                 print("median {0:.1f} avg {1:.1f} stddev {2:.1f}".format( med, avg, std ))
     19                print "median {0:.1f} avg {1:.1f} stddev {2:.1f}".format( med, avg, std )
    2020
    2121
Note: See TracChangeset for help on using the changeset viewer.