Changeset 6a490b2 for libcfa/src/concurrency/coroutine.hfa
- Timestamp:
- May 11, 2020, 1:53:29 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 504a7dc
- Parents:
- b7d6a36 (diff), a7b486b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.hfa
rb7d6a36 r6a490b2 25 25 trait is_coroutine(dtype T) { 26 26 void main(T & this); 27 coroutine_desc* get_coroutine(T & this);27 $coroutine * get_coroutine(T & this); 28 28 }; 29 29 30 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X& this) { return &this.__cor; } void main(X& this)30 #define DECL_COROUTINE(X) static inline $coroutine* get_coroutine(X& this) { return &this.__cor; } void main(X& this) 31 31 32 32 //----------------------------------------------------------------------------- … … 35 35 // void ^?{}( coStack_t & this ); 36 36 37 void ?{}( coroutine_desc& this, const char name[], void * storage, size_t storageSize );38 void ^?{}( coroutine_desc& this );37 void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ); 38 void ^?{}( $coroutine & this ); 39 39 40 static inline void ?{}( coroutine_desc& this) { this{ "Anonymous Coroutine", 0p, 0 }; }41 static inline void ?{}( coroutine_desc& this, size_t stackSize) { this{ "Anonymous Coroutine", 0p, stackSize }; }42 static inline void ?{}( coroutine_desc& this, void * storage, size_t storageSize ) { this{ "Anonymous Coroutine", storage, storageSize }; }43 static inline void ?{}( coroutine_desc& this, const char name[]) { this{ name, 0p, 0 }; }44 static inline void ?{}( coroutine_desc& this, const char name[], size_t stackSize ) { this{ name, 0p, stackSize }; }40 static inline void ?{}( $coroutine & this) { this{ "Anonymous Coroutine", 0p, 0 }; } 41 static inline void ?{}( $coroutine & this, size_t stackSize) { this{ "Anonymous Coroutine", 0p, stackSize }; } 42 static inline void ?{}( $coroutine & this, void * storage, size_t storageSize ) { this{ "Anonymous Coroutine", storage, storageSize }; } 43 static inline void ?{}( $coroutine & this, const char name[]) { this{ name, 0p, 0 }; } 44 static inline void ?{}( $coroutine & this, const char name[], size_t stackSize ) { this{ name, 0p, stackSize }; } 45 45 46 46 //----------------------------------------------------------------------------- 47 47 // Public coroutine API 48 static inline void suspend(void);49 50 forall(dtype T | is_coroutine(T))51 static inline T & resume(T & cor);52 53 48 forall(dtype T | is_coroutine(T)) 54 49 void prime(T & cor); 55 50 56 static inline struct coroutine_desc* active_coroutine() { return TL_GET( this_thread )->curr_cor; }51 static inline struct $coroutine * active_coroutine() { return TL_GET( this_thread )->curr_cor; } 57 52 58 53 //----------------------------------------------------------------------------- … … 61 56 // Start coroutine routines 62 57 extern "C" { 63 void CtxInvokeCoroutine(void (*main)(void *), void * this);58 void __cfactx_invoke_coroutine(void (*main)(void *), void * this); 64 59 65 60 forall(dtype T) 66 void CtxStart(void (*main)(T &), struct coroutine_desc* cor, T & this, void (*invoke)(void (*main)(void *), void *));61 void __cfactx_start(void (*main)(T &), struct $coroutine * cor, T & this, void (*invoke)(void (*main)(void *), void *)); 67 62 68 extern void _ CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc*) __attribute__ ((__noreturn__));63 extern void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__)); 69 64 70 extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");65 extern void __cfactx_switch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("__cfactx_switch"); 71 66 } 72 67 73 68 // Private wrappers for context switch and stack creation 74 69 // Wrapper for co 75 static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {70 static inline void $ctx_switch( $coroutine * src, $coroutine * dst ) __attribute__((nonnull (1, 2))) { 76 71 // set state of current coroutine to inactive 77 src->state = src->state == Halted ? Halted : Inactive;72 src->state = src->state == Halted ? Halted : Blocked; 78 73 79 74 // set new coroutine that task is executing … … 82 77 // context switch to specified coroutine 83 78 verify( dst->context.SP ); 84 CtxSwitch( &src->context, &dst->context );85 // when CtxSwitch returns we are back in the src coroutine79 __cfactx_switch( &src->context, &dst->context ); 80 // when __cfactx_switch returns we are back in the src coroutine 86 81 87 82 // set state of new coroutine to active … … 89 84 90 85 if( unlikely(src->cancellation != 0p) ) { 91 _ CtxCoroutine_Unwind(src->cancellation, src);86 __cfactx_coroutine_unwind(src->cancellation, src); 92 87 } 93 88 } … … 96 91 97 92 // Suspend implementation inlined for performance 98 static inline void suspend(void) { 99 // optimization : read TLS once and reuse it 100 // Safety note: this is preemption safe since if 101 // preemption occurs after this line, the pointer 102 // will also migrate which means this value will 103 // stay in syn with the TLS 104 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 93 extern "C" { 94 static inline void __cfactx_suspend(void) { 95 // optimization : read TLS once and reuse it 96 // Safety note: this is preemption safe since if 97 // preemption occurs after this line, the pointer 98 // will also migrate which means this value will 99 // stay in syn with the TLS 100 $coroutine * src = TL_GET( this_thread )->curr_cor; 105 101 106 assertf( src->last != 0,107 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"108 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",109 src->name, src );110 assertf( src->last->state != Halted,111 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"112 "Possible cause is terminated coroutine's main routine has already returned.",113 src->name, src, src->last->name, src->last );102 assertf( src->last != 0, 103 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n" 104 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 105 src->name, src ); 106 assertf( src->last->state != Halted, 107 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n" 108 "Possible cause is terminated coroutine's main routine has already returned.", 109 src->name, src, src->last->name, src->last ); 114 110 115 CoroutineCtxSwitch( src, src->last ); 111 $ctx_switch( src, src->last ); 112 } 116 113 } 117 114 … … 124 121 // will also migrate which means this value will 125 122 // stay in syn with the TLS 126 coroutine_desc* src = TL_GET( this_thread )->curr_cor;127 coroutine_desc* dst = get_coroutine(cor);123 $coroutine * src = TL_GET( this_thread )->curr_cor; 124 $coroutine * dst = get_coroutine(cor); 128 125 129 126 if( unlikely(dst->context.SP == 0p) ) { 130 127 TL_GET( this_thread )->curr_cor = dst; 131 128 __stack_prepare(&dst->stack, 65000); 132 CtxStart(main, dst, cor, CtxInvokeCoroutine);129 __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine); 133 130 TL_GET( this_thread )->curr_cor = src; 134 131 } … … 147 144 148 145 // always done for performance testing 149 CoroutineCtxSwitch( src, dst );146 $ctx_switch( src, dst ); 150 147 151 148 return cor; 152 149 } 153 150 154 static inline void resume( coroutine_desc * dst) {151 static inline void resume( $coroutine * dst ) __attribute__((nonnull (1))) { 155 152 // optimization : read TLS once and reuse it 156 153 // Safety note: this is preemption safe since if … … 158 155 // will also migrate which means this value will 159 156 // stay in syn with the TLS 160 coroutine_desc* src = TL_GET( this_thread )->curr_cor;157 $coroutine * src = TL_GET( this_thread )->curr_cor; 161 158 162 159 // not resuming self ? … … 172 169 173 170 // always done for performance testing 174 CoroutineCtxSwitch( src, dst );171 $ctx_switch( src, dst ); 175 172 } 176 173
Note:
See TracChangeset
for help on using the changeset viewer.