- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.hfa
rd4e68a6 rae7be7a 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 17:49:39 201913 // Update Count : 912 // Last Modified On : Tue Feb 4 12:29:26 2020 13 // Update Count : 11 14 14 // 15 15 … … 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", NULL, 0 }; }41 static inline void ?{}( coroutine_desc & this, size_t stackSize) { this{ "Anonymous Coroutine", NULL, 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, NULL, 0 }; }44 static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, NULL, 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 forall(dtype T | is_coroutine(T)) 64 void CtxInvokeCoroutine(T * this); 58 void __cfactx_invoke_coroutine(void (*main)(void *), void * this); 65 59 66 forall(dtype T | is_coroutine(T))67 void CtxStart(T * this, void ( *invoke)(T*));60 forall(dtype T) 61 void __cfactx_start(void (*main)(T &), struct $coroutine * cor, T & this, void (*invoke)(void (*main)(void *), void *)); 68 62 69 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__)); 70 64 71 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"); 72 66 } 73 67 74 68 // Private wrappers for context switch and stack creation 75 69 // Wrapper for co 76 static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {70 static inline void $ctx_switch( $coroutine * src, $coroutine * dst ) __attribute__((nonnull (1, 2))) { 77 71 // set state of current coroutine to inactive 78 src->state = src->state == Halted ? Halted : Inactive;72 src->state = src->state == Halted ? Halted : Blocked; 79 73 80 74 // set new coroutine that task is executing … … 83 77 // context switch to specified coroutine 84 78 verify( dst->context.SP ); 85 CtxSwitch( &src->context, &dst->context );86 // 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 87 81 88 82 // set state of new coroutine to active 89 83 src->state = Active; 90 84 91 if( unlikely(src->cancellation != NULL) ) {92 _ CtxCoroutine_Unwind(src->cancellation, src);85 if( unlikely(src->cancellation != 0p) ) { 86 __cfactx_coroutine_unwind(src->cancellation, src); 93 87 } 94 88 } … … 97 91 98 92 // Suspend implementation inlined for performance 99 static inline void suspend(void) { 100 // optimization : read TLS once and reuse it 101 // Safety note: this is preemption safe since if 102 // preemption occurs after this line, the pointer 103 // will also migrate which means this value will 104 // stay in syn with the TLS 105 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; 106 101 107 assertf( src->last != 0,108 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"109 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",110 src->name, src );111 assertf( src->last->state != Halted,112 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"113 "Possible cause is terminated coroutine's main routine has already returned.",114 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 ); 115 110 116 CoroutineCtxSwitch( src, src->last ); 111 $ctx_switch( src, src->last ); 112 } 117 113 } 118 114 … … 125 121 // will also migrate which means this value will 126 122 // stay in syn with the TLS 127 coroutine_desc* src = TL_GET( this_thread )->curr_cor;128 coroutine_desc* dst = get_coroutine(cor);123 $coroutine * src = TL_GET( this_thread )->curr_cor; 124 $coroutine * dst = get_coroutine(cor); 129 125 130 if( unlikely(dst->context.SP == NULL) ) { 126 if( unlikely(dst->context.SP == 0p) ) { 127 TL_GET( this_thread )->curr_cor = dst; 131 128 __stack_prepare(&dst->stack, 65000); 132 CtxStart(&cor, CtxInvokeCoroutine); 129 __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine); 130 TL_GET( this_thread )->curr_cor = src; 133 131 } 134 132 … … 146 144 147 145 // always done for performance testing 148 CoroutineCtxSwitch( src, dst );146 $ctx_switch( src, dst ); 149 147 150 148 return cor; 151 149 } 152 150 153 static inline void resume( coroutine_desc * dst) {151 static inline void resume( $coroutine * dst ) __attribute__((nonnull (1))) { 154 152 // optimization : read TLS once and reuse it 155 153 // Safety note: this is preemption safe since if … … 157 155 // will also migrate which means this value will 158 156 // stay in syn with the TLS 159 coroutine_desc* src = TL_GET( this_thread )->curr_cor;157 $coroutine * src = TL_GET( this_thread )->curr_cor; 160 158 161 159 // not resuming self ? … … 171 169 172 170 // always done for performance testing 173 CoroutineCtxSwitch( src, dst );171 $ctx_switch( src, dst ); 174 172 } 175 173
Note:
See TracChangeset
for help on using the changeset viewer.