Changeset 58fe85a for libcfa/src/concurrency/coroutine.hfa
- Timestamp:
- Jan 7, 2021, 3:27:00 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (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
r3c64c668 r58fe85a 18 18 #include <assert.h> 19 19 #include "invoke.h" 20 #include "../exception.hfa" 21 22 //----------------------------------------------------------------------------- 23 // Exception thrown from resume when a coroutine stack is cancelled. 24 FORALL_DATA_EXCEPTION(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) ( 25 coroutine_t * the_coroutine; 26 exception_t * the_exception; 27 ); 28 29 forall(dtype T) 30 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src); 31 32 forall(dtype T) 33 const char * msg(CoroutineCancelled(T) *); 20 34 21 35 //----------------------------------------------------------------------------- … … 23 37 // Anything that implements this trait can be resumed. 24 38 // Anything that is resumed is a coroutine. 25 trait is_coroutine(dtype T ) {26 27 39 trait is_coroutine(dtype T | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) { 40 void main(T & this); 41 $coroutine * get_coroutine(T & this); 28 42 }; 29 43 … … 46 60 //----------------------------------------------------------------------------- 47 61 // 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 62 forall(dtype T | is_coroutine(T)) 54 63 void prime(T & cor); 55 64 56 static inline struct $coroutine * active_coroutine() { return TL_GET( this_thread)->curr_cor; }65 static inline struct $coroutine * active_coroutine() { return active_thread()->curr_cor; } 57 66 58 67 //----------------------------------------------------------------------------- … … 75 84 static inline void $ctx_switch( $coroutine * src, $coroutine * dst ) __attribute__((nonnull (1, 2))) { 76 85 // set state of current coroutine to inactive 77 src->state = src->state == Halted ? Halted : Inactive;86 src->state = src->state == Halted ? Halted : Blocked; 78 87 79 88 // set new coroutine that task is executing 80 TL_GET( this_thread)->curr_cor = dst;89 active_thread()->curr_cor = dst; 81 90 82 91 // context switch to specified coroutine … … 93 102 } 94 103 95 extern void __stack_prepare ( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 104 extern void __stack_prepare( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 105 extern void __stack_clean ( __stack_info_t * this ); 106 96 107 97 108 // 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 * src = TL_GET( this_thread )->curr_cor; 109 extern "C" { 110 static inline void __cfactx_suspend(void) { 111 // optimization : read TLS once and reuse it 112 // Safety note: this is preemption safe since if 113 // preemption occurs after this line, the pointer 114 // will also migrate which means this value will 115 // stay in syn with the TLS 116 $coroutine * src = active_coroutine(); 105 117 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 );118 assertf( src->last != 0, 119 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n" 120 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 121 src->name, src ); 122 assertf( src->last->state != Halted, 123 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n" 124 "Possible cause is terminated coroutine's main routine has already returned.", 125 src->name, src, src->last->name, src->last ); 114 126 115 $ctx_switch( src, src->last ); 127 $ctx_switch( src, src->last ); 128 } 116 129 } 130 131 forall(dtype T | is_coroutine(T)) 132 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ); 117 133 118 134 // Resume implementation inlined for performance … … 124 140 // will also migrate which means this value will 125 141 // stay in syn with the TLS 126 $coroutine * src = TL_GET( this_thread )->curr_cor;142 $coroutine * src = active_coroutine(); 127 143 $coroutine * dst = get_coroutine(cor); 128 144 129 145 if( unlikely(dst->context.SP == 0p) ) { 130 TL_GET( this_thread )->curr_cor = dst;131 146 __stack_prepare(&dst->stack, 65000); 132 147 __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine); 133 TL_GET( this_thread )->curr_cor = src;134 148 } 135 149 … … 148 162 // always done for performance testing 149 163 $ctx_switch( src, dst ); 164 if ( unlikely(dst->cancellation) ) { 165 __cfaehm_cancelled_coroutine( cor, dst ); 166 } 150 167 151 168 return cor; … … 158 175 // will also migrate which means this value will 159 176 // stay in syn with the TLS 160 $coroutine * src = TL_GET( this_thread )->curr_cor;177 $coroutine * src = active_coroutine(); 161 178 162 179 // not resuming self ?
Note:
See TracChangeset
for help on using the changeset viewer.