Changeset eef8dfb for libcfa/src/concurrency/invoke.c
- Timestamp:
- Jan 7, 2021, 2:55:57 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:
- 58fe85a
- Parents:
- bdfc032 (diff), 44e37ef (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/invoke.c
rbdfc032 reef8dfb 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 9 16:37:42 201813 // Update Count : 512 // Last Modified On : Sat Oct 24 14:35:28 2020 13 // Update Count : 32 14 14 // 15 15 … … 29 29 // Called from the kernel when starting a coroutine or task so must switch back to user mode. 30 30 31 extern void __leave_coroutine ( struct coroutine_desc * ); 32 extern struct coroutine_desc * __finish_coroutine(void); 33 extern void __leave_thread_monitor(); 31 extern struct $coroutine * __cfactx_cor_finish(void); 32 extern void __cfactx_cor_leave ( struct $coroutine * ); 33 extern void __cfactx_thrd_leave(); 34 34 35 extern void disable_interrupts() OPTIONAL_THREAD; 35 36 extern void enable_interrupts( __cfaabi_dbg_ctx_param ); 36 37 37 void CtxInvokeCoroutine(38 void __cfactx_invoke_coroutine( 38 39 void (*main)(void *), 39 40 void *this 40 41 ) { 41 42 // Finish setting up the coroutine by setting its state 42 struct coroutine_desc * cor = __finish_coroutine();43 struct $coroutine * cor = __cfactx_cor_finish(); 43 44 44 45 // Call the main of the coroutine … … 46 47 47 48 //Final suspend, should never return 48 __ leave_coroutine( cor );49 __cfactx_cor_leave( cor ); 49 50 __cabi_abort( "Resumed dead coroutine" ); 50 51 } 51 52 52 static _Unwind_Reason_Code _ CtxCoroutine_UnwindStop(53 static _Unwind_Reason_Code __cfactx_coroutine_unwindstop( 53 54 __attribute((__unused__)) int version, 54 55 _Unwind_Action actions, … … 61 62 // We finished unwinding the coroutine, 62 63 // leave it 63 __ leave_coroutine( param );64 __cfactx_cor_leave( param ); 64 65 __cabi_abort( "Resumed dead coroutine" ); 65 66 } … … 69 70 } 70 71 71 void _ CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc* cor) __attribute__ ((__noreturn__));72 void _ CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc* cor) {73 _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _ CtxCoroutine_UnwindStop, cor );72 void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine * cor) __attribute__ ((__noreturn__)); 73 void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine * cor) { 74 _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, __cfactx_coroutine_unwindstop, cor ); 74 75 printf("UNWIND ERROR %d after force unwind\n", ret); 75 76 abort(); 76 77 } 77 78 78 void CtxInvokeThread(79 void __cfactx_invoke_thread( 79 80 void (*main)(void *), 80 81 void *this … … 93 94 // The order of these 4 operations is very important 94 95 //Final suspend, should never return 95 __ leave_thread_monitor();96 __cfactx_thrd_leave(); 96 97 __cabi_abort( "Resumed dead thread" ); 97 98 } 98 99 99 void CtxStart(100 void __cfactx_start( 100 101 void (*main)(void *), 101 struct coroutine_desc* cor,102 struct $coroutine * cor, 102 103 void *this, 103 104 void (*invoke)(void *) … … 108 109 109 110 struct FakeStack { 110 void *fixedRegisters[3]; 111 void *rturn; 112 void *dummyReturn; 113 void *argument[3]; 114 void *padding; 111 void *fixedRegisters[3]; // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant) 112 void *rturn; // where to go on return from uSwitch 113 void *dummyReturn; // fake return compiler would have pushed on call to uInvoke 114 void *argument[3]; // for 16-byte ABI, 16-byte alignment starts here 115 void *padding; // padding to force 16-byte alignment, as "base" is 16-byte aligned 115 116 }; 116 117 … … 121 122 122 123 fs->dummyReturn = NULL; 123 fs->argument[0] = main; 124 fs->argument[1] = this; 124 fs->argument[0] = main; // argument to invoke 125 fs->argument[1] = this; // argument to invoke 125 126 fs->rturn = invoke; 126 127 … … 128 129 129 130 struct FakeStack { 130 void *fixedRegisters[5]; 131 void *rturn; 132 void *dummyReturn; 131 void *fixedRegisters[5]; // fixed registers rbx, r12, r13, r14, r15 132 void *rturn; // where to go on return from uSwitch 133 void *dummyReturn; // NULL return address to provide proper alignment 133 134 }; 134 135 135 136 cor->context.SP = (char *)stack->base - sizeof( struct FakeStack ); 136 cor->context.FP = NULL; // terminate stack with NULL fp137 cor->context.FP = NULL; // terminate stack with NULL fp 137 138 138 139 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 139 140 140 141 fs->dummyReturn = NULL; 141 fs->rturn = CtxInvokeStub;142 fs->fixedRegisters[0] = main; 143 fs->fixedRegisters[1] = this; 142 fs->rturn = __cfactx_invoke_stub; 143 fs->fixedRegisters[0] = main; // argument to invoke 144 fs->fixedRegisters[1] = this; // argument to invoke 144 145 fs->fixedRegisters[2] = invoke; 145 146 146 #elif defined( __ARM_ARCH ) 147 #error ARM needs to be upgrade to use to parameters like X86/X64 (A.K.A. : I broke this and do not know how to fix it) 147 #elif defined( __ARM_ARCH_32 ) 148 #error ARM needs to be upgrade to use two parameters like X86/X64 (A.K.A. : I broke this and do not know how to fix it) 149 // More details about the error: 150 // To avoid the thunk problem, I changed the invoke routine to pass the main explicitly 151 // instead of relying on an assertion. This effectively hoists any required thunk one level 152 // which was enough to get to global scope in most cases. 153 // This means that __cfactx_invoke_... now takes two parameters and the FakeStack needs 154 // to be adjusted as a consequence of that. 155 // I don't know how to do that for ARM, hence the #error 156 148 157 struct FakeStack { 149 float fpRegs[16]; // floating point registers150 void * intRegs[9];// integer/pointer registers151 void * arg[2];// placeholder for this pointer158 float fpRegs[16]; // floating point registers 159 void * intRegs[9]; // integer/pointer registers 160 void * arg[2]; // placeholder for this pointer 152 161 }; 153 162 … … 157 166 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 158 167 159 fs->intRegs[8] = CtxInvokeStub;168 fs->intRegs[8] = __cfactx_invoke_stub; 160 169 fs->arg[0] = this; 161 170 fs->arg[1] = invoke; 162 171 172 #elif defined( __ARM_ARCH ) 173 struct FakeStack { 174 void * intRegs[12]; // x19-x30 integer registers 175 double fpRegs[8]; // v8-v15 floating point 176 }; 177 178 cor->context.SP = (char *)stack->base - sizeof( struct FakeStack ); 179 cor->context.FP = NULL; 180 181 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 182 183 fs->intRegs[0] = main; // argument to invoke x19 => x0 184 fs->intRegs[1] = this; // argument to invoke x20 => x1 185 fs->intRegs[2] = invoke; 186 fs->intRegs[11] = __cfactx_invoke_stub; // link register x30 => ret moves to pc 163 187 #else 164 188 #error uknown hardware architecture
Note:
See TracChangeset
for help on using the changeset viewer.