// -*- Mode: CFA -*- // // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // kernel.c -- // // Author : Thierry Delisle // Created On : Tue Jan 17 12:27:26 2016 // Last Modified By : Thierry Delisle // Last Modified On : -- // Update Count : 0 // //Header #include "kernel" //C Includes #include //CFA Includes #include "libhdr.h" #include "threads" //Private includes #define __CFA_INVOKE_PRIVATE__ #include "invoke.h" processor systemProcessorStorage = {}; processor * systemProcessor = &systemProcessorStorage; void ?{}(processor * this) { this->cor = NULL; this->thread_index = 0; this->thread_count = 10; this->terminated = false; for(int i = 0; i < 10; i++) { this->threads[i] = NULL; } LIB_DEBUG_PRINTF("Processor : ctor for core %p (core spots %d)\n", this, this->thread_count); } void ^?{}(processor * this) { } //----------------------------------------------------------------------------- // Processor coroutine struct proc_coroutine { processor * proc; coroutine c; }; void ?{}(coroutine * this, processor * proc) { this{}; } DECL_COROUTINE(proc_coroutine) void ?{}(proc_coroutine * this, processor * proc) { (&this->c){proc}; this->proc = proc; proc->cor = this; } void ^?{}(proc_coroutine * this) { ^(&this->c){}; } void CtxInvokeProcessor(processor * proc) { proc_coroutine proc_cor_storage = {proc}; resume( &proc_cor_storage ); } //----------------------------------------------------------------------------- // Processor running routines void main(proc_coroutine * cor); thread_h * nextThread(processor * this); void runThread(processor * this, thread_h * dst); void spin(processor * this, unsigned int * spin_count); void main(proc_coroutine * cor) { processor * this; this = cor->proc; thread_h * readyThread = NULL; for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) { readyThread = nextThread(this); if(readyThread) { runThread(this, readyThread); spin_count = 0; } else { spin(this, &spin_count); } } LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this); } thread_h * nextThread(processor * this) { for(int i = 0; i < this->thread_count; i++) { this->thread_index = (this->thread_index + 1) % this->thread_count; thread_h * thrd = this->threads[this->thread_index]; if(thrd) return thrd; } return NULL; } void runThread(processor * this, thread_h * dst) { coroutine * proc_ctx = get_coroutine(this->cor); coroutine * thrd_ctx = get_coroutine(dst); thrd_ctx->last = proc_ctx; // context switch to specified coroutine // Which is now the current_coroutine LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine); current_coroutine = thrd_ctx; CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context ); current_coroutine = proc_ctx; LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine); // when CtxSwitch returns we are back in the processor coroutine } void spin(processor * this, unsigned int * spin_count) { (*spin_count)++; } //----------------------------------------------------------------------------- // Kernel runner (Temporary) void scheduler_add( struct thread_h * thrd ) { LIB_DEBUG_PRINTF("Kernel : scheduling %p on core %p (%d spots)\n", thrd, systemProcessor, systemProcessor->thread_count); for(int i = 0; i < systemProcessor->thread_count; i++) { if(systemProcessor->threads[i] == NULL) { systemProcessor->threads[i] = thrd; return; } } assert(false); } void scheduler_remove( struct thread_h * thrd ) { LIB_DEBUG_PRINTF("Kernel : unscheduling %p from core %p\n", thrd, systemProcessor); for(int i = 0; i < systemProcessor->thread_count; i++) { if(systemProcessor->threads[i] == thrd) { systemProcessor->threads[i] = NULL; break; } } for(int i = 0; i < systemProcessor->thread_count; i++) { if(systemProcessor->threads[i] != NULL) { return; } } LIB_DEBUG_PRINTF("Kernel : terminating core %p\n\n\n", systemProcessor); systemProcessor->terminated = true; } void kernel_run( void ) { CtxInvokeProcessor(systemProcessor); } // Local Variables: // // mode: c // // tab-width: 4 // // End: //