Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/kernel.c

    r135b431 r83a071f9  
     1//                              -*- Mode: CFA -*-
    12//
    23// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    910// Author           : Thierry Delisle
    1011// Created On       : Tue Jan 17 12:27:26 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 22:33:18 2017
    13 // Update Count     : 2
     12// Last Modified By : Thierry Delisle
     13// Last Modified On : --
     14// Update Count     : 0
    1415//
    1516
     
    4142//-----------------------------------------------------------------------------
    4243// Kernel storage
    43 KERNEL_STORAGE(cluster,           mainCluster);
    44 KERNEL_STORAGE(processor,         mainProcessor);
    45 KERNEL_STORAGE(processorCtx_t,    mainProcessorCtx);
    46 KERNEL_STORAGE(thread_desc,       mainThread);
     44#define KERNEL_STORAGE(T,X) static char X##Storage[sizeof(T)]
     45
     46KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
     47KERNEL_STORAGE(cluster, systemCluster);
     48KERNEL_STORAGE(system_proc_t, systemProcessor);
     49KERNEL_STORAGE(thread_desc, mainThread);
    4750KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    4851
    49 cluster *     mainCluster;
    50 processor *   mainProcessor;
     52cluster * systemCluster;
     53system_proc_t * systemProcessor;
    5154thread_desc * mainThread;
    5255
     
    5457// Global state
    5558
    56 thread_local coroutine_desc * volatile this_coroutine;
    57 thread_local thread_desc *    volatile this_thread;
    58 thread_local processor *      volatile this_processor;
    59 
     59volatile thread_local processor * this_processor;
     60volatile thread_local coroutine_desc * this_coroutine;
     61volatile thread_local thread_desc * this_thread;
    6062volatile thread_local bool preemption_in_progress = 0;
    6163volatile thread_local unsigned short disable_preempt_count = 1;
     
    7375};
    7476
    75 void ?{}( current_stack_info_t * this ) {
    76         CtxGet( this->ctx );
    77         this->base = this->ctx.FP;
    78         this->storage = this->ctx.SP;
     77void ?{}( current_stack_info_t & this ) {
     78        CtxGet( this.ctx );
     79        this.base = this.ctx.FP;
     80        this.storage = this.ctx.SP;
    7981
    8082        rlimit r;
    8183        getrlimit( RLIMIT_STACK, &r);
    82         this->size = r.rlim_cur;
    83 
    84         this->limit = (void *)(((intptr_t)this->base) - this->size);
    85         this->context = &storage_mainThreadCtx;
    86         this->top = this->base;
    87 }
    88 
    89 void ?{}( coStack_t * this, current_stack_info_t * info) {
    90         this->size = info->size;
    91         this->storage = info->storage;
    92         this->limit = info->limit;
    93         this->base = info->base;
    94         this->context = info->context;
    95         this->top = info->top;
    96         this->userStack = true;
    97 }
    98 
    99 void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    100         (&this->stack){ info };
    101         this->name = "Main Thread";
    102         this->errno_ = 0;
    103         this->state = Start;
    104 }
    105 
    106 void ?{}( thread_desc * this, current_stack_info_t * info) {
    107         (&this->cor){ info };
     84        this.size = r.rlim_cur;
     85
     86        this.limit = (void *)(((intptr_t)this.base) - this.size);
     87        this.context = &mainThreadCtxStorage;
     88        this.top = this.base;
     89}
     90
     91void ?{}( coStack_t & this, current_stack_info_t * info) {
     92        this.size = info->size;
     93        this.storage = info->storage;
     94        this.limit = info->limit;
     95        this.base = info->base;
     96        this.context = info->context;
     97        this.top = info->top;
     98        this.userStack = true;
     99}
     100
     101void ?{}( coroutine_desc & this, current_stack_info_t * info) {
     102        (this.stack){ info };
     103        this.name = "Main Thread";
     104        this.errno_ = 0;
     105        this.state = Start;
     106}
     107
     108void ?{}( thread_desc & this, current_stack_info_t * info) {
     109        (this.cor){ info };
    108110}
    109111
    110112//-----------------------------------------------------------------------------
    111113// Processor coroutine
    112 void ?{}(processorCtx_t * this, processor * proc) {
    113         (&this->__cor){ "Processor" };
    114         this->proc = proc;
    115         proc->runner = this;
    116 }
    117 
    118 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {
    119         (&this->__cor){ info };
    120         this->proc = proc;
    121         proc->runner = this;
    122 }
    123 
    124 void ?{}(processor * this) {
    125         this{ mainCluster };
    126 }
    127 
    128 void ?{}(processor * this, cluster * cltr) {
    129         this->cltr = cltr;
    130         (&this->terminated){ 0 };
    131         this->do_terminate = false;
    132         this->preemption_alarm = NULL;
    133         this->pending_preemption = false;
    134 
    135         start( this );
    136 }
    137 
    138 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    139         this->cltr = cltr;
    140         (&this->terminated){ 0 };
    141         this->do_terminate = false;
    142         this->preemption_alarm = NULL;
    143         this->pending_preemption = false;
    144         this->kernel_thread = pthread_self();
    145 
    146         this->runner = runner;
    147         LIB_DEBUG_PRINT_SAFE("Kernel : constructing main processor context %p\n", runner);
    148         runner{ this };
    149 }
    150 
    151 void ^?{}(processor * this) {
    152         if( ! this->do_terminate ) {
    153                 LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", this);
    154                 this->do_terminate = true;
    155                 P( &this->terminated );
    156                 pthread_join( this->kernel_thread, NULL );
    157         }
    158 }
    159 
    160 void ?{}(cluster * this) {
    161         ( &this->ready_queue ){};
    162         ( &this->ready_queue_lock ){};
    163 
    164         this->preemption = default_preemption();
    165 }
    166 
    167 void ^?{}(cluster * this) {
     114void ?{}(processorCtx_t & this, processor * proc) {
     115        (this.__cor){ "Processor" };
     116        this.proc = proc;
     117        proc->runner = &this;
     118}
     119
     120void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
     121        (this.__cor){ info };
     122        this.proc = proc;
     123        proc->runner = &this;
     124}
     125
     126void ?{}(processor & this) {
     127        this{ systemCluster };
     128}
     129
     130void ?{}(processor & this, cluster * cltr) {
     131        this.cltr = cltr;
     132        (this.terminated){ 0 };
     133        this.is_terminated = false;
     134        this.preemption_alarm = NULL;
     135        this.preemption = default_preemption();
     136        this.pending_preemption = false;
     137
     138        start( &this );
     139}
     140
     141void ?{}(processor & this, cluster * cltr, processorCtx_t & runner) {
     142        this.cltr = cltr;
     143        (this.terminated){ 0 };
     144        this.is_terminated = false;
     145        this.preemption_alarm = NULL;
     146        this.preemption = default_preemption();
     147        this.pending_preemption = false;
     148        this.kernel_thread = pthread_self();
     149
     150        this.runner = &runner;
     151        LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", &runner);
     152        runner{ &this };
     153}
     154
     155LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
     156
     157void ?{}(system_proc_t & this, cluster * cltr, processorCtx_t & runner) {
     158        (this.alarms){};
     159        (this.alarm_lock){};
     160        this.pending_alarm = false;
     161
     162        (this.proc){ cltr, runner };
     163
     164        verify( validate( &this.alarms ) );
     165}
     166
     167void ^?{}(processor & this) {
     168        if( ! this.is_terminated ) {
     169                LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", &this);
     170                this.is_terminated = true;
     171                P( &this.terminated );
     172                pthread_join( this.kernel_thread, NULL );
     173        }
     174}
     175
     176void ?{}(cluster & this) {
     177        ( this.ready_queue ){};
     178        ( this.lock ){};
     179}
     180
     181void ^?{}(cluster & this) {
    168182
    169183}
     
    173187//=============================================================================================
    174188//Main of the processor contexts
    175 void main(processorCtx_t * runner) {
    176         processor * this = runner->proc;
     189void main(processorCtx_t & runner) {
     190        processor * this = runner.proc;
    177191
    178192        LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this);
     
    185199
    186200                thread_desc * readyThread = NULL;
    187                 for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
     201                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    188202                {
    189203                        readyThread = nextThread( this->cltr );
     
    219233// from the processor coroutine to the target thread
    220234void runThread(processor * this, thread_desc * dst) {
    221         coroutine_desc * proc_cor = get_coroutine(this->runner);
     235        coroutine_desc * proc_cor = get_coroutine(*this->runner);
    222236        coroutine_desc * thrd_cor = get_coroutine(dst);
    223237
     
    301315        // appropriate stack.
    302316        proc_cor_storage.__cor.state = Active;
    303         main( &proc_cor_storage );
     317        main( proc_cor_storage );
    304318        proc_cor_storage.__cor.state = Halted;
    305319
     
    322336void ScheduleThread( thread_desc * thrd ) {
    323337        // if( !thrd ) return;
    324         verify( thrd );
    325         verify( thrd->cor.state != Halted );
     338        assert( thrd );
     339        assert( thrd->cor.state != Halted );
    326340
    327341        verify( disable_preempt_count > 0 );
     
    329343        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    330344
    331         lock(   &this_processor->cltr->ready_queue_lock DEBUG_CTX2 );
    332         append( &this_processor->cltr->ready_queue, thrd );
    333         unlock( &this_processor->cltr->ready_queue_lock );
     345        lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
     346        append( &systemProcessor->proc.cltr->ready_queue, thrd );
     347        unlock( &systemProcessor->proc.cltr->lock );
    334348
    335349        verify( disable_preempt_count > 0 );
     
    338352thread_desc * nextThread(cluster * this) {
    339353        verify( disable_preempt_count > 0 );
    340         lock( &this->ready_queue_lock DEBUG_CTX2 );
     354        lock( &this->lock DEBUG_CTX2 );
    341355        thread_desc * head = pop_head( &this->ready_queue );
    342         unlock( &this->ready_queue_lock );
     356        unlock( &this->lock );
    343357        verify( disable_preempt_count > 0 );
    344358        return head;
     
    366380
    367381void BlockInternal( thread_desc * thrd ) {
    368         assert(thrd);
    369382        disable_interrupts();
    370383        assert( thrd->cor.state != Halted );
     
    380393
    381394void BlockInternal( spinlock * lock, thread_desc * thrd ) {
    382         assert(thrd);
    383395        disable_interrupts();
    384396        this_processor->finish.action_code = Release_Schedule;
     
    440452        // Start by initializing the main thread
    441453        // SKULLDUGGERY: the mainThread steals the process main thread
    442         // which will then be scheduled by the mainProcessor normally
    443         mainThread = (thread_desc *)&storage_mainThread;
     454        // which will then be scheduled by the systemProcessor normally
     455        mainThread = (thread_desc *)&mainThreadStorage;
    444456        current_stack_info_t info;
    445         mainThread{ &info };
     457        (*mainThread){ &info };
    446458
    447459        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    448460
    449         // Initialize the main cluster
    450         mainCluster = (cluster *)&storage_mainCluster;
    451         mainCluster{};
    452 
    453         LIB_DEBUG_PRINT_SAFE("Kernel : main cluster ready\n");
    454 
    455         // Initialize the main processor and the main processor ctx
     461        // Initialize the system cluster
     462        systemCluster = (cluster *)&systemClusterStorage;
     463        (*systemCluster){};
     464
     465        LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n");
     466
     467        // Initialize the system processor and the system processor ctx
    456468        // (the coroutine that contains the processing control flow)
    457         mainProcessor = (processor *)&storage_mainProcessor;
    458         mainProcessor{ mainCluster, (processorCtx_t *)&storage_mainProcessorCtx };
     469        systemProcessor = (system_proc_t *)&systemProcessorStorage;
     470        (*systemProcessor){ systemCluster, *(processorCtx_t *)&systemProcessorCtxStorage };
     471
     472        // Add the main thread to the ready queue
     473        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
     474        ScheduleThread(mainThread);
    459475
    460476        //initialize the global state variables
    461         this_processor = mainProcessor;
     477        this_processor = &systemProcessor->proc;
    462478        this_thread = mainThread;
    463479        this_coroutine = &mainThread->cor;
     480        disable_preempt_count = 1;
    464481
    465482        // Enable preemption
    466483        kernel_start_preemption();
    467484
    468         // Add the main thread to the ready queue
    469         // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    470         ScheduleThread(mainThread);
    471 
    472         // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
     485        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    473486        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    474487        // mainThread is on the ready queue when this call is made.
    475         resume( mainProcessor->runner );
     488        resume( *systemProcessor->proc.runner );
    476489
    477490
     
    488501        disable_interrupts();
    489502
    490         // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     503        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
    491504        // When its coroutine terminates, it return control to the mainThread
    492505        // which is currently here
    493         mainProcessor->do_terminate = true;
     506        systemProcessor->proc.is_terminated = true;
    494507        suspend();
    495508
     
    499512        kernel_stop_preemption();
    500513
    501         // Destroy the main processor and its context in reverse order of construction
     514        // Destroy the system processor and its context in reverse order of construction
    502515        // These were manually constructed so we need manually destroy them
    503         ^(mainProcessor->runner){};
    504         ^(mainProcessor){};
     516        ^(*systemProcessor->proc.runner){};
     517        ^(systemProcessor){};
    505518
    506519        // Final step, destroy the main thread since it is no longer needed
     
    569582//-----------------------------------------------------------------------------
    570583// Locks
    571 void ?{}( spinlock * this ) {
    572         this->lock = 0;
    573 }
    574 void ^?{}( spinlock * this ) {
     584void ?{}( spinlock & this ) {
     585        this.lock = 0;
     586}
     587void ^?{}( spinlock & this ) {
    575588
    576589}
     
    606619}
    607620
    608 void  ?{}( semaphore * this, int count = 1 ) {
    609         (&this->lock){};
    610         this->count = count;
    611         (&this->waiting){};
    612 }
    613 void ^?{}(semaphore * this) {}
     621void  ?{}( semaphore & this, int count = 1 ) {
     622        (this.lock){};
     623        this.count = count;
     624        (this.waiting){};
     625}
     626void ^?{}(semaphore & this) {}
    614627
    615628void P(semaphore * this) {
     
    645658//-----------------------------------------------------------------------------
    646659// Queues
    647 void ?{}( __thread_queue_t * this ) {
    648         this->head = NULL;
    649         this->tail = &this->head;
     660void ?{}( __thread_queue_t & this ) {
     661        this.head = NULL;
     662        this.tail = &this.head;
    650663}
    651664
     
    668681}
    669682
    670 thread_desc * remove( __thread_queue_t * this, thread_desc ** it ) {
    671         thread_desc * thrd = *it;
    672         verify( thrd );
    673 
    674         (*it) = thrd->next;
    675 
    676         if( this->tail == &thrd->next ) {
    677                 this->tail = it;
    678         }
    679 
    680         thrd->next = NULL;
    681 
    682         verify( (this->head == NULL) == (&this->head == this->tail) );
    683         verify( *this->tail == NULL );
    684         return thrd;
    685 }
    686 
    687 
    688 
    689 void ?{}( __condition_stack_t * this ) {
    690         this->top = NULL;
     683void ?{}( __condition_stack_t & this ) {
     684        this.top = NULL;
    691685}
    692686
     
    705699        return top;
    706700}
    707 
    708701// Local Variables: //
    709702// mode: c //
Note: See TracChangeset for help on using the changeset viewer.