Changeset 8fcbb4c for src


Ignore:
Timestamp:
Feb 9, 2017, 4:51:40 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
8d4f7fe
Parents:
84e2523
Message:

removed pthread_spinlock_t and fixed race condition in yield

Location:
src/libcfa/concurrency
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/kernel

    r84e2523 r8fcbb4c  
    3030struct cluster {
    3131        simple_thread_list ready_queue;
    32         pthread_spinlock_t lock;
     32        // pthread_spinlock_t lock;
    3333};
    3434
     
    3838//-----------------------------------------------------------------------------
    3939// Processor
     40enum ProcessorAction {
     41        Reschedule,
     42        NoAction
     43};
     44
    4045struct processor {
    41         struct processorCtx_t * ctx;
     46        struct processorCtx_t * runner;
    4247        cluster * cltr;
    4348        coroutine * current_coroutine;
     
    4651        simple_lock lock;
    4752        volatile bool terminated;
     53        ProcessorAction thread_action;
    4854};
    4955
  • src/libcfa/concurrency/kernel.c

    r84e2523 r8fcbb4c  
    2525#include <stddef.h>
    2626extern "C" {
     27#include <fenv.h>
    2728#include <sys/resource.h>
    2829}
     
    3536#define __CFA_INVOKE_PRIVATE__
    3637#include "invoke.h"
     38
     39static volatile int lock;
     40
     41void spin_lock( volatile int *lock ) {
     42        for ( unsigned int i = 1;; i += 1 ) {
     43          if ( *lock == 0 && __sync_lock_test_and_set_4( lock, 1 ) == 0 ) break;
     44        }
     45}
     46
     47void spin_unlock( volatile int *lock ) {
     48        __sync_lock_release_4( lock );
     49}
    3750
    3851//-----------------------------------------------------------------------------
     
    127140        (&this->c){};
    128141        this->proc = proc;
    129         proc->ctx = this;
     142        proc->runner = this;
    130143}
    131144
     
    133146        (&this->c){ info };
    134147        this->proc = proc;
    135         proc->ctx = this;
     148        proc->runner = this;
    136149}
    137150
     
    152165}
    153166
    154 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) {
     167void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    155168        this->cltr = cltr;
    156169        this->current_coroutine = NULL;
     
    159172        this->terminated = false;
    160173
    161         this->ctx = ctx;
    162         LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx);
    163         ctx{ this };
     174        this->runner = runner;
     175        LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", runner);
     176        runner{ this };
    164177}
    165178
     
    174187void ?{}(cluster * this) {
    175188        ( &this->ready_queue ){};
    176         pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );
     189        lock = 0;
    177190}
    178191
    179192void ^?{}(cluster * this) {
    180         pthread_spin_destroy( &this->lock );
     193       
    181194}
    182195
    183196//-----------------------------------------------------------------------------
    184197// Processor running routines
    185 void main(processorCtx_t * ctx);
     198void main(processorCtx_t *);
    186199thread * nextThread(cluster * this);
    187200void scheduleInternal(processor * this, thread * dst);
    188201void spin(processor * this, unsigned int * spin_count);
    189 
    190 void main(processorCtx_t * ctx) {
    191         processor * this = ctx->proc;
     202void thread_schedule( thread * thrd );
     203
     204//Main of the processor contexts
     205void main(processorCtx_t * runner) {
     206        processor * this = runner->proc;
    192207        LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);
     208
     209        fenv_t envp;
     210        fegetenv( &envp );
     211        LIB_DEBUG_PRINTF("Kernel : mxcsr %x\n", envp.__mxcsr);
    193212
    194213        thread * readyThread = NULL;
     
    216235// from the processor coroutine to the target thread
    217236void scheduleInternal(processor * this, thread * dst) {
     237        this->thread_action = NoAction;
     238
    218239        // coroutine * proc_ctx = get_coroutine(this->ctx);
    219240        // coroutine * thrd_ctx = get_coroutine(dst);
     
    226247        // // when ThreadCtxSwitch returns we are back in the processor coroutine
    227248
    228         coroutine * proc_ctx = get_coroutine(this->ctx);
     249        coroutine * proc_ctx = get_coroutine(this->runner);
    229250        coroutine * thrd_ctx = get_coroutine(dst);
    230251      thrd_ctx->last = proc_ctx;
     
    232253      // context switch to specified coroutine
    233254      // 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);
     255      // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
    235256      this->current_thread = dst;
    236257      this->current_coroutine = thrd_ctx;
    237258      CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
    238259      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);
     260      // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
    240261 
    241262      // when CtxSwitch returns we are back in the processor coroutine
     263        if(this->thread_action == Reschedule) {
     264                thread_schedule( dst );
     265        }
    242266}
    243267
     
    262286        processorCtx_t proc_cor_storage = { proc, &info };
    263287
     288        LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage.c.stack.base);
     289
    264290        //Set global state
    265         proc->current_coroutine = &proc->ctx->c;
     291        proc->current_coroutine = &proc->runner->c;
    266292        proc->current_thread = NULL;
    267293
    268294        //We now have a proper context from which to schedule threads
    269         LIB_DEBUG_PRINTF("Kernel : core %p created (%p)\n", proc, proc->ctx);
     295        LIB_DEBUG_PRINTF("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    270296
    271297        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     
    279305
    280306        // 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);       
     307        LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->runner);     
    282308
    283309        return NULL;
     
    287313        LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this);
    288314       
    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 );
     315        // pthread_attr_t attributes;
     316        // pthread_attr_init( &attributes );
     317
     318        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
     319
     320        // pthread_attr_destroy( &attributes );
    295321
    296322        LIB_DEBUG_PRINTF("Kernel : core %p started\n", this);   
     
    302328        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    303329       
    304         pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };
     330        spin_lock( &lock );
    305331        append( &systemProcessor->cltr->ready_queue, thrd );
     332        spin_unlock( &lock );
    306333}
    307334
    308335thread * nextThread(cluster * this) {
    309         pthread_spinlock_guard guard = { &this->lock };
    310         return pop_head( &this->ready_queue );
     336        spin_lock( &lock );
     337        thread * head = pop_head( &this->ready_queue );
     338        spin_unlock( &lock );
     339        return head;
    311340}
    312341
     
    314343// Kernel boot procedures
    315344void kernel_startup(void) {
    316 
     345        LIB_DEBUG_PRINTF("Kernel : Starting\n");       
     346
     347        // Start by initializing the main thread
    317348        // SKULLDUGGERY: the mainThread steals the process main thread
    318349        // which will then be scheduled by the systemProcessor normally
    319         LIB_DEBUG_PRINTF("Kernel : Starting\n");       
    320 
     350        mainThread = (thread *)&mainThread_storage;
    321351        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;
    332352        mainThread{ &info };
    333353
     
    353373        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    354374        // mainThread is on the ready queue when this call is made.
    355         resume(systemProcessor->ctx);
     375        resume(systemProcessor->runner);
    356376
    357377
    358378
    359379        // THE SYSTEM IS NOW COMPLETELY RUNNING
    360 
    361 
    362 
    363380        LIB_DEBUG_PRINTF("Kernel : Started\n--------------------------------------------------\n\n");
    364381}
     
    377394        // Destroy the system processor and its context in reverse order of construction
    378395        // These were manually constructed so we need manually destroy them
    379         ^(systemProcessor->ctx){};
     396        ^(systemProcessor->runner){};
    380397        ^(systemProcessor){};
    381398
     
    399416void lock( simple_lock * this ) {
    400417        {
    401                 pthread_spinlock_guard guard = { &systemCluster->lock };        //HUGE TEMP HACK which only works if we have a single cluster and is stupid
     418                spin_lock( &lock );
    402419                append( &this->blocked, this_thread() );
     420                spin_unlock( &lock );
    403421        }
    404422        suspend();
  • src/libcfa/concurrency/threads.c

    r84e2523 r8fcbb4c  
    2424
    2525extern "C" {
     26        #include <fenv.h>
    2627        #include <stddef.h>
    2728}
     
    9192        CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
    9293
     94        fenv_t envp;
     95        fegetenv( &envp );
     96        LIB_DEBUG_PRINTF("Thread : mxcsr %x\n", envp.__mxcsr);
    9397        LIB_DEBUG_PRINTF("Thread started : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
    9498
     
    105109
    106110void yield( void ) {
    107         thread_schedule( this_thread() );
     111        get_this_processor()->thread_action = Reschedule;
    108112        suspend();
    109113}
Note: See TracChangeset for help on using the changeset viewer.