- File:
-
- 1 edited
-
libcfa/src/concurrency/invoke.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/invoke.c
rd31bb83 r09f357ec 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Oct 24 14:35:28 202013 // Update Count : 3212 // Last Modified On : Fri Feb 9 16:37:42 2018 13 // Update Count : 5 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 struct $coroutine * __cfactx_cor_finish(void); 32 extern void __cfactx_cor_leave ( struct $coroutine * ); 33 extern void __cfactx_thrd_leave(); 34 31 extern void __leave_coroutine ( struct coroutine_desc * ); 32 extern struct coroutine_desc * __finish_coroutine(void); 33 extern void __leave_thread_monitor(); 35 34 extern void disable_interrupts() OPTIONAL_THREAD; 36 35 extern void enable_interrupts( __cfaabi_dbg_ctx_param ); 37 36 38 void __cfactx_invoke_coroutine(37 void CtxInvokeCoroutine( 39 38 void (*main)(void *), 40 39 void *this 41 40 ) { 42 41 // Finish setting up the coroutine by setting its state 43 struct $coroutine * cor = __cfactx_cor_finish();42 struct coroutine_desc * cor = __finish_coroutine(); 44 43 45 44 // Call the main of the coroutine … … 47 46 48 47 //Final suspend, should never return 49 __ cfactx_cor_leave( cor );48 __leave_coroutine( cor ); 50 49 __cabi_abort( "Resumed dead coroutine" ); 51 50 } 52 51 53 static _Unwind_Reason_Code _ _cfactx_coroutine_unwindstop(52 static _Unwind_Reason_Code _CtxCoroutine_UnwindStop( 54 53 __attribute((__unused__)) int version, 55 54 _Unwind_Action actions, … … 62 61 // We finished unwinding the coroutine, 63 62 // leave it 64 __ cfactx_cor_leave( param );63 __leave_coroutine( param ); 65 64 __cabi_abort( "Resumed dead coroutine" ); 66 65 } … … 70 69 } 71 70 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 );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 ); 75 74 printf("UNWIND ERROR %d after force unwind\n", ret); 76 75 abort(); 77 76 } 78 77 79 void __cfactx_invoke_thread(78 void CtxInvokeThread( 80 79 void (*main)(void *), 81 80 void *this … … 94 93 // The order of these 4 operations is very important 95 94 //Final suspend, should never return 96 __ cfactx_thrd_leave();95 __leave_thread_monitor(); 97 96 __cabi_abort( "Resumed dead thread" ); 98 97 } 99 98 100 void __cfactx_start(99 void CtxStart( 101 100 void (*main)(void *), 102 struct $coroutine* cor,101 struct coroutine_desc * cor, 103 102 void *this, 104 103 void (*invoke)(void *) … … 109 108 110 109 struct FakeStack { 111 void *fixedRegisters[3]; // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)112 void *rturn; // where to go on return from uSwitch113 void *dummyReturn; // fake return compiler would have pushed on call to uInvoke114 void *argument[3]; // for 16-byte ABI, 16-byte alignment starts here115 void *padding; // padding to force 16-byte alignment, as "base" is 16-byte aligned110 void *fixedRegisters[3]; // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant) 111 void *rturn; // where to go on return from uSwitch 112 void *dummyReturn; // fake return compiler would have pushed on call to uInvoke 113 void *argument[3]; // for 16-byte ABI, 16-byte alignment starts here 114 void *padding; // padding to force 16-byte alignment, as "base" is 16-byte aligned 116 115 }; 117 116 … … 122 121 123 122 fs->dummyReturn = NULL; 124 fs->argument[0] = main; // argument to invoke125 fs->argument[1] = this; // argument to invoke123 fs->argument[0] = main; // argument to invoke 124 fs->argument[1] = this; // argument to invoke 126 125 fs->rturn = invoke; 127 126 … … 129 128 130 129 struct FakeStack { 131 void *fixedRegisters[5]; // fixed registers rbx, r12, r13, r14, r15132 void *rturn; // where to go on return from uSwitch133 void *dummyReturn; // NULL return address to provide proper alignment130 void *fixedRegisters[5]; // fixed registers rbx, r12, r13, r14, r15 131 void *rturn; // where to go on return from uSwitch 132 void *dummyReturn; // NULL return address to provide proper alignment 134 133 }; 135 134 136 135 cor->context.SP = (char *)stack->base - sizeof( struct FakeStack ); 137 cor->context.FP = NULL; // terminate stack with NULL fp136 cor->context.FP = NULL; // terminate stack with NULL fp 138 137 139 138 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 140 139 141 140 fs->dummyReturn = NULL; 142 fs->rturn = __cfactx_invoke_stub;143 fs->fixedRegisters[0] = main; // argument to invoke144 fs->fixedRegisters[1] = this; // argument to invoke141 fs->rturn = CtxInvokeStub; 142 fs->fixedRegisters[0] = main; 143 fs->fixedRegisters[1] = this; 145 144 fs->fixedRegisters[2] = invoke; 146 145 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 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) 157 148 struct FakeStack { 158 float fpRegs[16]; // floating point registers159 void * intRegs[9];// integer/pointer registers160 void * arg[2];// placeholder for this pointer149 float fpRegs[16]; // floating point registers 150 void *intRegs[9]; // integer/pointer registers 151 void *arg[2]; // placeholder for this pointer 161 152 }; 162 153 … … 166 157 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 167 158 168 fs->intRegs[8] = __cfactx_invoke_stub;159 fs->intRegs[8] = CtxInvokeStub; 169 160 fs->arg[0] = this; 170 161 fs->arg[1] = invoke; 171 162 172 #elif defined( __ARM_ARCH )173 struct FakeStack {174 void * intRegs[12]; // x19-x30 integer registers175 double fpRegs[8]; // v8-v15 floating point176 };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 => x0184 fs->intRegs[1] = this; // argument to invoke x20 => x1185 fs->intRegs[2] = invoke;186 fs->intRegs[11] = __cfactx_invoke_stub; // link register x30 => ret moves to pc187 163 #else 188 164 #error uknown hardware architecture
Note:
See TracChangeset
for help on using the changeset viewer.