Ignore:
Timestamp:
Jan 19, 2017, 2:56:51 PM (9 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:
8f49a54
Parents:
765aa76 (diff), c2416d5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

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

    r765aa76 r4a3386b4  
     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>
     22extern "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
     34processor * systemProcessor;
     35thread_h * mainThread;
     36
     37void kernel_startup(void)  __attribute__((constructor(101)));
     38void kernel_shutdown(void) __attribute__((destructor(101)));
     39
     40void ?{}(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
     53void ^?{}(processor * this) {
     54
     55}
     56
     57//-----------------------------------------------------------------------------
     58// Processor coroutine
     59struct processorCtx_t {
     60        processor * proc;
     61        coroutine c;
     62};
     63
     64DECL_COROUTINE(processorCtx_t)
     65
     66void ?{}(processorCtx_t * this, processor * proc) {
     67        (&this->c){};
     68        this->proc = proc;
     69}
     70
     71void CtxInvokeProcessor(processor * proc) {
     72        processorCtx_t proc_cor_storage = {proc};
     73        resume( &proc_cor_storage );
     74}
     75
     76//-----------------------------------------------------------------------------
     77// Processor running routines
     78void main(processorCtx_t * ctx);
     79thread_h * nextThread(processor * this);
     80void runThread(processor * this, thread_h * dst);
     81void spin(processor * this, unsigned int * spin_count);
     82
     83void 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
     103thread_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
     114void 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
     130void spin(processor * this, unsigned int * spin_count) {
     131        (*spin_count)++;
     132}
     133
     134//-----------------------------------------------------------------------------
     135// Kernel runner (Temporary)
     136
     137void 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
     148void 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
     169KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
     170KERNEL_STORAGE(processor, systemProcessor);
     171KERNEL_STORAGE(thread_h, mainThread);
     172KERNEL_STORAGE(machine_context_t, mainThread_context);
     173
     174//-----------------------------------------------------------------------------
     175// Main thread construction
     176struct 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
     186void ?{}( 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
     200void ?{}( 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
     210void ?{}( 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
     218void ?{}( thread_h * this, mainThread_info_t * info) {
     219        (&this->c){ info };
     220}
     221
     222//-----------------------------------------------------------------------------
     223// Kernel boot procedures
     224void 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}
     261void 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.