Ignore:
Timestamp:
Feb 14, 2017, 1:19:28 PM (9 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
97d246d
Parents:
f923b5f (diff), eafb094 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
src/libcfa/concurrency
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/coroutines

    rf923b5f rd3a804f5  
    3636void ?{}(coStack_t * this);
    3737void ?{}(coroutine * this);
     38void ?{}(coroutine * this, const char * name);
    3839void ^?{}(coStack_t * this);
    3940void ^?{}(coroutine * this);
     
    7677                "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    7778                src->name, src );
    78         assertf( src->last->notHalted,
     79        assertf( src->last->state != Halted,
    7980                "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
    8081                "Possible cause is terminated coroutine's main routine has already returned.",
     
    9798      // not resuming self ?
    9899        if ( src != dst ) {
    99                 assertf( dst->notHalted ,
     100                assertf( dst->state != Halted ,
    100101                        "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
    101102                        "Possible cause is terminated coroutine's main routine has already returned.",
     
    115116      // not resuming self ?
    116117        if ( src != dst ) {
    117                 assertf( dst->notHalted ,
     118                assertf( dst->state != Halted ,
    118119                        "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
    119120                        "Possible cause is terminated coroutine's main routine has already returned.",
  • src/libcfa/concurrency/coroutines.c

    rf923b5f rd3a804f5  
    6161
    6262void ?{}(coroutine* this) {
    63         this->name = "Anonymous Coroutine";
     63        this{ "Anonymous Coroutine" };
     64}
     65
     66void ?{}(coroutine* this, const char * name) {
     67        this->name = name;
    6468        this->errno_ = 0;
    6569        this->state = Start;
    66       this->notHalted = true;
    6770        this->starter = NULL;
    6871        this->last = NULL;
  • src/libcfa/concurrency/invoke.c

    rf923b5f rd3a804f5  
    4848      main( this );
    4949
    50       cor->state = Halt;
    51       cor->notHalted = false;
     50      cor->state = Halted;
    5251
    5352      //Final suspend, should never return
  • src/libcfa/concurrency/invoke.h

    rf923b5f rd3a804f5  
    3030      #define SCHEDULER_CAPACITY 10
    3131
     32      struct spinlock {
     33            volatile int lock;
     34      };
     35
    3236      struct simple_thread_list {
    3337            struct thread * head;
    3438            struct thread ** tail;
     39      };
     40
     41      struct signal_once {
     42            volatile bool condition;
     43            struct spinlock lock;
     44            struct simple_thread_list blocked;
    3545      };
    3646
     
    4050            void append( struct simple_thread_list *, struct thread * );
    4151            struct thread * pop_head( struct simple_thread_list * );
     52
     53            void ?{}(spinlock * this);
     54            void ^?{}(spinlock * this);
     55
     56            void ?{}(signal_once * this);
     57            void ^?{}(signal_once * this);
    4258      }
    4359      #endif
     
    5369      };
    5470
    55       enum coroutine_state { Start, Inactive, Active, Halt, Primed };
     71      enum coroutine_state { Halted, Start, Inactive, Active, Primed };
    5672
    5773      struct coroutine {
     
    6076            int errno_;                         // copy of global UNIX variable errno
    6177            enum coroutine_state state; // current execution status for coroutine
    62             bool notHalted;                     // indicate if execuation state is not halted
    63 
    6478            struct coroutine *starter;  // first coroutine to resume this one
    6579            struct coroutine *last;             // last coroutine to resume this one
    6680      };
    6781
    68       struct simple_lock {
    69         struct simple_thread_list blocked;
    70       };
    71 
    7282      struct thread {
    73             struct coroutine c;
    74             struct simple_lock lock;
    75             struct thread * next;
     83            struct coroutine c;           // coroutine body used to store context
     84            struct signal_once terminated;// indicate if execuation state is not halted
     85            struct thread * next;         // instrusive link field for threads
    7686      };
    7787
  • src/libcfa/concurrency/kernel

    rf923b5f rd3a804f5  
    99//
    1010// Author           : Thierry Delisle
    11 // Created On       : Tue Jan 17 12:27:26 2016
     11// Created On       : Tue Jan 17 12:27:26 2017
    1212// Last Modified By : Thierry Delisle
    1313// Last Modified On : --
     
    2727
    2828//-----------------------------------------------------------------------------
     29// Locks
     30void lock( spinlock * );
     31void unlock( spinlock * );
     32
     33void wait( signal_once * );
     34void signal( signal_once * );
     35
     36//-----------------------------------------------------------------------------
    2937// Cluster
    3038struct cluster {
    3139        simple_thread_list ready_queue;
    32         pthread_spinlock_t lock;
     40        spinlock lock;
    3341};
    3442
     
    3846//-----------------------------------------------------------------------------
    3947// Processor
     48enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule };
     49struct FinishAction {
     50        FinishOpCode action_code;
     51        thread * thrd;
     52        spinlock * lock;
     53};
     54static inline void ?{}(FinishAction * this) {
     55        this->action_code = No_Action;
     56        this->thrd = NULL;
     57        this->lock = NULL;
     58}
     59static inline void ^?{}(FinishAction * this) {}
     60
    4061struct processor {
    41         struct processorCtx_t * ctx;
     62        struct processorCtx_t * runner;
    4263        cluster * cltr;
    4364        coroutine * current_coroutine;
    4465        thread * current_thread;
    4566        pthread_t kernel_thread;
    46         simple_lock lock;
    47         volatile bool terminated;
     67       
     68        signal_once terminated;
     69        volatile bool is_terminated;
     70
     71        struct FinishAction finish;
    4872};
    4973
     
    5175void ?{}(processor * this, cluster * cltr);
    5276void ^?{}(processor * this);
    53 
    54 
    55 //-----------------------------------------------------------------------------
    56 // Locks
    57 
    58 void ?{}(simple_lock * this);
    59 void ^?{}(simple_lock * this);
    60 
    61 void lock( simple_lock * );
    62 void unlock( simple_lock * );
    63 
    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 // }
    10077
    10178#endif //KERNEL_H
  • src/libcfa/concurrency/kernel.c

    rf923b5f rd3a804f5  
    99//
    1010// Author           : Thierry Delisle
    11 // Created On       : Tue Jan 17 12:27:26 2016
     11// Created On       : Tue Jan 17 12:27:26 2017
    1212// Last Modified By : Thierry Delisle
    1313// Last Modified On : --
     
    2020
    2121//Header
    22 #include "kernel"
     22#include "kernel_private.h"
    2323
    2424//C Includes
    2525#include <stddef.h>
    2626extern "C" {
     27#include <fenv.h>
    2728#include <sys/resource.h>
    2829}
     
    3031//CFA Includes
    3132#include "libhdr.h"
    32 #include "threads"
    3333
    3434//Private includes
     
    3838//-----------------------------------------------------------------------------
    3939// Kernel storage
    40 struct processorCtx_t {
    41         processor * proc;
    42         coroutine c;
    43 };
    44 
    45 DECL_COROUTINE(processorCtx_t);
    46 
    4740#define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
    4841
     
    9285
    9386        rlimit r;
    94         int ret = getrlimit( RLIMIT_STACK, &r);
     87        getrlimit( RLIMIT_STACK, &r);
    9588        this->size = r.rlim_cur;
    9689
     
    114107        this->name = "Main Thread";
    115108        this->errno_ = 0;
    116         this->state = Inactive;
    117         this->notHalted = true;
     109        this->state = Start;
    118110}
    119111
     
    127119        (&this->c){};
    128120        this->proc = proc;
    129         proc->ctx = this;
     121        proc->runner = this;
    130122}
    131123
     
    133125        (&this->c){ info };
    134126        this->proc = proc;
    135         proc->ctx = this;
    136 }
    137 
    138 void start(processor * this);
     127        proc->runner = this;
     128}
    139129
    140130void ?{}(processor * this) {
     
    146136        this->current_coroutine = NULL;
    147137        this->current_thread = NULL;
    148         (&this->lock){};
    149         this->terminated = false;
     138        (&this->terminated){};
     139        this->is_terminated = false;
    150140
    151141        start( this );
    152142}
    153143
    154 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) {
     144void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    155145        this->cltr = cltr;
    156146        this->current_coroutine = NULL;
    157147        this->current_thread = NULL;
    158         (&this->lock){};
    159         this->terminated = false;
    160 
    161         this->ctx = ctx;
    162         LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx);
    163         ctx{ this };
     148        (&this->terminated){};
     149        this->is_terminated = false;
     150
     151        this->runner = runner;
     152        LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", runner);
     153        runner{ this };
    164154}
    165155
    166156void ^?{}(processor * this) {
    167         if( ! this->terminated ) {
     157        if( ! this->is_terminated ) {
    168158                LIB_DEBUG_PRINTF("Kernel : core %p signaling termination\n", this);
    169                 this->terminated = true;
    170                 lock( &this->lock );
     159                this->is_terminated = true;
     160                wait( &this->terminated );
    171161        }
    172162}
     
    174164void ?{}(cluster * this) {
    175165        ( &this->ready_queue ){};
    176         pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );
     166        ( &this->lock ){};
    177167}
    178168
    179169void ^?{}(cluster * this) {
    180         pthread_spin_destroy( &this->lock );
    181 }
    182 
    183 //-----------------------------------------------------------------------------
    184 // Processor running routines
    185 void main(processorCtx_t * ctx);
    186 thread * nextThread(cluster * this);
    187 void scheduleInternal(processor * this, thread * dst);
    188 void spin(processor * this, unsigned int * spin_count);
    189 
    190 void main(processorCtx_t * ctx) {
    191         processor * this = ctx->proc;
     170       
     171}
     172
     173//=============================================================================================
     174// Kernel Scheduling logic
     175//=============================================================================================
     176//Main of the processor contexts
     177void main(processorCtx_t * runner) {
     178        processor * this = runner->proc;
    192179        LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);
    193180
    194181        thread * readyThread = NULL;
    195         for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {
    196                
     182        for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     183        {
    197184                readyThread = nextThread( this->cltr );
    198185
    199                 if(readyThread) {
    200                         scheduleInternal(this, readyThread);
     186                if(readyThread)
     187                {
     188                        runThread(this, readyThread);
     189
     190                        //Some actions need to be taken from the kernel
     191                        finishRunning(this);
     192
    201193                        spin_count = 0;
    202                 } else {
     194                }
     195                else
     196                {
    203197                        spin(this, &spin_count);
    204198                }               
     
    206200
    207201        LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this);
    208         unlock( &this->lock );
     202        signal( &this->terminated );
    209203        LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);
    210204}
    211205
    212 //Declarations for scheduleInternal
    213 extern void ThreadCtxSwitch(coroutine * src, coroutine * dst);
    214 
    215 // scheduleInternal runs a thread by context switching
     206// runThread runs a thread by context switching
    216207// from the processor coroutine to the target thread
    217 void scheduleInternal(processor * this, thread * dst) {
    218         // coroutine * proc_ctx = get_coroutine(this->ctx);
    219         // coroutine * thrd_ctx = get_coroutine(dst);
    220 
    221         // //Update global state
    222         // this->current_thread = dst;
    223 
    224         // // Context Switch to the thread
    225         // ThreadCtxSwitch(proc_ctx, thrd_ctx);
    226         // // when ThreadCtxSwitch returns we are back in the processor coroutine
    227 
    228         coroutine * proc_ctx = get_coroutine(this->ctx);
    229         coroutine * thrd_ctx = get_coroutine(dst);
    230       thrd_ctx->last = proc_ctx;
    231  
    232       // context switch to specified coroutine
    233       // Which is now the current_coroutine
    234       LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
    235       this->current_thread = dst;
    236       this->current_coroutine = thrd_ctx;
    237       CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
    238       this->current_coroutine = proc_ctx;
    239       LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
    240  
    241       // when CtxSwitch returns we are back in the processor coroutine
     208void runThread(processor * this, thread * dst) {
     209        coroutine * proc_cor = get_coroutine(this->runner);
     210        coroutine * thrd_cor = get_coroutine(dst);
     211       
     212        //Reset the terminating actions here
     213        this->finish.action_code = No_Action;
     214
     215        //Update global state
     216        this->current_thread = dst;
     217
     218        // Context Switch to the thread
     219        ThreadCtxSwitch(proc_cor, thrd_cor);
     220        // when ThreadCtxSwitch returns we are back in the processor coroutine
     221}
     222
     223// Once a thread has finished running, some of
     224// its final actions must be executed from the kernel
     225void finishRunning(processor * this) {
     226        if( this->finish.action_code == Release ) {
     227                unlock( this->finish.lock );
     228        }
     229        else if( this->finish.action_code == Schedule ) {
     230                ScheduleThread( this->finish.thrd );
     231        }
     232        else if( this->finish.action_code == Release_Schedule ) {
     233                unlock( this->finish.lock );           
     234                ScheduleThread( this->finish.thrd );
     235        }
     236        else {
     237                assert(this->finish.action_code == No_Action);
     238        }
    242239}
    243240
     
    262259        processorCtx_t proc_cor_storage = { proc, &info };
    263260
     261        LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage.c.stack.base);
     262
    264263        //Set global state
    265         proc->current_coroutine = &proc->ctx->c;
     264        proc->current_coroutine = &proc->runner->c;
    266265        proc->current_thread = NULL;
    267266
    268267        //We now have a proper context from which to schedule threads
    269         LIB_DEBUG_PRINTF("Kernel : core %p created (%p)\n", proc, proc->ctx);
     268        LIB_DEBUG_PRINTF("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    270269
    271270        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     
    275274        proc_cor_storage.c.state = Active;
    276275      main( &proc_cor_storage );
    277       proc_cor_storage.c.state = Halt;
    278       proc_cor_storage.c.notHalted = false;
     276      proc_cor_storage.c.state = Halted;
    279277
    280278        // Main routine of the core returned, the core is now fully terminated
    281         LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->ctx);       
     279        LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->runner);     
    282280
    283281        return NULL;
     
    287285        LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this);
    288286       
    289         pthread_attr_t attributes;
    290         pthread_attr_init( &attributes );
    291 
    292         pthread_create( &this->kernel_thread, &attributes, CtxInvokeProcessor, (void*)this );
    293 
    294         pthread_attr_destroy( &attributes );
     287        // pthread_attr_t attributes;
     288        // pthread_attr_init( &attributes );
     289
     290        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
     291
     292        // pthread_attr_destroy( &attributes );
    295293
    296294        LIB_DEBUG_PRINTF("Kernel : core %p started\n", this);   
     
    299297//-----------------------------------------------------------------------------
    300298// Scheduler routines
    301 void thread_schedule( thread * thrd ) {
     299void ScheduleThread( thread * thrd ) {
    302300        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    303301       
    304         pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };
     302        lock( &systemProcessor->cltr->lock );
    305303        append( &systemProcessor->cltr->ready_queue, thrd );
     304        unlock( &systemProcessor->cltr->lock );
    306305}
    307306
    308307thread * nextThread(cluster * this) {
    309         pthread_spinlock_guard guard = { &this->lock };
    310         return pop_head( &this->ready_queue );
     308        lock( &this->lock );
     309        thread * head = pop_head( &this->ready_queue );
     310        unlock( &this->lock );
     311        return head;
     312}
     313
     314void ScheduleInternal() {
     315        suspend();
     316}
     317
     318void ScheduleInternal( spinlock * lock ) {
     319        get_this_processor()->finish.action_code = Release;
     320        get_this_processor()->finish.lock = lock;
     321        suspend();
     322}
     323
     324void ScheduleInternal( thread * thrd ) {
     325        get_this_processor()->finish.action_code = Schedule;
     326        get_this_processor()->finish.thrd = thrd;
     327        suspend();
     328}
     329
     330void ScheduleInternal( spinlock * lock, thread * thrd ) {
     331        get_this_processor()->finish.action_code = Release_Schedule;
     332        get_this_processor()->finish.lock = lock;
     333        get_this_processor()->finish.thrd = thrd;
     334        suspend();
    311335}
    312336
     
    314338// Kernel boot procedures
    315339void kernel_startup(void) {
    316 
     340        LIB_DEBUG_PRINTF("Kernel : Starting\n");       
     341
     342        // Start by initializing the main thread
    317343        // SKULLDUGGERY: the mainThread steals the process main thread
    318344        // which will then be scheduled by the systemProcessor normally
    319         LIB_DEBUG_PRINTF("Kernel : Starting\n");       
    320 
     345        mainThread = (thread *)&mainThread_storage;
    321346        current_stack_info_t info;
    322 
    323         // LIB_DEBUG_PRINTF("Kernel : core    base : %p \n", info.base );
    324         // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage );
    325         // LIB_DEBUG_PRINTF("Kernel : core    size : %x \n", info.size );
    326         // LIB_DEBUG_PRINTF("Kernel : core   limit : %p \n", info.limit );
    327         // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context );
    328         // LIB_DEBUG_PRINTF("Kernel : core     top : %p \n", info.top );
    329 
    330         // Start by initializing the main thread
    331         mainThread = (thread *)&mainThread_storage;
    332347        mainThread{ &info };
    333348
     
    343358        // Add the main thread to the ready queue
    344359        // once resume is called on systemProcessor->ctx the mainThread needs to be scheduled like any normal thread
    345         thread_schedule(mainThread);
     360        ScheduleThread(mainThread);
    346361
    347362        //initialize the global state variables
     
    353368        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    354369        // mainThread is on the ready queue when this call is made.
    355         resume(systemProcessor->ctx);
     370        resume(systemProcessor->runner);
    356371
    357372
    358373
    359374        // THE SYSTEM IS NOW COMPLETELY RUNNING
    360 
    361 
    362 
    363375        LIB_DEBUG_PRINTF("Kernel : Started\n--------------------------------------------------\n\n");
    364376}
     
    370382        // When its coroutine terminates, it return control to the mainThread
    371383        // which is currently here
    372         systemProcessor->terminated = true;
     384        systemProcessor->is_terminated = true;
    373385        suspend();
    374386
     
    377389        // Destroy the system processor and its context in reverse order of construction
    378390        // These were manually constructed so we need manually destroy them
    379         ^(systemProcessor->ctx){};
     391        ^(systemProcessor->runner){};
    380392        ^(systemProcessor){};
    381393
     
    389401//-----------------------------------------------------------------------------
    390402// Locks
    391 void ?{}( simple_lock * this ) {
    392         ( &this->blocked ){};
    393 }
    394 
    395 void ^?{}( simple_lock * this ) {
    396 
    397 }
    398 
    399 void lock( simple_lock * this ) {
     403void ?{}( spinlock * this ) {
     404        this->lock = 0;
     405}
     406void ^?{}( spinlock * this ) {
     407
     408}
     409
     410void lock( spinlock * this ) {
     411        for ( unsigned int i = 1;; i += 1 ) {
     412                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
     413        }
     414}
     415
     416void unlock( spinlock * this ) {
     417        __sync_lock_release_4( &this->lock );
     418}
     419
     420void ?{}( signal_once * this ) {
     421        this->condition = false;
     422}
     423void ^?{}( signal_once * this ) {
     424
     425}
     426
     427void wait( signal_once * this ) {
     428        lock( &this->lock );
     429        if( !this->condition ) {
     430                append( &this->blocked, this_thread() );
     431                ScheduleInternal( &this->lock );
     432                lock( &this->lock );
     433        }
     434        unlock( &this->lock );
     435}
     436
     437void signal( signal_once * this ) {
     438        lock( &this->lock );
    400439        {
    401                 pthread_spinlock_guard guard = { &systemCluster->lock };        //HUGE TEMP HACK which only works if we have a single cluster and is stupid
    402                 append( &this->blocked, this_thread() );
    403         }
    404         suspend();
    405 }
    406 
    407 void unlock( simple_lock * this ) {
    408         thread * it;
    409         while( it = pop_head( &this->blocked) ) {
    410                 thread_schedule( it );
    411         }
     440                this->condition = true;
     441
     442                thread * it;
     443                while( it = pop_head( &this->blocked) ) {
     444                        ScheduleThread( it );
     445                }
     446        }
     447        unlock( &this->lock );
    412448}
    413449
  • src/libcfa/concurrency/threads.c

    rf923b5f rd3a804f5  
    1717#include "threads"
    1818
    19 #include "kernel"
     19#include "kernel_private.h"
    2020#include "libhdr.h"
    2121
     
    2424
    2525extern "C" {
     26        #include <fenv.h>
    2627        #include <stddef.h>
    2728}
     
    4344        (&this->c){};
    4445        this->c.name = "Anonymous Coroutine";
    45         (&this->lock){};
     46        (&this->terminated){};
    4647        this->next = NULL;
    4748}
     
    7172//-----------------------------------------------------------------------------
    7273// Starting and stopping threads
    73 extern "C" {
    74       forall(dtype T | is_thread(T))
    75       void CtxInvokeThread(T * this);
    76 }
    77 
    78 extern void thread_schedule( thread * );
    79 
    8074forall( dtype T | is_thread(T) )
    8175void start( T* this ) {
     
    9185        CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
    9286
    93         LIB_DEBUG_PRINTF("Thread started : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
    94 
    95         thread_schedule(thrd_h);
     87        ScheduleThread(thrd_h);
    9688}
    9789
    9890forall( dtype T | is_thread(T) )
    9991void stop( T* this ) {
    100         thread*  thrd = get_thread(this);
    101         if( thrd->c.notHalted ) {
    102                 lock( &thrd->lock );
    103         }
     92        wait( & get_thread(this)->terminated );
    10493}
    10594
    10695void yield( void ) {
    107         thread_schedule( this_thread() );
    108         suspend();
     96        ScheduleInternal( get_this_processor()->current_thread );
    10997}
    11098
    11199void ThreadCtxSwitch(coroutine* src, coroutine* dst) {
     100        // set state of current coroutine to inactive
     101        src->state = Inactive;
     102        dst->state = Active;
     103
     104        //update the last resumer
    112105        dst->last = src;
    113106
    114         // set state of current coroutine to inactive
    115         src->state = Inactive;
    116 
    117         // set new coroutine that task is executing
     107        // set new coroutine that the processor is executing
     108        // and context switch to it
    118109        get_this_processor()->current_coroutine = dst; 
    119 
    120         // context switch to specified coroutine
    121110        CtxSwitch( src->stack.context, dst->stack.context );
    122         // when CtxSwitch returns we are back in the src coroutine
     111        get_this_processor()->current_coroutine = src; 
    123112
    124113        // set state of new coroutine to active
     114        dst->state = Inactive;
    125115        src->state = Active;
    126116}
     
    130120extern "C" {
    131121        void __thread_signal_termination( thread * this ) {
    132                 this->c.state = Halt;
    133                 this->c.notHalted = false;
    134                 unlock( &this->lock );
     122                this->c.state = Halted;
     123                LIB_DEBUG_PRINTF("Thread end : %p\n", this);
     124                signal( &this->terminated );   
    135125        }
    136126}
Note: See TracChangeset for help on using the changeset viewer.