Ignore:
File:
1 edited

Legend:

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

    rbd98b58 r8def349  
    3232#include "invoke.h"
    3333
    34 cluster * systemCluster;
    35 processor * systemProcessor;
    36 thread_h * mainThread;
    37 
    38 void kernel_startup(void)  __attribute__((constructor(101)));
    39 void kernel_shutdown(void) __attribute__((destructor(101)));
    40 
    41 void ?{}(processor * this, cluster * cltr) {
    42         this->ctx = NULL;
    43         this->cltr = cltr;
    44         this->terminated = false;
    45 }
    46 
    47 void ^?{}(processor * this) {}
    48 
    49 void ?{}(cluster * this) {
    50         ( &this->ready_queue ){};
    51 }
    52 
    53 void ^?{}(cluster * this) {}
    54 
    55 //-----------------------------------------------------------------------------
    56 // Global state
    57 
    58 /*thread_local*/ processor * this_processor;
    59 
    60 coroutine * this_coroutine(void) {
    61         return this_processor->current_coroutine;
    62 }
    63 
    64 thread_h * this_thread(void) {
    65         return this_processor->current_thread;
    66 }
    67 
    68 //-----------------------------------------------------------------------------
    69 // Processor coroutine
     34//-----------------------------------------------------------------------------
     35// Kernel storage
    7036struct processorCtx_t {
    7137        processor * proc;
     
    7541DECL_COROUTINE(processorCtx_t)
    7642
     43#define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
     44
     45KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
     46KERNEL_STORAGE(cluster, systemCluster);
     47KERNEL_STORAGE(processor, systemProcessor);
     48KERNEL_STORAGE(thread_h, mainThread);
     49KERNEL_STORAGE(machine_context_t, mainThread_context);
     50
     51cluster * systemCluster;
     52processor * systemProcessor;
     53thread_h * mainThread;
     54
     55void kernel_startup(void)  __attribute__((constructor(101)));
     56void kernel_shutdown(void) __attribute__((destructor(101)));
     57
     58//-----------------------------------------------------------------------------
     59// Global state
     60
     61thread_local processor * this_processor;
     62
     63processor * get_this_processor() {
     64        return this_processor;
     65}
     66
     67coroutine * this_coroutine(void) {
     68        return this_processor->current_coroutine;
     69}
     70
     71thread_h * this_thread(void) {
     72        return this_processor->current_thread;
     73}
     74
     75//-----------------------------------------------------------------------------
     76// Main thread construction
     77struct current_stack_info_t {
     78        machine_context_t ctx; 
     79        unsigned int size;              // size of stack
     80        void *base;                             // base of stack
     81        void *storage;                  // pointer to stack
     82        void *limit;                    // stack grows towards stack limit
     83        void *context;                  // address of cfa_context_t
     84        void *top;                              // address of top of storage
     85};
     86
     87void ?{}( current_stack_info_t * this ) {
     88        CtxGet( &this->ctx );
     89        this->base = this->ctx.FP;
     90        this->storage = this->ctx.SP;
     91
     92        rlimit r;
     93        int ret = getrlimit( RLIMIT_STACK, &r);
     94        this->size = r.rlim_cur;
     95
     96        this->limit = (void *)(((intptr_t)this->base) - this->size);
     97        this->context = &mainThread_context_storage;
     98        this->top = this->base;
     99}
     100
     101void ?{}( coStack_t * this, current_stack_info_t * info) {
     102        this->size = info->size;
     103        this->storage = info->storage;
     104        this->limit = info->limit;
     105        this->base = info->base;
     106        this->context = info->context;
     107        this->top = info->top;
     108        this->userStack = true;
     109}
     110
     111void ?{}( coroutine * this, current_stack_info_t * info) {
     112        (&this->stack){ info };
     113        this->name = "Main Thread";
     114        this->errno_ = 0;
     115        this->state = Inactive;
     116        this->notHalted = true;
     117}
     118
     119void ?{}( thread_h * this, current_stack_info_t * info) {
     120        (&this->c){ info };
     121}
     122
     123//-----------------------------------------------------------------------------
     124// Processor coroutine
    77125void ?{}(processorCtx_t * this, processor * proc) {
    78126        (&this->c){};
    79127        this->proc = proc;
    80 }
    81 
    82 void CtxInvokeProcessor(processor * proc) {
    83         processorCtx_t proc_cor_storage = {proc};
    84         resume( &proc_cor_storage );
     128        proc->ctx = this;
     129}
     130
     131void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {
     132        (&this->c){ info };
     133        this->proc = proc;
     134        proc->ctx = this;
     135}
     136
     137void start(processor * this);
     138
     139void ?{}(processor * this) {
     140        this{ systemCluster };
     141}
     142
     143void ?{}(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
     153void ?{}(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
     165void ^?{}(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
     173void ?{}(cluster * this) {
     174        ( &this->ready_queue ){};
     175        pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );
     176}
     177
     178void ^?{}(cluster * this) {
     179        pthread_spin_destroy( &this->lock );
    85180}
    86181
     
    109204        }
    110205
     206        LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this);
     207        unlock( &this->lock );
    111208        LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);
    112209}
     
    133230}
    134231
     232void * 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
     271void 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
    135284//-----------------------------------------------------------------------------
    136285// Scheduler routines
    137286void thread_schedule( thread_h * thrd ) {
    138287        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
     288       
     289        pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };
    139290        append( &systemProcessor->cltr->ready_queue, thrd );
    140291}
    141292
    142293thread_h * nextThread(cluster * this) {
     294        pthread_spinlock_guard guard = { &this->lock };
    143295        return pop_head( &this->ready_queue );
    144 }
    145 
    146 //-----------------------------------------------------------------------------
    147 // Kernel storage
    148 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
    149 
    150 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
    151 KERNEL_STORAGE(cluster, systemCluster);
    152 KERNEL_STORAGE(processor, systemProcessor);
    153 KERNEL_STORAGE(thread_h, mainThread);
    154 KERNEL_STORAGE(machine_context_t, mainThread_context);
    155 
    156 //-----------------------------------------------------------------------------
    157 // Main thread construction
    158 struct mainThread_info_t {
    159         machine_context_t ctx; 
    160         unsigned int size;              // size of stack
    161         void *base;                             // base of stack
    162         void *storage;                  // pointer to stack
    163         void *limit;                    // stack grows towards stack limit
    164         void *context;                  // address of cfa_context_t
    165         void *top;                              // address of top of storage
    166 };
    167 
    168 void ?{}( mainThread_info_t * this ) {
    169         CtxGet( &this->ctx );
    170         this->base = this->ctx.FP;
    171         this->storage = this->ctx.SP;
    172 
    173         rlimit r;
    174         int ret = getrlimit( RLIMIT_STACK, &r);
    175         this->size = r.rlim_cur;
    176 
    177         this->limit = (void *)(((intptr_t)this->base) - this->size);
    178         this->context = &mainThread_context_storage;
    179         this->top = this->base;
    180 }
    181 
    182 void ?{}( coStack_t * this, mainThread_info_t * info) {
    183         this->size = info->size;
    184         this->storage = info->storage;
    185         this->limit = info->limit;
    186         this->base = info->base;
    187         this->context = info->context;
    188         this->top = info->top;
    189         this->userStack = true;
    190 }
    191 
    192 void ?{}( coroutine * this, mainThread_info_t * info) {
    193         (&this->stack){ info };
    194         this->name = "Main Thread";
    195         this->errno_ = 0;
    196         this->state = Inactive;
    197         this->notHalted = true;
    198 }
    199 
    200 void ?{}( thread_h * this, mainThread_info_t * info) {
    201         (&this->c){ info };
    202296}
    203297
     
    210304        LIB_DEBUG_PRINTF("Kernel : Starting\n");       
    211305
    212         mainThread_info_t ctx;
     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 );
    213314
    214315        // Start by initializing the main thread
    215316        mainThread = (thread_h *)&mainThread_storage;
    216         mainThread{ &ctx };
     317        mainThread{ &info };
    217318
    218319        // Initialize the system cluster
     
    220321        systemCluster{};
    221322
    222         // Initialize the system processor
     323        // Initialize the system processor and the system processor ctx
     324        // (the coroutine that contains the processing control flow)
    223325        systemProcessor = (processor *)&systemProcessor_storage;
    224         systemProcessor{ systemCluster };
    225 
    226         // Initialize the system processor ctx
    227         // (the coroutine that contains the processing control flow)
    228         systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage;
    229         systemProcessor->ctx{ systemProcessor };
     326        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    230327
    231328        // Add the main thread to the ready queue
     
    286383
    287384void lock( simple_lock * this ) {
    288         append( &this->blocked, this_thread() );
     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        }
    289389        suspend();
    290390}
Note: See TracChangeset for help on using the changeset viewer.