| 1 |
|
|---|
| 2 | #include <stdbool.h>
|
|---|
| 3 | #include <stdlib.h>
|
|---|
| 4 | #include <stdio.h>
|
|---|
| 5 |
|
|---|
| 6 | #include "invoke.h"
|
|---|
| 7 |
|
|---|
| 8 | struct machine_context_t {
|
|---|
| 9 | void *SP;
|
|---|
| 10 | void *FP;
|
|---|
| 11 | void *PC;
|
|---|
| 12 | };
|
|---|
| 13 |
|
|---|
| 14 | extern void coInvokeStub( void );
|
|---|
| 15 |
|
|---|
| 16 | // magically invoke the "main" of the most derived class
|
|---|
| 17 | // Called from the kernel when starting a coroutine or task so must switch back to user mode.
|
|---|
| 18 | void __invokeCoroutine__F_P9scoVtablePv__1(struct coVtable *vtable, void* vthis)
|
|---|
| 19 | {
|
|---|
| 20 | printf("Invoke : Received %p (v %p)\n", vthis, vtable);
|
|---|
| 21 |
|
|---|
| 22 | struct coroutine* cor = vtable->this_coroutine(vthis);
|
|---|
| 23 |
|
|---|
| 24 | cor->state = Active;
|
|---|
| 25 |
|
|---|
| 26 | vtable->main(vthis);
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | void __startCoroutine__A0_1_0___this_coroutine__PFP10scoroutine_Pd0___co_main__PF_Pd0___vtable__PFP9scoVtable_Pd0__F_Pd0PF_P9scoVtablePv___1(
|
|---|
| 30 | struct coroutine *(*this_coroutine)(void * ),
|
|---|
| 31 | void (*co_main)(void *),
|
|---|
| 32 | struct coVtable *(*get_vtable)(void *),
|
|---|
| 33 | void *vthis,
|
|---|
| 34 | void (*invoke)(struct coVtable *, void *)
|
|---|
| 35 | ) {
|
|---|
| 36 |
|
|---|
| 37 | #if ! defined( __x86_64__ ) && ! defined( __i386__ )
|
|---|
| 38 | #error Only __x86_64__ and __i386__ is supported for threads in cfa
|
|---|
| 39 | #endif
|
|---|
| 40 |
|
|---|
| 41 | #if defined( __U_SWAPCONTEXT__ )
|
|---|
| 42 | #error __U_SWAPCONTEXT__ should not be defined for __x86_64__
|
|---|
| 43 | #endif
|
|---|
| 44 |
|
|---|
| 45 | struct coVtable * vtable = get_vtable( vthis );
|
|---|
| 46 | struct coroutine* this = this_coroutine( vthis );
|
|---|
| 47 | struct coStack_t* stack = &this->stack;
|
|---|
| 48 |
|
|---|
| 49 | struct FakeStack {
|
|---|
| 50 | void *fixedRegisters[5]; // fixed registers rbx, r12, r13, r14, r15
|
|---|
| 51 | void *rturn; // where to go on return from uSwitch
|
|---|
| 52 | void *dummyReturn; // NULL return address to provide proper alignment
|
|---|
| 53 | }; // FakeStack
|
|---|
| 54 |
|
|---|
| 55 | ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
|
|---|
| 56 | ((struct machine_context_t *)stack->context)->FP = NULL; // terminate stack with NULL fp
|
|---|
| 57 |
|
|---|
| 58 | fprintf(stderr, "StartCoroutine : Passing in %p (v %p) to %p\n", vthis, vtable, invoke);
|
|---|
| 59 |
|
|---|
| 60 | ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
|
|---|
| 61 | ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = coInvokeStub;
|
|---|
| 62 | ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = vtable;
|
|---|
| 63 | ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = vthis;
|
|---|
| 64 | ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[2] = invoke;
|
|---|
| 65 | }
|
|---|