Changes in / [2fabdc02:bee653c]
- Location:
- libcfa/src/concurrency
- Files:
-
- 7 edited
-
CtxSwitch-x86_64.S (modified) (1 diff)
-
coroutine.cfa (modified) (6 diffs)
-
coroutine.hfa (modified) (4 diffs)
-
invoke.c (modified) (5 diffs)
-
invoke.h (modified) (4 diffs)
-
kernel.cfa (modified) (8 diffs)
-
thread.cfa (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/CtxSwitch-x86_64.S
r2fabdc02 rbee653c 88 88 ret 89 89 90 //.text91 // .align 292 //.globl CtxStore93 //CtxStore:94 // // Save floating & SSE control words on the stack.95 //96 // subq $8,%rsp97 // stmxcsr 0(%rsp) // 4 bytes98 // fnstcw 4(%rsp) // 2 bytes99 //100 // // Save volatile registers on the stack.101 //102 // pushq %r15103 // pushq %r14104 // pushq %r13105 // pushq %r12106 // pushq %rbx107 //108 // // Save old context in the "from" area.109 //110 // movq %rsp,SP_OFFSET(%rdi)111 // movq %rbp,FP_OFFSET(%rdi)112 //113 // // Return to thread114 //115 // ret116 //117 //.text118 // .align 2119 //.globl CtxRet120 //CtxRet:121 // // Load new context from the "to" area.122 //123 // movq SP_OFFSET(%rdi),%rsp124 // movq FP_OFFSET(%rdi),%rbp125 //126 // // Load volatile registers from the stack.127 //128 // popq %rbx129 // popq %r12130 // popq %r13131 // popq %r14132 // popq %r15133 //134 // // Load floating & SSE control words from the stack.135 //136 // fldcw 4(%rsp)137 // ldmxcsr 0(%rsp)138 // addq $8,%rsp139 //140 // // Return to thread.141 //142 // ret143 144 145 90 .text 146 91 .align 2 -
libcfa/src/concurrency/coroutine.cfa
r2fabdc02 rbee653c 35 35 36 36 extern "C" { 37 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage , struct coroutine_desc *) __attribute__ ((__noreturn__));37 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) __attribute__ ((__noreturn__)); 38 38 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__)); 39 39 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) { … … 84 84 void ^?{}(coroutine_desc& this) { 85 85 if(this.state != Halted && this.state != Start) { 86 coroutine_desc * src = TL_GET( this_ thread )->curr_cor;86 coroutine_desc * src = TL_GET( this_coroutine ); 87 87 coroutine_desc * dst = &this; 88 88 … … 115 115 // Wrapper for co 116 116 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 117 // Safety note : Preemption must be disabled since there is a race condition 118 // kernelTLS.this_thread->curr_cor and $rsp/$rbp must agree at all times 117 // Safety note : This could cause some false positives due to preemption 119 118 verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate ); 120 119 disable_interrupts(); … … 124 123 125 124 // set new coroutine that task is executing 126 TL_GET( this_thread )->curr_cor= dst;125 kernelTLS.this_coroutine = dst; 127 126 128 127 // context switch to specified coroutine … … 135 134 136 135 enable_interrupts( __cfaabi_dbg_ctx ); 136 // Safety note : This could cause some false positives due to preemption 137 137 verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate ); 138 138 139 140 139 if( unlikely(src->cancellation != NULL) ) { 141 _CtxCoroutine_Unwind(src->cancellation , src);140 _CtxCoroutine_Unwind(src->cancellation); 142 141 } 143 142 } //ctxSwitchDirect … … 198 197 } 199 198 200 void __leave_coroutine( coroutine_desc * src ) { 199 void __leave_coroutine() { 200 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 201 201 coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter; 202 202 -
libcfa/src/concurrency/coroutine.hfa
r2fabdc02 rbee653c 77 77 // will also migrate which means this value will 78 78 // stay in syn with the TLS 79 coroutine_desc * src = TL_GET( this_ thread )->curr_cor;79 coroutine_desc * src = TL_GET( this_coroutine ); 80 80 81 81 assertf( src->last != 0, … … 99 99 // will also migrate which means this value will 100 100 // stay in syn with the TLS 101 coroutine_desc * src = TL_GET( this_ thread )->curr_cor;101 coroutine_desc * src = TL_GET( this_coroutine ); 102 102 coroutine_desc * dst = get_coroutine(cor); 103 103 … … 129 129 // will also migrate which means this value will 130 130 // stay in syn with the TLS 131 coroutine_desc * src = TL_GET( this_ thread )->curr_cor;131 coroutine_desc * src = TL_GET( this_coroutine ); 132 132 133 133 // not resuming self ? … … 146 146 } 147 147 148 149 150 // static inline bool suspend_checkpoint(void) {151 // // optimization : read TLS once and reuse it152 // // Safety note: this is preemption safe since if153 // // preemption occurs after this line, the pointer154 // // will also migrate which means this value will155 // // stay in syn with the TLS156 // // set state of current coroutine to inactive157 // this->state = Checkpoint;158 159 // // context switch to specified coroutine160 // assert( src->stack.context );161 162 // CtxStore(src->stack.context);163 164 // bool ret = this->state == Checkpoint;165 166 // // set state of new coroutine to active167 // src->state = Active;168 169 // enable_interrupts( __cfaabi_dbg_ctx );170 // // Safety note : This could cause some false positives due to preemption171 // verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );172 173 // if( unlikely(src->cancellation != NULL) ) {174 // _CtxCoroutine_Unwind(src->cancellation);175 // }176 177 // return ret;178 // }179 180 // static inline void suspend_return(void) {181 // // optimization : read TLS once and reuse it182 // // Safety note: this is preemption safe since if183 // // preemption occurs after this line, the pointer184 // // will also migrate which means this value will185 // // stay in syn with the TLS186 // coroutine_desc * src = TL_GET( this_thread )->curr_cor;187 188 // assertf( src->last != 0,189 // "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"190 // "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",191 // src->name, src );192 // assertf( src->last->state != Halted,193 // "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"194 // "Possible cause is terminated coroutine's main routine has already returned.",195 // src->name, src, src->last->name, src->last );196 197 // // Safety note : Preemption must be disabled here since kernelTLS.this_coroutine must always be up to date198 // verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );199 // disable_interrupts();200 201 // // set state of current coroutine to inactive202 // src->state = src->state == Halted ? Halted : Inactive;203 204 // // set new coroutine that task is executing205 // kernelTLS.this_coroutine = dst;206 207 // // context switch to specified coroutine208 // assert( src->stack.context );209 // CtxRet( src->stack.context );210 211 // abort();212 // }213 214 148 // Local Variables: // 215 149 // mode: c // -
libcfa/src/concurrency/invoke.c
r2fabdc02 rbee653c 28 28 29 29 extern void __suspend_internal(void); 30 extern void __leave_coroutine( struct coroutine_desc *);31 extern void __finish_creation( struct coroutine_desc *);30 extern void __leave_coroutine(void); 31 extern void __finish_creation(void); 32 32 extern void __leave_thread_monitor( struct thread_desc * this ); 33 33 extern void disable_interrupts(); … … 52 52 53 53 //Final suspend, should never return 54 __leave_coroutine( cor);54 __leave_coroutine(); 55 55 __cabi_abort( "Resumed dead coroutine" ); 56 56 } … … 62 62 __attribute((__unused__)) struct _Unwind_Exception * unwind_exception, 63 63 __attribute((__unused__)) struct _Unwind_Context * context, 64 void * param64 __attribute((__unused__)) void * param 65 65 ) { 66 66 if( actions & _UA_END_OF_STACK ) { 67 67 // We finished unwinding the coroutine, 68 68 // leave it 69 __leave_coroutine( param);69 __leave_coroutine(); 70 70 __cabi_abort( "Resumed dead coroutine" ); 71 71 } … … 75 75 } 76 76 77 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage , struct coroutine_desc * cor) __attribute__ ((__noreturn__));78 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage , struct coroutine_desc * cor) {79 _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, cor);77 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) __attribute__ ((__noreturn__)); 78 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) { 79 _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, NULL ); 80 80 printf("UNWIND ERROR %d after force unwind\n", ret); 81 81 abort(); … … 88 88 void *this 89 89 ) { 90 // First suspend, once the thread arrives here, 91 // the function pointer to main can be invalidated without risk 92 __finish_creation(); 93 90 94 // Fetch the thread handle from the user defined thread structure 91 95 struct thread_desc* thrd = get_thread( this ); 92 93 // First suspend, once the thread arrives here,94 // the function pointer to main can be invalidated without risk95 __finish_creation(&thrd->self_cor);96 97 // Restore the last to NULL, we clobbered because of the thunk problem98 96 thrd->self_cor.last = NULL; 99 97 -
libcfa/src/concurrency/invoke.h
r2fabdc02 rbee653c 50 50 51 51 extern thread_local struct KernelThreadData { 52 struct coroutine_desc * volatile this_coroutine; 52 53 struct thread_desc * volatile this_thread; 53 54 struct processor * volatile this_processor; … … 60 61 } kernelTLS __attribute__ ((tls_model ( "initial-exec" ))); 61 62 } 63 64 static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); } 65 static inline struct thread_desc * volatile active_thread () { return TL_GET( this_thread ); } 66 static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE 62 67 #endif 63 68 … … 165 170 struct thread_desc * prev; 166 171 } node; 167 }; 168 169 #ifdef __cforall 170 extern "Cforall" { 171 static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_thread )->curr_cor; } 172 static inline struct thread_desc * volatile active_thread () { return TL_GET( this_thread ); } 173 static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE 174 172 }; 173 174 #ifdef __cforall 175 extern "Cforall" { 175 176 static inline thread_desc * & get_next( thread_desc & this ) { 176 177 return this.next; … … 231 232 extern void CtxInvokeStub( void ); 232 233 void CtxSwitch( void * from, void * to ) asm ("CtxSwitch"); 233 // void CtxStore ( void * this ) asm ("CtxStore");234 // void CtxRet ( void * dst ) asm ("CtxRet");235 234 236 235 #if defined( __i386 ) -
libcfa/src/concurrency/kernel.cfa
r2fabdc02 rbee653c 60 60 NULL, 61 61 NULL, 62 NULL, 62 63 { 1, false, false } 63 64 }; … … 262 263 static void returnToKernel() { 263 264 coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 264 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor ;265 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine; 265 266 ThreadCtxSwitch(thrd_cor, proc_cor); 266 267 } … … 306 307 processor * proc = (processor *) arg; 307 308 kernelTLS.this_processor = proc; 309 kernelTLS.this_coroutine = NULL; 308 310 kernelTLS.this_thread = NULL; 309 311 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1]; … … 319 321 320 322 //Set global state 323 kernelTLS.this_coroutine = get_coroutine(proc->runner); 321 324 kernelTLS.this_thread = NULL; 322 325 … … 348 351 // KERNEL_ONLY 349 352 void kernel_first_resume(processor * this) { 350 coroutine_desc * src = mainThread->curr_cor;353 coroutine_desc * src = kernelTLS.this_coroutine; 351 354 coroutine_desc * dst = get_coroutine(this->runner); 352 355 … … 363 366 // set state of current coroutine to inactive 364 367 src->state = src->state == Halted ? Halted : Inactive; 368 369 // set new coroutine that task is executing 370 kernelTLS.this_coroutine = dst; 365 371 366 372 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. … … 593 599 kernelTLS.this_processor = mainProcessor; 594 600 kernelTLS.this_thread = mainThread; 601 kernelTLS.this_coroutine = &mainThread->self_cor; 595 602 596 603 // Enable preemption … … 713 720 __cfaabi_dbg_bits_write( abort_text, len ); 714 721 715 if ( &thrd->self_cor != thrd->curr_cor) {716 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 ); 717 724 __cfaabi_dbg_bits_write( abort_text, len ); 718 725 } -
libcfa/src/concurrency/thread.cfa
r2fabdc02 rbee653c 75 75 coroutine_desc* thrd_c = get_coroutine(this); 76 76 thread_desc * thrd_h = get_thread (this); 77 thrd_c->last = TL_GET( this_ thread )->curr_cor;77 thrd_c->last = TL_GET( this_coroutine ); 78 78 79 79 // __cfaabi_dbg_print_safe("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h); … … 81 81 disable_interrupts(); 82 82 create_stack(&thrd_c->stack, thrd_c->stack.size); 83 kernelTLS.this_coroutine = thrd_c; 83 84 CtxStart(&this, CtxInvokeThread); 84 85 assert( thrd_c->last->stack.context ); … … 91 92 extern "C" { 92 93 // KERNEL ONLY 93 void __finish_creation(coroutine_desc * thrd_c) { 94 void __finish_creation(void) { 95 coroutine_desc* thrd_c = kernelTLS.this_coroutine; 94 96 ThreadCtxSwitch( thrd_c, thrd_c->last ); 95 97 } … … 118 120 // set new coroutine that the processor is executing 119 121 // and context switch to it 122 kernelTLS.this_coroutine = dst; 120 123 assert( src->stack.context ); 121 124 CtxSwitch( src->stack.context, dst->stack.context ); 125 kernelTLS.this_coroutine = src; 122 126 123 127 // set state of new coroutine to active
Note:
See TracChangeset
for help on using the changeset viewer.