Ignore:
File:
1 edited

Legend:

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

    reb2e723 raed3f54  
    1 //                              -*- Mode: CFA -*-
    2 //
    3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 //
    5 // The contents of this file are covered under the licence agreement in the
    6 // file "LICENCE" distributed with Cforall.
    7 //
    8 // kernel.c --
    9 //
    10 // Author           : Thierry Delisle
    11 // Created On       : Tue Jan 17 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
    15 //
    16 
    17 //Header
    18 #include "kernel"
    19 
    20 //C Includes
    21 #include <stddef.h>
    22 extern "C" {
    23 #include <sys/resource.h>
    24 }
    25 
    26 //CFA Includes
    27 #include "libhdr.h"
    28 #include "threads"
    29 
    30 //Private includes
    31 #define __CFA_INVOKE_PRIVATE__
    32 #include "invoke.h"
    33 
    34 processor * systemProcessor;
    35 thread_h * mainThread;
    36 
    37 void kernel_startup(void)  __attribute__((constructor(101)));
    38 void kernel_shutdown(void) __attribute__((destructor(101)));
    39 
    40 void ?{}(processor * this) {
    41         this->ctx = NULL;
    42         this->thread_index = 0;
    43         this->thread_count = 10;
    44         this->terminated = false;
    45 
    46         for(int i = 0; i < 10; i++) {
    47                 this->threads[i] = NULL;
    48         }
    49 
    50         LIB_DEBUG_PRINTF("Processor : ctor for core %p (core spots %d)\n", this, this->thread_count);
    51 }
    52 
    53 void ^?{}(processor * this) {
    54 
    55 }
    56 
    57 //-----------------------------------------------------------------------------
    58 // Processor coroutine
    59 struct processorCtx_t {
    60         processor * proc;
    61         coroutine c;
    62 };
    63 
    64 DECL_COROUTINE(processorCtx_t)
    65 
    66 void ?{}(processorCtx_t * this, processor * proc) {
    67         (&this->c){};
    68         this->proc = proc;
    69 }
    70 
    71 void CtxInvokeProcessor(processor * proc) {
    72         processorCtx_t proc_cor_storage = {proc};
    73         resume( &proc_cor_storage );
    74 }
    75 
    76 //-----------------------------------------------------------------------------
    77 // Processor running routines
    78 void main(processorCtx_t * ctx);
    79 thread_h * nextThread(processor * this);
    80 void runThread(processor * this, thread_h * dst);
    81 void spin(processor * this, unsigned int * spin_count);
    82 
    83 void main(processorCtx_t * ctx) {
    84         processor * this = ctx->proc;
    85         LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);
    86 
    87         thread_h * readyThread = NULL;
    88         for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {
    89                
    90                 readyThread = nextThread(this);
    91 
    92                 if(readyThread) {
    93                         runThread(this, readyThread);
    94                         spin_count = 0;
    95                 } else {
    96                         spin(this, &spin_count);
    97                 }               
    98         }
    99 
    100         LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);
    101 }
    102 
    103 thread_h * nextThread(processor * this) {
    104         for(int i = 0; i < this->thread_count; i++) {
    105                 this->thread_index = (this->thread_index + 1) % this->thread_count;     
    106                
    107                 thread_h * thrd = this->threads[this->thread_index];
    108                 if(thrd) return thrd;
    109         }
    110 
    111         return NULL;
    112 }
    113 
    114 void runThread(processor * this, thread_h * dst) {
    115         coroutine * proc_ctx = get_coroutine(this->ctx);
    116         coroutine * thrd_ctx = get_coroutine(dst);
    117         thrd_ctx->last = proc_ctx;
    118 
    119         // context switch to specified coroutine
    120         // Which is now the current_coroutine
    121         LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
    122         current_coroutine = thrd_ctx;
    123         CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
    124         current_coroutine = proc_ctx;
    125         LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);
    126 
    127         // when CtxSwitch returns we are back in the processor coroutine
    128 }
    129 
    130 void spin(processor * this, unsigned int * spin_count) {
    131         (*spin_count)++;
    132 }
    133 
    134 //-----------------------------------------------------------------------------
    135 // Kernel runner (Temporary)
    136 
    137 void scheduler_add( thread_h * thrd ) {
    138         LIB_DEBUG_PRINTF("Kernel : scheduling %p on core %p (%d spots)\n", thrd, systemProcessor, systemProcessor->thread_count);
    139         for(int i = 0; i < systemProcessor->thread_count; i++) {
    140                 if(systemProcessor->threads[i] == NULL) {
    141                         systemProcessor->threads[i] = thrd;
    142                         return;
    143                 }
    144         }
    145         assert(false);
    146 }
    147 
    148 void scheduler_remove( thread_h * thrd ) {
    149         LIB_DEBUG_PRINTF("Kernel : unscheduling %p from core %p\n", thrd, systemProcessor);
    150         for(int i = 0; i < systemProcessor->thread_count; i++) {
    151                 if(systemProcessor->threads[i] == thrd) {
    152                         systemProcessor->threads[i] = NULL;
    153                         break;
    154                 }
    155         }
    156         for(int i = 0; i < systemProcessor->thread_count; i++) {
    157                 if(systemProcessor->threads[i] != NULL) {
    158                         return;
    159                 }
    160         }
    161         LIB_DEBUG_PRINTF("Kernel : terminating core %p\n", systemProcessor);   
    162         systemProcessor->terminated = true;
    163 }
    164 
    165 //-----------------------------------------------------------------------------
    166 // Kernel storage
    167 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
    168 
    169 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
    170 KERNEL_STORAGE(processor, systemProcessor);
    171 KERNEL_STORAGE(thread_h, mainThread);
    172 KERNEL_STORAGE(machine_context_t, mainThread_context);
    173 
    174 //-----------------------------------------------------------------------------
    175 // Main thread construction
    176 struct mainThread_info_t {
    177         machine_context_t ctx; 
    178         unsigned int size;              // size of stack
    179         void *base;                             // base of stack
    180         void *storage;                  // pointer to stack
    181         void *limit;                    // stack grows towards stack limit
    182         void *context;                  // address of cfa_context_t
    183         void *top;                              // address of top of storage
    184 };
    185 
    186 void ?{}( mainThread_info_t * this ) {
    187         CtxGet( &this->ctx );
    188         this->base = this->ctx.FP;
    189         this->storage = this->ctx.SP;
    190 
    191         rlimit r;
    192         int ret = getrlimit( RLIMIT_STACK, &r);
    193         this->size = r.rlim_cur;
    194 
    195         this->limit = (void *)(((intptr_t)this->base) - this->size);
    196         this->context = &mainThread_context_storage;
    197         this->top = this->base;
    198 }
    199 
    200 void ?{}( coStack_t * this, mainThread_info_t * info) {
    201         this->size = info->size;
    202         this->storage = info->storage;
    203         this->limit = info->limit;
    204         this->base = info->base;
    205         this->context = info->context;
    206         this->top = info->top;
    207         this->userStack = true;
    208 }
    209 
    210 void ?{}( coroutine * this, mainThread_info_t * info) {
    211         (&this->stack){ info };
    212         this->name = "Main Thread";
    213         this->errno_ = 0;
    214         this->state = Inactive;
    215         this->notHalted = true;
    216 }
    217 
    218 void ?{}( thread_h * this, mainThread_info_t * info) {
    219         (&this->c){ info };
    220 }
    221 
    222 //-----------------------------------------------------------------------------
    223 // Kernel boot procedures
    224 void kernel_startup(void) {
    225 
    226         // SKULLDUGGERY: the mainThread steals the process main thread
    227         // which will then be scheduled by the systemProcessor normally
    228         LIB_DEBUG_PRINTF("Kernel : Starting\n");       
    229 
    230         mainThread_info_t ctx;
    231         LIB_DEBUG_PRINTF("Kernel :    base : %p\n", ctx.base );
    232         LIB_DEBUG_PRINTF("Kernel :     top : %p\n", ctx.top );
    233         LIB_DEBUG_PRINTF("Kernel :   limit : %p\n", ctx.limit );
    234         LIB_DEBUG_PRINTF("Kernel :    size : %x\n", ctx.size );
    235         LIB_DEBUG_PRINTF("Kernel : storage : %p\n", ctx.storage );
    236         LIB_DEBUG_PRINTF("Kernel : context : %p\n", ctx.context );
    237 
    238         // Start by initializing the main thread
    239         mainThread = (thread_h *)&mainThread_storage;
    240         LIB_DEBUG_PRINTF("Kernel : Main thread : %p\n", mainThread );
    241         mainThread{ &ctx };
    242 
    243         // // Initialize the system processor
    244         systemProcessor = (processor *)&systemProcessor_storage;
    245         systemProcessor{};
    246 
    247         // Initialize the system processor ctx
    248         // (the coroutine that contains the processing control flow)
    249         systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage;
    250         systemProcessor->ctx{ systemProcessor };
    251 
    252         scheduler_add(mainThread);
    253 
    254         current_coroutine = &mainThread->c;
    255 
    256         LIB_DEBUG_PRINTF("Kernel : Starting system processor\n");       
    257         resume(systemProcessor->ctx);
    258 
    259         LIB_DEBUG_PRINTF("Kernel : Started\n--------------------------------------------------\n\n");
    260 }
    261 void kernel_shutdown(void) {
    262         LIB_DEBUG_PRINTF("\n--------------------------------------------------\nKernel : Shutting down");
    263 
    264         LIB_DEBUG_PRINTF("Unscheduling main thread\n");
    265         scheduler_remove(mainThread);
    266 
    267         LIB_DEBUG_PRINTF("Suspending main\n");
    268         suspend();
    269 
    270         LIB_DEBUG_PRINTF("Kernel : Control return to initial process thread\n");
    271 
    272         ^(systemProcessor->ctx){};
    273         ^(systemProcessor){};
    274 
    275         ^(mainThread){};
    276 
    277         LIB_DEBUG_PRINTF("Kernel : Shutdown complete\n");       
    278 }
    279 
    280 // Local Variables: //
    281 // mode: c //
    282 // tab-width: 4 //
    283 // End: //
Note: See TracChangeset for help on using the changeset viewer.