- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
rffe2fad rafc2427 36 36 #include "invoke.h" 37 37 38 //-----------------------------------------------------------------------------39 // Some assembly required40 #if defined( __i386 )41 #define CtxGet( ctx ) \42 __asm__ volatile ( \43 "movl %%esp,%0\n"\44 "movl %%ebp,%1\n"\45 : "=rm" (ctx.SP),\46 "=rm" (ctx.FP) \47 )48 49 // mxcr : SSE Status and Control bits (control bits are preserved across function calls)50 // fcw : X87 FPU control word (preserved across function calls)51 #define __x87_store \52 uint32_t __mxcr; \53 uint16_t __fcw; \54 __asm__ volatile ( \55 "stmxcsr %0\n" \56 "fnstcw %1\n" \57 : "=m" (__mxcr),\58 "=m" (__fcw) \59 )60 61 #define __x87_load \62 __asm__ volatile ( \63 "fldcw %1\n" \64 "ldmxcsr %0\n" \65 ::"m" (__mxcr),\66 "m" (__fcw) \67 )68 69 #elif defined( __x86_64 )70 #define CtxGet( ctx ) \71 __asm__ volatile ( \72 "movq %%rsp,%0\n"\73 "movq %%rbp,%1\n"\74 : "=rm" (ctx.SP),\75 "=rm" (ctx.FP) \76 )77 78 #define __x87_store \79 uint32_t __mxcr; \80 uint16_t __fcw; \81 __asm__ volatile ( \82 "stmxcsr %0\n" \83 "fnstcw %1\n" \84 : "=m" (__mxcr),\85 "=m" (__fcw) \86 )87 88 #define __x87_load \89 __asm__ volatile ( \90 "fldcw %1\n" \91 "ldmxcsr %0\n" \92 :: "m" (__mxcr),\93 "m" (__fcw) \94 )95 96 97 #elif defined( __ARM_ARCH )98 #define CtxGet( ctx ) __asm__ ( \99 "mov %0,%%sp\n" \100 "mov %1,%%r11\n" \101 : "=rm" (ctx.SP), "=rm" (ctx.FP) )102 #else103 #error unknown hardware architecture104 #endif105 106 //-----------------------------------------------------------------------------107 38 //Start and stop routine for the kernel, declared first to make sure they run first 108 39 static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); … … 111 42 //----------------------------------------------------------------------------- 112 43 // Kernel storage 113 KERNEL_STORAGE(cluster, mainCluster);114 KERNEL_STORAGE(processor, mainProcessor);115 KERNEL_STORAGE(thread_desc, mainThread);116 KERNEL_STORAGE( __stack_t,mainThreadCtx);44 KERNEL_STORAGE(cluster, mainCluster); 45 KERNEL_STORAGE(processor, mainProcessor); 46 KERNEL_STORAGE(thread_desc, mainThread); 47 KERNEL_STORAGE(machine_context_t, mainThreadCtx); 117 48 118 49 cluster * mainCluster; … … 123 54 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters; 124 55 } 125 126 size_t __page_size = 0;127 56 128 57 //----------------------------------------------------------------------------- … … 131 60 NULL, 132 61 NULL, 62 NULL, 133 63 { 1, false, false } 134 64 }; … … 137 67 // Struct to steal stack 138 68 struct current_stack_info_t { 139 __stack_t * storage; // pointer to stack object 69 machine_context_t ctx; 70 unsigned int size; // size of stack 140 71 void *base; // base of stack 72 void *storage; // pointer to stack 141 73 void *limit; // stack grows towards stack limit 142 74 void *context; // address of cfa_context_t 75 void *top; // address of top of storage 143 76 }; 144 77 145 78 void ?{}( current_stack_info_t & this ) { 146 __stack_context_t ctx;147 CtxGet( ctx );148 this. base = ctx.FP;79 CtxGet( this.ctx ); 80 this.base = this.ctx.FP; 81 this.storage = this.ctx.SP; 149 82 150 83 rlimit r; 151 84 getrlimit( RLIMIT_STACK, &r); 152 size_tsize = r.rlim_cur;153 154 this.limit = (void *)(((intptr_t)this.base) - size);85 this.size = r.rlim_cur; 86 87 this.limit = (void *)(((intptr_t)this.base) - this.size); 155 88 this.context = &storage_mainThreadCtx; 89 this.top = this.base; 156 90 } 157 91 158 92 //----------------------------------------------------------------------------- 159 93 // Main thread construction 94 void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) { 95 size = info->size; 96 storage = info->storage; 97 limit = info->limit; 98 base = info->base; 99 context = info->context; 100 top = info->top; 101 userStack = true; 102 } 160 103 161 104 void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) { 162 stack.storage = info->storage; 163 with(*stack.storage) { 164 limit = info->limit; 165 base = info->base; 166 } 167 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*) &stack.storage; 168 *istorage |= 0x1; 105 stack{ info }; 169 106 name = "Main Thread"; 107 errno_ = 0; 170 108 state = Start; 171 109 starter = NULL; 172 last = NULL;173 cancellation = NULL;174 110 } 175 111 176 112 void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) { 177 state = Start;178 113 self_cor{ info }; 179 114 curr_cor = &self_cor; … … 306 241 } 307 242 308 static int * __volatile_errno() __attribute__((noinline));309 static int * __volatile_errno() { asm(""); return &errno; }310 311 243 // KERNEL ONLY 312 244 // runThread runs a thread by context switching 313 245 // from the processor coroutine to the target thread 314 static void runThread(processor * this, thread_desc * thrd_dst) { 246 static void runThread(processor * this, thread_desc * dst) { 247 assert(dst->curr_cor); 315 248 coroutine_desc * proc_cor = get_coroutine(this->runner); 249 coroutine_desc * thrd_cor = dst->curr_cor; 316 250 317 251 // Reset the terminating actions here … … 319 253 320 254 // Update global state 321 kernelTLS.this_thread = thrd_dst; 322 323 // set state of processor coroutine to inactive and the thread to active 324 proc_cor->state = proc_cor->state == Halted ? Halted : Inactive; 325 thrd_dst->state = Active; 326 327 // set context switch to the thread that the processor is executing 328 verify( thrd_dst->context.SP ); 329 CtxSwitch( &proc_cor->context, &thrd_dst->context ); 330 // when CtxSwitch returns we are back in the processor coroutine 331 332 // set state of processor coroutine to active and the thread to inactive 333 thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive; 334 proc_cor->state = Active; 255 kernelTLS.this_thread = dst; 256 257 // Context Switch to the thread 258 ThreadCtxSwitch(proc_cor, thrd_cor); 259 // when ThreadCtxSwitch returns we are back in the processor coroutine 335 260 } 336 261 … … 338 263 static void returnToKernel() { 339 264 coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 340 thread_desc * thrd_src = kernelTLS.this_thread; 341 342 // set state of current coroutine to inactive 343 thrd_src->state = thrd_src->state == Halted ? Halted : Inactive; 344 proc_cor->state = Active; 345 int local_errno = *__volatile_errno(); 346 #if defined( __i386 ) || defined( __x86_64 ) 347 __x87_store; 348 #endif 349 350 // set new coroutine that the processor is executing 351 // and context switch to it 352 verify( proc_cor->context.SP ); 353 CtxSwitch( &thrd_src->context, &proc_cor->context ); 354 355 // set state of new coroutine to active 356 proc_cor->state = proc_cor->state == Halted ? Halted : Inactive; 357 thrd_src->state = Active; 358 359 #if defined( __i386 ) || defined( __x86_64 ) 360 __x87_load; 361 #endif 362 *__volatile_errno() = local_errno; 265 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine; 266 ThreadCtxSwitch(thrd_cor, proc_cor); 363 267 } 364 268 … … 403 307 processor * proc = (processor *) arg; 404 308 kernelTLS.this_processor = proc; 309 kernelTLS.this_coroutine = NULL; 405 310 kernelTLS.this_thread = NULL; 406 311 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1]; … … 409 314 // to waste the perfectly valid stack create by pthread. 410 315 current_stack_info_t info; 411 __stack_t ctx;412 info. storage= &ctx;316 machine_context_t ctx; 317 info.context = &ctx; 413 318 (proc->runner){ proc, &info }; 414 319 415 __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack. storage);320 __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.base); 416 321 417 322 //Set global state 323 kernelTLS.this_coroutine = get_coroutine(proc->runner); 418 324 kernelTLS.this_thread = NULL; 419 325 … … 444 350 445 351 // KERNEL_ONLY 446 void kernel_first_resume( processor * this) {447 thread_desc * src = mainThread;352 void kernel_first_resume(processor * this) { 353 coroutine_desc * src = kernelTLS.this_coroutine; 448 354 coroutine_desc * dst = get_coroutine(this->runner); 449 355 450 356 verify( ! kernelTLS.preemption_state.enabled ); 451 357 452 __stack_prepare( &dst->stack, 65000);358 create_stack(&dst->stack, dst->stack.size); 453 359 CtxStart(&this->runner, CtxInvokeCoroutine); 454 360 455 361 verify( ! kernelTLS.preemption_state.enabled ); 456 362 457 dst->last = &src->self_cor;458 dst->starter = dst->starter ? dst->starter : &src->self_cor;363 dst->last = src; 364 dst->starter = dst->starter ? dst->starter : src; 459 365 460 366 // set state of current coroutine to inactive 461 367 src->state = src->state == Halted ? Halted : Inactive; 462 368 369 // set new coroutine that task is executing 370 kernelTLS.this_coroutine = dst; 371 372 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. 373 // Therefore, when first creating a coroutine, interrupts are enable before calling the main. 374 // This is consistent with thread creation. However, when creating the main processor coroutine, 375 // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will 376 // stay disabled. 377 disable_interrupts(); 378 463 379 // context switch to specified coroutine 464 verify( dst->context.SP);465 CtxSwitch( &src->context, &dst->context );380 assert( src->stack.context ); 381 CtxSwitch( src->stack.context, dst->stack.context ); 466 382 // when CtxSwitch returns we are back in the src coroutine 467 383 … … 470 386 471 387 verify( ! kernelTLS.preemption_state.enabled ); 472 }473 474 // KERNEL_ONLY475 void kernel_last_resume( processor * this ) {476 coroutine_desc * src = &mainThread->self_cor;477 coroutine_desc * dst = get_coroutine(this->runner);478 479 verify( ! kernelTLS.preemption_state.enabled );480 verify( dst->starter == src );481 verify( dst->context.SP );482 483 // context switch to the processor484 CtxSwitch( &src->context, &dst->context );485 388 } 486 389 … … 491 394 void ScheduleThread( thread_desc * thrd ) { 492 395 verify( thrd ); 493 verify( thrd->s tate != Halted );396 verify( thrd->self_cor.state != Halted ); 494 397 495 398 verify( ! kernelTLS.preemption_state.enabled ); … … 648 551 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 649 552 650 __page_size = sysconf( _SC_PAGESIZE );651 652 553 __cfa_dbg_global_clusters.list{ __get }; 653 554 __cfa_dbg_global_clusters.lock{}; … … 664 565 mainThread = (thread_desc *)&storage_mainThread; 665 566 current_stack_info_t info; 666 info.storage = (__stack_t*)&storage_mainThreadCtx;667 567 (*mainThread){ &info }; 668 568 … … 699 599 kernelTLS.this_processor = mainProcessor; 700 600 kernelTLS.this_thread = mainThread; 601 kernelTLS.this_coroutine = &mainThread->self_cor; 701 602 702 603 // Enable preemption … … 733 634 // which is currently here 734 635 __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE); 735 kernel_last_resume( kernelTLS.this_processor);636 returnToKernel(); 736 637 mainThread->self_cor.state = Halted; 737 638 … … 819 720 __cfaabi_dbg_bits_write( abort_text, len ); 820 721 821 if ( &thrd->self_cor != thrd->curr_cor) {822 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor);722 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) { 723 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine ); 823 724 __cfaabi_dbg_bits_write( abort_text, len ); 824 725 }
Note:
See TracChangeset
for help on using the changeset viewer.