- File:
-
- 1 edited
-
libcfa/src/concurrency/coroutine.hfa (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.hfa
r212c2187 r5b11c25 64 64 forall(dtype T | is_coroutine(T)) 65 65 void CtxStart(T * this, void ( *invoke)(T *)); 66 67 extern void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__)); 68 69 extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch"); 70 extern void CtxStore ( struct __stack_context_t * from, __attribute__((noreturn)) void (*__callback)(void) ) asm ("CtxStore"); 71 extern void CtxRet ( struct __stack_context_t * to ) asm ("CtxRet") __attribute__ ((__noreturn__)); 66 72 } 67 73 68 74 // Private wrappers for context switch and stack creation 69 extern void CoroutineCtxSwitch(coroutine_desc * src, coroutine_desc * dst); 70 extern void create_stack( coStack_t * this, unsigned int storageSize ); 75 // Wrapper for co 76 static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 77 // set state of current coroutine to inactive 78 src->state = src->state == Halted ? Halted : Inactive; 79 80 // set new coroutine that task is executing 81 TL_GET( this_thread )->curr_cor = dst; 82 83 // context switch to specified coroutine 84 verify( dst->context.SP ); 85 CtxSwitch( &src->context, &dst->context ); 86 // when CtxSwitch returns we are back in the src coroutine 87 88 // set state of new coroutine to active 89 src->state = Active; 90 91 if( unlikely(src->cancellation != NULL) ) { 92 _CtxCoroutine_Unwind(src->cancellation, src); 93 } 94 } 95 96 extern void __stack_prepare ( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 71 97 72 98 // Suspend implementation inlined for performance … … 102 128 coroutine_desc * dst = get_coroutine(cor); 103 129 104 if( unlikely( !dst->stack.base) ) {105 create_stack(&dst->stack, dst->stack.size);130 if( unlikely(dst->context.SP == NULL) ) { 131 __stack_prepare(&dst->stack, 65000); 106 132 CtxStart(&cor, CtxInvokeCoroutine); 107 133 } … … 146 172 } 147 173 148 149 150 // static inline bool suspend_checkpoint(void) { 151 // // optimization : read TLS once and reuse it 152 // // Safety note: this is preemption safe since if 153 // // preemption occurs after this line, the pointer 154 // // will also migrate which means this value will 155 // // stay in syn with the TLS 156 // // set state of current coroutine to inactive 157 // this->state = Checkpoint; 158 159 // // context switch to specified coroutine 160 // 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 active 167 // src->state = Active; 168 169 // enable_interrupts( __cfaabi_dbg_ctx ); 170 // // Safety note : This could cause some false positives due to preemption 171 // 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 // } 174 static inline void suspend_then(fptr_t call) { 175 // optimization : read TLS once and reuse it 176 // Safety note: this is preemption safe since if 177 // preemption occurs after this line, the pointer 178 // will also migrate which means this value will 179 // stay in syn with the TLS 180 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 181 182 assertf( src->last != 0, 183 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n" 184 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 185 src->name, src ); 186 assertf( src->last->state != Halted, 187 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n" 188 "Possible cause is terminated coroutine's main routine has already returned.", 189 src->name, src, src->last->name, src->last ); 190 191 src->state = PreInactive; 192 193 // context switch to specified coroutine 194 assert( src->context.SP ); 195 196 __attribute__((noreturn)) void __suspend_callback(void) { 197 call(); 198 199 // set state of current coroutine to inactive 200 src->state = src->state == Halted ? Halted : Inactive; 201 202 TL_GET( this_thread )->curr_cor = src->last; 203 204 // context switch to specified coroutine 205 assert( src->last->context.SP ); 206 CtxRet( &src->last->context ); 207 208 abort(); 209 } 210 CtxStore( &src->context, __suspend_callback ); 211 // when CtxStore returns we are back in the src coroutine 212 213 // set state of new coroutine to active 214 src->state = Active; 215 216 if( unlikely(src->cancellation != NULL) ) { 217 _CtxCoroutine_Unwind(src->cancellation, src); 218 } 219 220 return; 221 } 179 222 180 223 // static inline void suspend_return(void) {
Note:
See TracChangeset
for help on using the changeset viewer.