Changes in / [ad6343e:4a9ccc3]


Ignore:
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • doc/proposals/concurrency/thePlan.md

    rad6343e r4a9ccc3  
    44done - SimpleBlockingLock.
    55done - Synchronisation points in thread destructors.
    6 done - Processors & SpinLock.
     6Processors & SpinLock.
    77
    88_Phase 2_ : Minimum Viable Product
    9 Monitor type and enter/leave mutex member routines
    10 Monitors as a language feature (not calling enter/leave by hand)
    11 Internal scheduling
     9Basic monitors for synchronisation (No internal/external scheduling).
     10Non-thrash scheduler.
     11Clusters.
    1212
    1313_Phase 3_ : Kernel features
    14 Detach thread
    15 Cluster migration
    16 Preemption
     14Threads features ex: detach
     15Internal scheduling
    1716
    1817_Phase 4_ : Monitor features
  • src/driver/cfa.cc

    rad6343e r4a9ccc3  
    267267                }
    268268                nargs += 1;
    269                 args[nargs] = "-lpthread";
    270                 nargs += 1;
    271269        } // if
    272270#endif //HAVE_LIBCFA
  • src/examples/thread.c

    rad6343e r4a9ccc3  
    1 #line 1 "thread.c"
    21#include <fstream>
    3 #include <kernel>
    42#include <stdlib>
    53#include <threads>
     
    1210};
    1311
    14 DECL_THREAD(MyThread)
    15 
    16 void ?{}( MyThread * this ) {
    17 }
     12// DECL_THREAD(MyThread)
    1813
    1914void ?{}( MyThread * this, unsigned id, unsigned count ) {
     
    2217}
    2318
    24 void main(MyThread* this) {
    25         sout | "Thread" | this->id | " : Suspending" | this->count | "times" | endl;
    26         yield();
     19// void main(MyThread* this) {
     20//      sout | "Thread" | this->id | " : Suspending" | this->count | "times" | endl;
     21//      yield();
    2722
    28         for(int i = 0; i < this->count; i++) {
    29                 sout | "Thread" | this->id | " : Suspend No." | i + 1 | endl;
    30                 yield();
    31         }
    32 }
     23//      for(int i = 0; i < this->count; i++) {
     24//              sout | "Thread" | this->id | " : Suspend No." | i + 1 | endl;
     25//              yield();
     26//      }
     27// }
    3328
    3429int main(int argc, char* argv[]) {
    3530
    36         unsigned itterations = 10u;
    37         if(argc == 2) {
    38                 int val = ato(argv[1]);
    39                 assert(val >= 0);
    40                 itterations = val;
    41         }
     31        // unsigned itterations = 10u;
     32        // if(argc == 2) {
     33        //      int val = ato(argv[1]);
     34        //      assert(val >= 0);
     35        //      itterations = val;
     36        // }
    4237
    4338        sout | "User main begin" | endl;
    4439
    45         {
    46                 processor p;
    47                 {
    48                         thread(MyThread) thread1 = { 1u, itterations };
    49                         thread(MyThread) thread2 = { 2u, itterations };
    50                 }
    51         }
     40        // {
     41        //      thread(MyThread) thread1 = { 1u, itterations };
     42        //      thread(MyThread) thread2 = { 2u, itterations };
     43        // }
    5244
    5345        sout | "User main end" | endl;
  • src/libcfa/concurrency/coroutines

    rad6343e r4a9ccc3  
    7373
    7474        assertf( src->last != 0,
    75                 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"
     75                "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"
    7676                "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    7777                src->name, src );
    7878        assertf( src->last->notHalted,
    79                 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
     79                "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"
    8080                "Possible cause is terminated coroutine's main routine has already returned.",
    8181                src->name, src, src->last->name, src->last );
  • src/libcfa/concurrency/coroutines.c

    rad6343e r4a9ccc3  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    3231#include "invoke.h"
    3332
    34 extern processor * get_this_processor();
     33/*thread_local*/ extern processor * this_processor;
    3534
    3635//-----------------------------------------------------------------------------
     
    111110
    112111        // set new coroutine that task is executing
    113         get_this_processor()->current_coroutine = dst;                 
     112        this_processor->current_coroutine = dst;                       
    114113
    115114        // context switch to specified coroutine
  • src/libcfa/concurrency/invoke.c

    rad6343e r4a9ccc3  
    1 //                              -*- Mode: CFA -*-
    2 //
    3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 //
    5 // The contents of this file are covered under the licence agreement in the
    6 // file "LICENCE" distributed with Cforall.
    7 //
    8 // invoke.c --
    9 //
    10 // Author           : Thierry Delisle
    11 // Created On       : Tue Jan 17 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
    15 //
    161
    172#include <stdbool.h>
  • src/libcfa/concurrency/invoke.h

    rad6343e r4a9ccc3  
    1 //                              -*- Mode: CFA -*-
    2 //
    3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 //
    5 // The contents of this file are covered under the licence agreement in the
    6 // file "LICENCE" distributed with Cforall.
    7 //
    8 // invoke.h --
    9 //
    10 // Author           : Thierry Delisle
    11 // Created On       : Tue Jan 17 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
    15 //
    16 
    171#include <stdbool.h>
    182#include <stdint.h>
     
    2711
    2812      #define unlikely(x)    __builtin_expect(!!(x), 0)
    29       #define thread_local _Thread_local
    3013      #define SCHEDULER_CAPACITY 10
    3114
  • src/libcfa/concurrency/kernel

    rad6343e r4a9ccc3  
    2222#include "invoke.h"
    2323
    24 extern "C" {
    25 #include <pthread.h>
    26 }
    27 
    2824//-----------------------------------------------------------------------------
    2925// Cluster
    3026struct cluster {
    3127        simple_thread_list ready_queue;
    32         pthread_spinlock_t lock;
    3328};
    3429
     
    4338        coroutine * current_coroutine;
    4439        thread_h * current_thread;
    45         pthread_t kernel_thread;
    46         simple_lock lock;
    47         volatile bool terminated;
     40        bool terminated;
    4841};
    4942
    50 void ?{}(processor * this);
    5143void ?{}(processor * this, cluster * cltr);
    5244void ^?{}(processor * this);
     
    6254void unlock( simple_lock * );
    6355
    64 struct pthread_spinlock_guard {
    65         pthread_spinlock_t * lock;
    66 };
    67 
    68 static inline void ?{}( pthread_spinlock_guard * this, pthread_spinlock_t * lock ) {
    69         this->lock = lock;
    70         pthread_spin_lock( this->lock );
    71 }
    72 
    73 static inline void ^?{}( pthread_spinlock_guard * this ) {
    74         pthread_spin_unlock( this->lock );
    75 }
    76 
    77 // //Simple spinlock implementation from
    78 // //http://stackoverflow.com/questions/1383363/is-my-spin-lock-implementation-correct-and-optimal
    79 // //Not optimal but correct
    80 // #define VOL
    81 
    82 // struct simple_spinlock {
    83 //      VOL int lock;
    84 // };
    85 
    86 // extern VOL int __sync_lock_test_and_set( VOL int *, VOL int);
    87 // extern void __sync_synchronize();
    88 
    89 // static inline void lock( simple_spinlock * this ) {
    90 //     while (__sync_lock_test_and_set(&this->lock, 1)) {
    91 //         // Do nothing. This GCC builtin instruction
    92 //         // ensures memory barrier.
    93 //     }
    94 // }
    95 
    96 // static inline void unlock( simple_spinlock * this ) {
    97 //     __sync_synchronize(); // Memory barrier.
    98 //     this->lock = 0;
    99 // }
    100 
    10156#endif //KERNEL_H
    10257
  • src/libcfa/concurrency/kernel.c

    rad6343e r4a9ccc3  
    3232#include "invoke.h"
    3333
    34 //-----------------------------------------------------------------------------
    35 // Kernel storage
     34cluster * systemCluster;
     35processor * systemProcessor;
     36thread_h * mainThread;
     37
     38void kernel_startup(void)  __attribute__((constructor(101)));
     39void kernel_shutdown(void) __attribute__((destructor(101)));
     40
     41void ?{}(processor * this, cluster * cltr) {
     42        this->ctx = NULL;
     43        this->cltr = cltr;
     44        this->terminated = false;
     45}
     46
     47void ^?{}(processor * this) {}
     48
     49void ?{}(cluster * this) {
     50        ( &this->ready_queue ){};
     51}
     52
     53void ^?{}(cluster * this) {}
     54
     55//-----------------------------------------------------------------------------
     56// Global state
     57
     58/*thread_local*/ processor * this_processor;
     59
     60coroutine * this_coroutine(void) {
     61        return this_processor->current_coroutine;
     62}
     63
     64thread_h * this_thread(void) {
     65        return this_processor->current_thread;
     66}
     67
     68//-----------------------------------------------------------------------------
     69// Processor coroutine
    3670struct processorCtx_t {
    3771        processor * proc;
     
    4175DECL_COROUTINE(processorCtx_t)
    4276
     77void ?{}(processorCtx_t * this, processor * proc) {
     78        (&this->c){};
     79        this->proc = proc;
     80}
     81
     82void CtxInvokeProcessor(processor * proc) {
     83        processorCtx_t proc_cor_storage = {proc};
     84        resume( &proc_cor_storage );
     85}
     86
     87//-----------------------------------------------------------------------------
     88// Processor running routines
     89void main(processorCtx_t * ctx);
     90thread_h * nextThread(cluster * this);
     91void runThread(processor * this, thread_h * dst);
     92void spin(processor * this, unsigned int * spin_count);
     93
     94void main(processorCtx_t * ctx) {
     95        processor * this = ctx->proc;
     96        LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);
     97
     98        thread_h * readyThread = NULL;
     99        for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {
     100               
     101                readyThread = nextThread( this->cltr );
     102
     103                if(readyThread) {
     104                        runThread(this, readyThread);
     105                        spin_count = 0;
     106                } else {
     107                        spin(this, &spin_count);
     108                }               
     109        }
     110
     111        LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);
     112}
     113
     114void runThread(processor * this, thread_h * dst) {
     115        coroutine * proc_ctx = get_coroutine(this->ctx);
     116        coroutine * thrd_ctx = get_coroutine(dst);
     117        thrd_ctx->last = proc_ctx;
     118
     119        // context switch to specified coroutine
     120        // Which is now the current_coroutine
     121        // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
     122        this->current_thread = dst;
     123        this->current_coroutine = thrd_ctx;
     124        CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
     125        this->current_coroutine = proc_ctx;
     126        // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
     127
     128        // when CtxSwitch returns we are back in the processor coroutine
     129}
     130
     131void spin(processor * this, unsigned int * spin_count) {
     132        (*spin_count)++;
     133}
     134
     135//-----------------------------------------------------------------------------
     136// Scheduler routines
     137void thread_schedule( thread_h * thrd ) {
     138        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
     139        append( &systemProcessor->cltr->ready_queue, thrd );
     140}
     141
     142thread_h * nextThread(cluster * this) {
     143        return pop_head( &this->ready_queue );
     144}
     145
     146//-----------------------------------------------------------------------------
     147// Kernel storage
    43148#define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
    44149
     
    49154KERNEL_STORAGE(machine_context_t, mainThread_context);
    50155
    51 cluster * systemCluster;
    52 processor * systemProcessor;
    53 thread_h * mainThread;
    54 
    55 void kernel_startup(void)  __attribute__((constructor(101)));
    56 void kernel_shutdown(void) __attribute__((destructor(101)));
    57 
    58 //-----------------------------------------------------------------------------
    59 // Global state
    60 
    61 thread_local processor * this_processor;
    62 
    63 processor * get_this_processor() {
    64         return this_processor;
    65 }
    66 
    67 coroutine * this_coroutine(void) {
    68         return this_processor->current_coroutine;
    69 }
    70 
    71 thread_h * this_thread(void) {
    72         return this_processor->current_thread;
    73 }
    74 
    75156//-----------------------------------------------------------------------------
    76157// Main thread construction
    77 struct current_stack_info_t {
     158struct mainThread_info_t {
    78159        machine_context_t ctx; 
    79160        unsigned int size;              // size of stack
     
    85166};
    86167
    87 void ?{}( current_stack_info_t * this ) {
     168void ?{}( mainThread_info_t * this ) {
    88169        CtxGet( &this->ctx );
    89170        this->base = this->ctx.FP;
     
    99180}
    100181
    101 void ?{}( coStack_t * this, current_stack_info_t * info) {
     182void ?{}( coStack_t * this, mainThread_info_t * info) {
    102183        this->size = info->size;
    103184        this->storage = info->storage;
     
    109190}
    110191
    111 void ?{}( coroutine * this, current_stack_info_t * info) {
     192void ?{}( coroutine * this, mainThread_info_t * info) {
    112193        (&this->stack){ info };
    113194        this->name = "Main Thread";
     
    117198}
    118199
    119 void ?{}( thread_h * this, current_stack_info_t * info) {
     200void ?{}( thread_h * this, mainThread_info_t * info) {
    120201        (&this->c){ info };
    121 }
    122 
    123 //-----------------------------------------------------------------------------
    124 // Processor coroutine
    125 void ?{}(processorCtx_t * this, processor * proc) {
    126         (&this->c){};
    127         this->proc = proc;
    128         proc->ctx = this;
    129 }
    130 
    131 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {
    132         (&this->c){ info };
    133         this->proc = proc;
    134         proc->ctx = this;
    135 }
    136 
    137 void start(processor * this);
    138 
    139 void ?{}(processor * this) {
    140         this{ systemCluster };
    141 }
    142 
    143 void ?{}(processor * this, cluster * cltr) {
    144         this->cltr = cltr;
    145         this->current_coroutine = NULL;
    146         this->current_thread = NULL;
    147         (&this->lock){};
    148         this->terminated = false;
    149 
    150         start( this );
    151 }
    152 
    153 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) {
    154         this->cltr = cltr;
    155         this->current_coroutine = NULL;
    156         this->current_thread = NULL;
    157         (&this->lock){};
    158         this->terminated = false;
    159 
    160         this->ctx = ctx;
    161         LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx);
    162         ctx{ this };
    163 }
    164 
    165 void ^?{}(processor * this) {
    166         if( ! this->terminated ) {
    167                 LIB_DEBUG_PRINTF("Kernel : core %p signaling termination\n", this);
    168                 this->terminated = true;
    169                 lock( &this->lock );
    170         }
    171 }
    172 
    173 void ?{}(cluster * this) {
    174         ( &this->ready_queue ){};
    175         pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );
    176 }
    177 
    178 void ^?{}(cluster * this) {
    179         pthread_spin_destroy( &this->lock );
    180 }
    181 
    182 //-----------------------------------------------------------------------------
    183 // Processor running routines
    184 void main(processorCtx_t * ctx);
    185 thread_h * nextThread(cluster * this);
    186 void runThread(processor * this, thread_h * dst);
    187 void spin(processor * this, unsigned int * spin_count);
    188 
    189 void main(processorCtx_t * ctx) {
    190         processor * this = ctx->proc;
    191         LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);
    192 
    193         thread_h * readyThread = NULL;
    194         for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {
    195                
    196                 readyThread = nextThread( this->cltr );
    197 
    198                 if(readyThread) {
    199                         runThread(this, readyThread);
    200                         spin_count = 0;
    201                 } else {
    202                         spin(this, &spin_count);
    203                 }               
    204         }
    205 
    206         LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this);
    207         unlock( &this->lock );
    208         LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);
    209 }
    210 
    211 void runThread(processor * this, thread_h * dst) {
    212         coroutine * proc_ctx = get_coroutine(this->ctx);
    213         coroutine * thrd_ctx = get_coroutine(dst);
    214         thrd_ctx->last = proc_ctx;
    215 
    216         // context switch to specified coroutine
    217         // Which is now the current_coroutine
    218         // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
    219         this->current_thread = dst;
    220         this->current_coroutine = thrd_ctx;
    221         CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
    222         this->current_coroutine = proc_ctx;
    223         // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
    224 
    225         // when CtxSwitch returns we are back in the processor coroutine
    226 }
    227 
    228 void spin(processor * this, unsigned int * spin_count) {
    229         (*spin_count)++;
    230 }
    231 
    232 void * CtxInvokeProcessor(void * arg) {
    233         processor * proc = (processor *) arg;
    234         this_processor = proc;
    235         // SKULLDUGGERY: We want to create a context for the processor coroutine
    236         // which is needed for the 2-step context switch. However, there is no reason
    237         // to waste the perfectly valid stack create by pthread.
    238         current_stack_info_t info;
    239         machine_context_t ctx;
    240         info.context = &ctx;
    241         processorCtx_t proc_cor_storage = { proc, &info };
    242 
    243         proc->current_coroutine = &proc->ctx->c;
    244         proc->current_thread = NULL;
    245 
    246         LIB_DEBUG_PRINTF("Kernel : core %p created (%p)\n", proc, proc->ctx);
    247 
    248         // LIB_DEBUG_PRINTF("Kernel : core    base : %p \n", info.base );
    249         // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage );
    250         // LIB_DEBUG_PRINTF("Kernel : core    size : %x \n", info.size );
    251         // LIB_DEBUG_PRINTF("Kernel : core   limit : %p \n", info.limit );
    252         // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context );
    253         // LIB_DEBUG_PRINTF("Kernel : core     top : %p \n", info.top );
    254 
    255         //We now have a proper context from which to schedule threads
    256 
    257         // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
    258         // resume it to start it like it normally would, it will just context switch
    259         // back to here. Instead directly call the main since we already are on the
    260         // appropriate stack.
    261         proc_cor_storage.c.state = Active;
    262       main( &proc_cor_storage );
    263       proc_cor_storage.c.state = Halt;
    264       proc_cor_storage.c.notHalted = false;
    265 
    266         LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->ctx);       
    267 
    268         return NULL;
    269 }
    270 
    271 void start(processor * this) {
    272         LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this);
    273        
    274         pthread_attr_t attributes;
    275         pthread_attr_init( &attributes );
    276 
    277         pthread_create( &this->kernel_thread, &attributes, CtxInvokeProcessor, (void*)this );
    278 
    279         pthread_attr_destroy( &attributes );
    280 
    281         LIB_DEBUG_PRINTF("Kernel : core %p started\n", this);   
    282 }
    283 
    284 //-----------------------------------------------------------------------------
    285 // Scheduler routines
    286 void thread_schedule( thread_h * thrd ) {
    287         assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    288        
    289         pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };
    290         append( &systemProcessor->cltr->ready_queue, thrd );
    291 }
    292 
    293 thread_h * nextThread(cluster * this) {
    294         pthread_spinlock_guard guard = { &this->lock };
    295         return pop_head( &this->ready_queue );
    296202}
    297203
     
    304210        LIB_DEBUG_PRINTF("Kernel : Starting\n");       
    305211
    306         current_stack_info_t info;
    307 
    308         // LIB_DEBUG_PRINTF("Kernel : core    base : %p \n", info.base );
    309         // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage );
    310         // LIB_DEBUG_PRINTF("Kernel : core    size : %x \n", info.size );
    311         // LIB_DEBUG_PRINTF("Kernel : core   limit : %p \n", info.limit );
    312         // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context );
    313         // LIB_DEBUG_PRINTF("Kernel : core     top : %p \n", info.top );
     212        mainThread_info_t ctx;
    314213
    315214        // Start by initializing the main thread
    316215        mainThread = (thread_h *)&mainThread_storage;
    317         mainThread{ &info };
     216        mainThread{ &ctx };
    318217
    319218        // Initialize the system cluster
     
    321220        systemCluster{};
    322221
    323         // Initialize the system processor and the system processor ctx
     222        // Initialize the system processor
     223        systemProcessor = (processor *)&systemProcessor_storage;
     224        systemProcessor{ systemCluster };
     225
     226        // Initialize the system processor ctx
    324227        // (the coroutine that contains the processing control flow)
    325         systemProcessor = (processor *)&systemProcessor_storage;
    326         systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
     228        systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage;
     229        systemProcessor->ctx{ systemProcessor };
    327230
    328231        // Add the main thread to the ready queue
     
    383286
    384287void lock( simple_lock * this ) {
    385         {
    386                 pthread_spinlock_guard guard = { &systemCluster->lock };        //HUGE TEMP HACK which only works if we have a single cluster and is stupid
    387                 append( &this->blocked, this_thread() );
    388         }
     288        append( &this->blocked, this_thread() );
    389289        suspend();
    390290}
  • src/libcfa/concurrency/threads

    rad6343e r4a9ccc3  
    2727// Anything that implements this trait can be resumed.
    2828// Anything that is resumed is a coroutine.
    29 trait is_thread(dtype T | sized(T)) {
     29trait is_thread(dtype T /*| sized(T)*/) {
    3030      void main(T* this);
    3131      thread_h* get_thread(T* this);
     32        /*void ?{}(T*);
     33        void ^?{}(T*);*/
    3234};
    3335
    3436#define DECL_THREAD(X) static inline thread_h* get_thread(X* this) { return &this->t; } void main(X* this);
    3537
    36 forall( dtype T | sized(T) | is_thread(T) )
     38forall(otype T | is_thread(T) )
    3739static inline coroutine* get_coroutine(T* this) {
    3840        return &get_thread(this)->c;
     
    5355// thread runner
    5456// Structure that actually start and stop threads
    55 forall( dtype T | sized(T) | is_thread(T) )
     57forall(otype T | is_thread(T) )
    5658struct thread {
    5759        T handle;
    5860};
    5961
    60 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T*); } )
     62forall(otype T | is_thread(T) )
    6163void ?{}( thread(T)* this );
    6264
    63 forall( dtype T, ttype P | sized(T) | is_thread(T) | { void ?{}(T*, P); } )
     65forall(otype T, ttype P | is_thread(T) | { void ?{}(T*, P); } )
    6466void ?{}( thread(T)* this, P params );
    6567
    66 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); } )
     68forall(otype T | is_thread(T) )
    6769void ^?{}( thread(T)* this );
    6870
  • src/libcfa/concurrency/threads.c

    rad6343e r4a9ccc3  
    2727}
    2828
    29 extern processor * get_this_processor();
     29/*thread_local*/ extern processor * this_processor;
    3030
    3131//-----------------------------------------------------------------------------
    3232// Forward declarations
    33 forall( dtype T | sized(T) | is_thread(T) )
     33forall(otype T | is_thread(T) )
    3434void start( T* this );
    3535
    36 forall( dtype T | sized(T) | is_thread(T) )
     36forall(otype T | is_thread(T) )
    3737void stop( T* this );
    3838
     
    4242void ?{}(thread_h* this) {
    4343        (&this->c){};
    44         this->c.name = "Anonymous Coroutine";
    4544        (&this->lock){};
    4645        this->next = NULL;
     
    5150}
    5251
    53 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T*); } )
     52forall(otype T | is_thread(T) )
    5453void ?{}( thread(T)* this ) {
    5554        (&this->handle){};
     
    5756}
    5857
    59 forall( dtype T, ttype P | sized(T) | is_thread(T) | { void ?{}(T*, P); } )
     58forall(otype T, ttype P | is_thread(T) | { void ?{}(T*, P); } )
    6059void ?{}( thread(T)* this, P params ) {
    6160        (&this->handle){ params };
     
    6362}
    6463
    65 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); } )
     64forall(otype T | is_thread(T) )
    6665void ^?{}( thread(T)* this ) {
    6766        stop(&this->handle);
     
    7877extern void thread_schedule( thread_h * );
    7978
    80 forall( dtype T | sized(T) | is_thread(T) )
     79forall(otype T | is_thread(T))
    8180void start( T* this ) {
    8281        coroutine* thrd_c = get_coroutine(this);
    8382        thread_h*  thrd_h = get_thread   (this);
    8483        thrd_c->last = this_coroutine();
    85         get_this_processor()->current_coroutine = thrd_c;
     84        this_processor->current_coroutine = thrd_c;
    8685
    8786        // LIB_DEBUG_PRINTF("Thread start : %p (t %p, c %p)\n", handle, thrd_c, thrd_h);
     
    9493}
    9594
    96 forall( dtype T | sized(T) | is_thread(T) )
     95forall(otype T | is_thread(T) )
    9796void stop( T* this ) {
    9897        thread_h*  thrd = get_thread(this);
Note: See TracChangeset for help on using the changeset viewer.