Changeset f32e53e
- Timestamp:
- Jul 7, 2017, 11:55:32 AM (6 years ago)
- 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:
- 3f12158
- Parents:
- b5f9829
- Location:
- src/libcfa/concurrency
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/CtxSwitch-i386.S
rb5f9829 rf32e53e 98 98 ret 99 99 100 .text101 .align 2102 .globl CtxGet103 CtxGet:104 movl %esp,SP_OFFSET(%eax)105 movl %ebp,FP_OFFSET(%eax)106 107 ret108 109 100 // Local Variables: // 110 101 // compile-command: "make install" // -
src/libcfa/concurrency/CtxSwitch-x86_64.S
rb5f9829 rf32e53e 1 // -*- Mode: Asm -*- 1 // -*- Mode: Asm -*- 2 2 // 3 3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo … … 18 18 // Free Software Foundation; either version 2.1 of the License, or (at your 19 19 // option) any later version. 20 // 20 // 21 21 // This library is distributed in the hope that it will be useful, but WITHOUT 22 22 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 23 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 24 24 // for more details. 25 // 25 // 26 26 // You should have received a copy of the GNU Lesser General Public License 27 27 // along with this library. 28 // 28 // 29 29 30 30 // This context switch routine depends on the fact that the stack of a new … … 93 93 .globl CtxInvokeStub 94 94 CtxInvokeStub: 95 movq %rbx, %rdi 95 movq %rbx, %rdi 96 96 jmp *%r12 97 98 .text99 .align 2100 .globl CtxGet101 CtxGet:102 movq %rsp,SP_OFFSET(%rdi)103 movq %rbp,FP_OFFSET(%rdi)104 105 ret106 97 107 98 // Local Variables: // -
src/libcfa/concurrency/invoke.h
rb5f9829 rf32e53e 99 99 #ifndef _INVOKE_PRIVATE_H_ 100 100 #define _INVOKE_PRIVATE_H_ 101 101 102 102 struct machine_context_t { 103 103 void *SP; … … 109 109 extern void CtxInvokeStub( void ); 110 110 void CtxSwitch( void * from, void * to ) asm ("CtxSwitch"); 111 void CtxGet( void * this ) asm ("CtxGet"); 111 112 #if defined( __x86_64__ ) 113 #define CtxGet( ctx ) __asm__ ( \ 114 "movq %%rsp,%0\n" \ 115 "movq %%rbp,%1\n" \ 116 : "=rm" (ctx.SP), "=rm" (ctx.FP) ) 117 #elif defined( __i386__ ) 118 #define CtxGet( ctx ) __asm__ ( \ 119 "movl %%esp,%0\n" \ 120 "movl %%ebp,%1\n" \ 121 : "=rm" (ctx.SP), "=rm" (ctx.FP) ) 122 #endif 112 123 113 124 #endif //_INVOKE_PRIVATE_H_ -
src/libcfa/concurrency/kernel.c
rb5f9829 rf32e53e 72 72 // Main thread construction 73 73 struct current_stack_info_t { 74 machine_context_t ctx; 74 machine_context_t ctx; 75 75 unsigned int size; // size of stack 76 76 void *base; // base of stack … … 82 82 83 83 void ?{}( current_stack_info_t * this ) { 84 CtxGet( &this->ctx );84 CtxGet( this->ctx ); 85 85 this->base = this->ctx.FP; 86 86 this->storage = this->ctx.SP; … … 106 106 107 107 void ?{}( coroutine_desc * this, current_stack_info_t * info) { 108 (&this->stack){ info }; 108 (&this->stack){ info }; 109 109 this->name = "Main Thread"; 110 110 this->errno_ = 0; … … 184 184 185 185 void ^?{}(cluster * this) { 186 186 187 187 } 188 188 … … 203 203 204 204 thread_desc * readyThread = NULL; 205 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 205 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 206 206 { 207 207 readyThread = nextThread( this->cltr ); … … 229 229 } 230 230 231 // runThread runs a thread by context switching 232 // from the processor coroutine to the target thread 231 // runThread runs a thread by context switching 232 // from the processor coroutine to the target thread 233 233 void runThread(processor * this, thread_desc * dst) { 234 234 coroutine_desc * proc_cor = get_coroutine(this->runner); 235 235 coroutine_desc * thrd_cor = get_coroutine(dst); 236 236 237 237 //Reset the terminating actions here 238 238 this->finish.action_code = No_Action; … … 246 246 } 247 247 248 // Once a thread has finished running, some of 248 // Once a thread has finished running, some of 249 249 // its final actions must be executed from the kernel 250 250 void finishRunning(processor * this) { … … 256 256 } 257 257 else if( this->finish.action_code == Release_Schedule ) { 258 unlock( this->finish.lock ); 258 unlock( this->finish.lock ); 259 259 ScheduleThread( this->finish.thrd ); 260 260 } … … 291 291 // SKULLDUGGERY: We want to create a context for the processor coroutine 292 292 // which is needed for the 2-step context switch. However, there is no reason 293 // to waste the perfectly valid stack create by pthread. 293 // to waste the perfectly valid stack create by pthread. 294 294 current_stack_info_t info; 295 295 machine_context_t ctx; … … 306 306 LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx); 307 307 308 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 309 // resume it to start it like it normally would, it will just context switch 310 // back to here. Instead directly call the main since we already are on the 308 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 309 // resume it to start it like it normally would, it will just context switch 310 // back to here. Instead directly call the main since we already are on the 311 311 // appropriate stack. 312 312 proc_cor_storage.__cor.state = Active; … … 315 315 316 316 // Main routine of the core returned, the core is now fully terminated 317 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 317 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 318 318 319 319 return NULL; … … 322 322 void start(processor * this) { 323 323 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 324 324 325 325 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 326 326 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 328 328 } 329 329 … … 334 334 335 335 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 336 336 337 337 lock( &systemProcessor->proc.cltr->lock ); 338 338 append( &systemProcessor->proc.cltr->ready_queue, thrd ); … … 392 392 // Kernel boot procedures 393 393 void kernel_startup(void) { 394 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 394 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 395 395 396 396 // Start by initializing the main thread 397 // SKULLDUGGERY: the mainThread steals the process main thread 397 // SKULLDUGGERY: the mainThread steals the process main thread 398 398 // which will then be scheduled by the systemProcessor normally 399 399 mainThread = (thread_desc *)&mainThread_storage; … … 417 417 systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage }; 418 418 419 // Add the main thread to the ready queue 419 // Add the main thread to the ready queue 420 420 // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread 421 421 ScheduleThread(mainThread); … … 428 428 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX 429 429 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 430 // mainThread is on the ready queue when this call is made. 430 // mainThread is on the ready queue when this call is made. 431 431 resume( systemProcessor->proc.runner ); 432 432 … … 457 457 ^(mainThread){}; 458 458 459 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 459 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 460 460 } 461 461 … … 473 473 kernel_abort_called = true; 474 474 unlock( &kernel_abort_lock ); 475 } 475 } 476 476 else { 477 477 unlock( &kernel_abort_lock ); 478 478 479 479 sigset_t mask; 480 480 sigemptyset( &mask ); … … 482 482 sigaddset( &mask, SIGUSR1 ); // block SIGUSR1 signals 483 483 sigsuspend( &mask ); // block the processor to prevent further damage during abort 484 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 484 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 485 485 } 486 486 … … 497 497 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine()->name, this_coroutine() ); 498 498 __lib_debug_write( STDERR_FILENO, abort_text, len ); 499 } 499 } 500 500 else { 501 501 __lib_debug_write( STDERR_FILENO, ".\n", 2 ); … … 590 590 } 591 591 head->next = NULL; 592 } 592 } 593 593 return head; 594 594 } … … 609 609 this->top = top->next; 610 610 top->next = NULL; 611 } 611 } 612 612 return top; 613 613 }
Note: See TracChangeset
for help on using the changeset viewer.