Ignore:
File:
1 edited

Legend:

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

    r83a071f9 r135b431  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:33:18 2017
     13// Update Count     : 2
    1514//
    1615
     
    4241//-----------------------------------------------------------------------------
    4342// Kernel storage
    44 #define KERNEL_STORAGE(T,X) static char X##Storage[sizeof(T)]
    45 
    46 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
    47 KERNEL_STORAGE(cluster, systemCluster);
    48 KERNEL_STORAGE(system_proc_t, systemProcessor);
    49 KERNEL_STORAGE(thread_desc, mainThread);
     43KERNEL_STORAGE(cluster,           mainCluster);
     44KERNEL_STORAGE(processor,         mainProcessor);
     45KERNEL_STORAGE(processorCtx_t,    mainProcessorCtx);
     46KERNEL_STORAGE(thread_desc,       mainThread);
    5047KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    5148
    52 cluster * systemCluster;
    53 system_proc_t * systemProcessor;
     49cluster *     mainCluster;
     50processor *   mainProcessor;
    5451thread_desc * mainThread;
    5552
     
    5754// Global state
    5855
    59 volatile thread_local processor * this_processor;
    60 volatile thread_local coroutine_desc * this_coroutine;
    61 volatile thread_local thread_desc * this_thread;
     56thread_local coroutine_desc * volatile this_coroutine;
     57thread_local thread_desc *    volatile this_thread;
     58thread_local processor *      volatile this_processor;
     59
    6260volatile thread_local bool preemption_in_progress = 0;
    6361volatile thread_local unsigned short disable_preempt_count = 1;
     
    7573};
    7674
    77 void ?{}( current_stack_info_t & this ) {
    78         CtxGet( this.ctx );
    79         this.base = this.ctx.FP;
    80         this.storage = this.ctx.SP;
     75void ?{}( current_stack_info_t * this ) {
     76        CtxGet( this->ctx );
     77        this->base = this->ctx.FP;
     78        this->storage = this->ctx.SP;
    8179
    8280        rlimit r;
    8381        getrlimit( RLIMIT_STACK, &r);
    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 
    91 void ?{}( 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 
    101 void ?{}( 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 
    108 void ?{}( thread_desc & this, current_stack_info_t * info) {
    109         (this.cor){ info };
     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
     89void ?{}( 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
     99void ?{}( 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
     106void ?{}( thread_desc * this, current_stack_info_t * info) {
     107        (&this->cor){ info };
    110108}
    111109
    112110//-----------------------------------------------------------------------------
    113111// Processor coroutine
    114 void ?{}(processorCtx_t & this, processor * proc) {
    115         (this.__cor){ "Processor" };
    116         this.proc = proc;
    117         proc->runner = &this;
    118 }
    119 
    120 void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
    121         (this.__cor){ info };
    122         this.proc = proc;
    123         proc->runner = &this;
    124 }
    125 
    126 void ?{}(processor & this) {
    127         this{ systemCluster };
    128 }
    129 
    130 void ?{}(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 
    141 void ?{}(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 
    155 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    156 
    157 void ?{}(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 
    167 void ^?{}(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 
    176 void ?{}(cluster & this) {
    177         ( this.ready_queue ){};
    178         ( this.lock ){};
    179 }
    180 
    181 void ^?{}(cluster & this) {
     112void ?{}(processorCtx_t * this, processor * proc) {
     113        (&this->__cor){ "Processor" };
     114        this->proc = proc;
     115        proc->runner = this;
     116}
     117
     118void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {
     119        (&this->__cor){ info };
     120        this->proc = proc;
     121        proc->runner = this;
     122}
     123
     124void ?{}(processor * this) {
     125        this{ mainCluster };
     126}
     127
     128void ?{}(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
     138void ?{}(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
     151void ^?{}(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
     160void ?{}(cluster * this) {
     161        ( &this->ready_queue ){};
     162        ( &this->ready_queue_lock ){};
     163
     164        this->preemption = default_preemption();
     165}
     166
     167void ^?{}(cluster * this) {
    182168
    183169}
     
    187173//=============================================================================================
    188174//Main of the processor contexts
    189 void main(processorCtx_t & runner) {
    190         processor * this = runner.proc;
     175void main(processorCtx_t * runner) {
     176        processor * this = runner->proc;
    191177
    192178        LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this);
     
    199185
    200186                thread_desc * readyThread = NULL;
    201                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     187                for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
    202188                {
    203189                        readyThread = nextThread( this->cltr );
     
    233219// from the processor coroutine to the target thread
    234220void runThread(processor * this, thread_desc * dst) {
    235         coroutine_desc * proc_cor = get_coroutine(*this->runner);
     221        coroutine_desc * proc_cor = get_coroutine(this->runner);
    236222        coroutine_desc * thrd_cor = get_coroutine(dst);
    237223
     
    315301        // appropriate stack.
    316302        proc_cor_storage.__cor.state = Active;
    317         main( proc_cor_storage );
     303        main( &proc_cor_storage );
    318304        proc_cor_storage.__cor.state = Halted;
    319305
     
    336322void ScheduleThread( thread_desc * thrd ) {
    337323        // if( !thrd ) return;
    338         assert( thrd );
    339         assert( thrd->cor.state != Halted );
     324        verify( thrd );
     325        verify( thrd->cor.state != Halted );
    340326
    341327        verify( disable_preempt_count > 0 );
     
    343329        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    344330
    345         lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
    346         append( &systemProcessor->proc.cltr->ready_queue, thrd );
    347         unlock( &systemProcessor->proc.cltr->lock );
     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 );
    348334
    349335        verify( disable_preempt_count > 0 );
     
    352338thread_desc * nextThread(cluster * this) {
    353339        verify( disable_preempt_count > 0 );
    354         lock( &this->lock DEBUG_CTX2 );
     340        lock( &this->ready_queue_lock DEBUG_CTX2 );
    355341        thread_desc * head = pop_head( &this->ready_queue );
    356         unlock( &this->lock );
     342        unlock( &this->ready_queue_lock );
    357343        verify( disable_preempt_count > 0 );
    358344        return head;
     
    380366
    381367void BlockInternal( thread_desc * thrd ) {
     368        assert(thrd);
    382369        disable_interrupts();
    383370        assert( thrd->cor.state != Halted );
     
    393380
    394381void BlockInternal( spinlock * lock, thread_desc * thrd ) {
     382        assert(thrd);
    395383        disable_interrupts();
    396384        this_processor->finish.action_code = Release_Schedule;
     
    452440        // Start by initializing the main thread
    453441        // SKULLDUGGERY: the mainThread steals the process main thread
    454         // which will then be scheduled by the systemProcessor normally
    455         mainThread = (thread_desc *)&mainThreadStorage;
     442        // which will then be scheduled by the mainProcessor normally
     443        mainThread = (thread_desc *)&storage_mainThread;
    456444        current_stack_info_t info;
    457         (*mainThread){ &info };
     445        mainThread{ &info };
    458446
    459447        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    460448
    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
     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
    468456        // (the coroutine that contains the processing control flow)
    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);
     457        mainProcessor = (processor *)&storage_mainProcessor;
     458        mainProcessor{ mainCluster, (processorCtx_t *)&storage_mainProcessorCtx };
    475459
    476460        //initialize the global state variables
    477         this_processor = &systemProcessor->proc;
     461        this_processor = mainProcessor;
    478462        this_thread = mainThread;
    479463        this_coroutine = &mainThread->cor;
    480         disable_preempt_count = 1;
    481464
    482465        // Enable preemption
    483466        kernel_start_preemption();
    484467
    485         // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
     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
    486473        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    487474        // mainThread is on the ready queue when this call is made.
    488         resume( *systemProcessor->proc.runner );
     475        resume( mainProcessor->runner );
    489476
    490477
     
    501488        disable_interrupts();
    502489
    503         // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     490        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
    504491        // When its coroutine terminates, it return control to the mainThread
    505492        // which is currently here
    506         systemProcessor->proc.is_terminated = true;
     493        mainProcessor->do_terminate = true;
    507494        suspend();
    508495
     
    512499        kernel_stop_preemption();
    513500
    514         // Destroy the system processor and its context in reverse order of construction
     501        // Destroy the main processor and its context in reverse order of construction
    515502        // These were manually constructed so we need manually destroy them
    516         ^(*systemProcessor->proc.runner){};
    517         ^(systemProcessor){};
     503        ^(mainProcessor->runner){};
     504        ^(mainProcessor){};
    518505
    519506        // Final step, destroy the main thread since it is no longer needed
     
    582569//-----------------------------------------------------------------------------
    583570// Locks
    584 void ?{}( spinlock & this ) {
    585         this.lock = 0;
    586 }
    587 void ^?{}( spinlock & this ) {
     571void ?{}( spinlock * this ) {
     572        this->lock = 0;
     573}
     574void ^?{}( spinlock * this ) {
    588575
    589576}
     
    619606}
    620607
    621 void  ?{}( semaphore & this, int count = 1 ) {
    622         (this.lock){};
    623         this.count = count;
    624         (this.waiting){};
    625 }
    626 void ^?{}(semaphore & this) {}
     608void  ?{}( semaphore * this, int count = 1 ) {
     609        (&this->lock){};
     610        this->count = count;
     611        (&this->waiting){};
     612}
     613void ^?{}(semaphore * this) {}
    627614
    628615void P(semaphore * this) {
     
    658645//-----------------------------------------------------------------------------
    659646// Queues
    660 void ?{}( __thread_queue_t & this ) {
    661         this.head = NULL;
    662         this.tail = &this.head;
     647void ?{}( __thread_queue_t * this ) {
     648        this->head = NULL;
     649        this->tail = &this->head;
    663650}
    664651
     
    681668}
    682669
    683 void ?{}( __condition_stack_t & this ) {
    684         this.top = NULL;
     670thread_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
     689void ?{}( __condition_stack_t * this ) {
     690        this->top = NULL;
    685691}
    686692
     
    699705        return top;
    700706}
     707
    701708// Local Variables: //
    702709// mode: c //
Note: See TracChangeset for help on using the changeset viewer.