Changes in src/libcfa/concurrency/kernel.c [8def349:bd98b58]
- File:
-
- 1 edited
-
src/libcfa/concurrency/kernel.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
r8def349 rbd98b58 32 32 #include "invoke.h" 33 33 34 //----------------------------------------------------------------------------- 35 // Kernel storage 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 36 70 struct processorCtx_t { 37 71 processor * proc; … … 41 75 DECL_COROUTINE(processorCtx_t) 42 76 77 void ?{}(processorCtx_t * this, processor * proc) { 78 (&this->c){}; 79 this->proc = proc; 80 } 81 82 void CtxInvokeProcessor(processor * proc) { 83 processorCtx_t proc_cor_storage = {proc}; 84 resume( &proc_cor_storage ); 85 } 86 87 //----------------------------------------------------------------------------- 88 // Processor running routines 89 void main(processorCtx_t * ctx); 90 thread_h * nextThread(cluster * this); 91 void runThread(processor * this, thread_h * dst); 92 void spin(processor * this, unsigned int * spin_count); 93 94 void main(processorCtx_t * ctx) { 95 processor * this = ctx->proc; 96 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this); 97 98 thread_h * readyThread = NULL; 99 for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) { 100 101 readyThread = nextThread( this->cltr ); 102 103 if(readyThread) { 104 runThread(this, readyThread); 105 spin_count = 0; 106 } else { 107 spin(this, &spin_count); 108 } 109 } 110 111 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this); 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 this->current_thread = dst; 123 this->current_coroutine = thrd_ctx; 124 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context ); 125 this->current_coroutine = proc_ctx; 126 // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine); 127 128 // when CtxSwitch returns we are back in the processor coroutine 129 } 130 131 void spin(processor * this, unsigned int * spin_count) { 132 (*spin_count)++; 133 } 134 135 //----------------------------------------------------------------------------- 136 // Scheduler routines 137 void thread_schedule( thread_h * thrd ) { 138 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 139 append( &systemProcessor->cltr->ready_queue, thrd ); 140 } 141 142 thread_h * nextThread(cluster * this) { 143 return pop_head( &this->ready_queue ); 144 } 145 146 //----------------------------------------------------------------------------- 147 // Kernel storage 43 148 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)] 44 149 … … 49 154 KERNEL_STORAGE(machine_context_t, mainThread_context); 50 155 51 cluster * systemCluster;52 processor * systemProcessor;53 thread_h * mainThread;54 55 void kernel_startup(void) __attribute__((constructor(101)));56 void kernel_shutdown(void) __attribute__((destructor(101)));57 58 //-----------------------------------------------------------------------------59 // Global state60 61 thread_local processor * this_processor;62 63 processor * get_this_processor() {64 return this_processor;65 }66 67 coroutine * this_coroutine(void) {68 return this_processor->current_coroutine;69 }70 71 thread_h * this_thread(void) {72 return this_processor->current_thread;73 }74 75 156 //----------------------------------------------------------------------------- 76 157 // Main thread construction 77 struct current_stack_info_t {158 struct mainThread_info_t { 78 159 machine_context_t ctx; 79 160 unsigned int size; // size of stack … … 85 166 }; 86 167 87 void ?{}( current_stack_info_t * this ) {168 void ?{}( mainThread_info_t * this ) { 88 169 CtxGet( &this->ctx ); 89 170 this->base = this->ctx.FP; … … 99 180 } 100 181 101 void ?{}( coStack_t * this, current_stack_info_t * info) {182 void ?{}( coStack_t * this, mainThread_info_t * info) { 102 183 this->size = info->size; 103 184 this->storage = info->storage; … … 109 190 } 110 191 111 void ?{}( coroutine * this, current_stack_info_t * info) {192 void ?{}( coroutine * this, mainThread_info_t * info) { 112 193 (&this->stack){ info }; 113 194 this->name = "Main Thread"; … … 117 198 } 118 199 119 void ?{}( thread_h * this, current_stack_info_t * info) {200 void ?{}( thread_h * this, mainThread_info_t * info) { 120 201 (&this->c){ info }; 121 }122 123 //-----------------------------------------------------------------------------124 // Processor coroutine125 void ?{}(processorCtx_t * this, processor * proc) {126 (&this->c){};127 this->proc = proc;128 proc->ctx = this;129 }130 131 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {132 (&this->c){ info };133 this->proc = proc;134 proc->ctx = this;135 }136 137 void start(processor * this);138 139 void ?{}(processor * this) {140 this{ systemCluster };141 }142 143 void ?{}(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 153 void ?{}(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 165 void ^?{}(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 173 void ?{}(cluster * this) {174 ( &this->ready_queue ){};175 pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );176 }177 178 void ^?{}(cluster * this) {179 pthread_spin_destroy( &this->lock );180 }181 182 //-----------------------------------------------------------------------------183 // Processor running routines184 void main(processorCtx_t * ctx);185 thread_h * nextThread(cluster * this);186 void runThread(processor * this, thread_h * dst);187 void spin(processor * this, unsigned int * spin_count);188 189 void main(processorCtx_t * ctx) {190 processor * this = ctx->proc;191 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);192 193 thread_h * readyThread = NULL;194 for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {195 196 readyThread = nextThread( this->cltr );197 198 if(readyThread) {199 runThread(this, readyThread);200 spin_count = 0;201 } else {202 spin(this, &spin_count);203 }204 }205 206 LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this);207 unlock( &this->lock );208 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);209 }210 211 void runThread(processor * this, thread_h * dst) {212 coroutine * proc_ctx = get_coroutine(this->ctx);213 coroutine * thrd_ctx = get_coroutine(dst);214 thrd_ctx->last = proc_ctx;215 216 // context switch to specified coroutine217 // Which is now the current_coroutine218 // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);219 this->current_thread = dst;220 this->current_coroutine = thrd_ctx;221 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );222 this->current_coroutine = proc_ctx;223 // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);224 225 // when CtxSwitch returns we are back in the processor coroutine226 }227 228 void spin(processor * this, unsigned int * spin_count) {229 (*spin_count)++;230 }231 232 void * CtxInvokeProcessor(void * arg) {233 processor * proc = (processor *) arg;234 this_processor = proc;235 // SKULLDUGGERY: We want to create a context for the processor coroutine236 // which is needed for the 2-step context switch. However, there is no reason237 // 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 threads256 257 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't258 // resume it to start it like it normally would, it will just context switch259 // back to here. Instead directly call the main since we already are on the260 // 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 271 void 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 284 //-----------------------------------------------------------------------------285 // Scheduler routines286 void thread_schedule( thread_h * thrd ) {287 assertf( thrd->next == NULL, "Expected null got %p", thrd->next );288 289 pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };290 append( &systemProcessor->cltr->ready_queue, thrd );291 }292 293 thread_h * nextThread(cluster * this) {294 pthread_spinlock_guard guard = { &this->lock };295 return pop_head( &this->ready_queue );296 202 } 297 203 … … 304 210 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 305 211 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 ); 212 mainThread_info_t ctx; 314 213 315 214 // Start by initializing the main thread 316 215 mainThread = (thread_h *)&mainThread_storage; 317 mainThread{ & info};216 mainThread{ &ctx }; 318 217 319 218 // Initialize the system cluster … … 321 220 systemCluster{}; 322 221 323 // Initialize the system processor and the system processor ctx 222 // Initialize the system processor 223 systemProcessor = (processor *)&systemProcessor_storage; 224 systemProcessor{ systemCluster }; 225 226 // Initialize the system processor ctx 324 227 // (the coroutine that contains the processing control flow) 325 systemProcessor = (processor *)&systemProcessor_storage;326 systemProcessor { systemCluster, (processorCtx_t *)&systemProcessorCtx_storage};228 systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage; 229 systemProcessor->ctx{ systemProcessor }; 327 230 328 231 // Add the main thread to the ready queue … … 383 286 384 287 void lock( simple_lock * this ) { 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 } 288 append( &this->blocked, this_thread() ); 389 289 suspend(); 390 290 }
Note:
See TracChangeset
for help on using the changeset viewer.