Changeset 5c81105 for src/libcfa/concurrency
- Timestamp:
- Dec 6, 2016, 6:28:47 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 2cd0434
- Parents:
- fa66f4e
- Location:
- src/libcfa/concurrency
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/CtxSwitch-x86_64.S
rfa66f4e r5c81105 81 81 .globl coInvokeStub 82 82 coInvokeStub: 83 movq %rbx, %rdi 84 movq %r12, %rsi 85 jmp *%r13 83 movq %rbx, %rdi 84 jmp *%r12 86 85 87 86 // Local Variables: // -
src/libcfa/concurrency/invoke.c
rfa66f4e r5c81105 7 7 #include "invoke.h" 8 8 9 struct machine_context_t { 10 void *SP; 11 void *FP; 12 void *PC; 13 }; 14 15 extern void coInvokeStub( void ); 9 #define __CFA_INVOKE_PRIVATE__ 10 #include "invoke.h" 16 11 17 12 // magically invoke the "main" of the most derived class 18 13 // Called from the kernel when starting a coroutine or task so must switch back to user mode. 19 void __invokeCoroutine__F_P9scoVtablePv__1(struct coVtable *vtable, void* vthis) 14 15 void invokeCoroutine(covptr_t* vthis) 20 16 { 21 LIB_DEBUG_PRINTF("Invoke : Received %p (v %p)\n", vthis, vtable);17 LIB_DEBUG_PRINTF("Invoke : Received %p (v %p)\n", vthis, *vthis); 22 18 23 struct coroutine* cor = vtable->this_coroutine(vthis);19 struct coroutine* cor = get_coroutine( vthis ); 24 20 25 21 cor->state = Active; 26 22 27 vtable->main(vthis);23 (*vthis)->main( get_object(vthis) ); 28 24 } 29 25 30 void __startCoroutine__A0_1_0___this_coroutine__PFP10scoroutine_Pd0___co_main__PF_Pd0___vtable__PFP9scoVtable_Pd0__F_Pd0PF_P9scoVtablePv___1(31 struct coroutine *(*this_coroutine)(void * ),32 void (*co_main)(void *),33 struct coVtable *(*get_vtable)(void *),34 void *vthis,35 void (*invoke)(struct coVtable *, void *)36 ) {37 LIB_DEBUG_PRINTF("StartCoroutine : Passing in %p (v %p) to %p\n", vthis, vtable, invoke);38 26 39 struct coVtable * vtable = get_vtable( vthis ); 40 struct coroutine* this = this_coroutine( vthis ); 27 void startCoroutine(covptr_t* vthis, void (*invoke)(covptr_t*)) { 28 LIB_DEBUG_PRINTF("StartCoroutine : Passing in %p (v %p) to %p\n", vthis, *vthis, invoke); 29 30 struct coroutine* this = get_coroutine( vthis ); 41 31 struct coStack_t* stack = &this->stack; 42 32 … … 47 37 void *rturn; // where to go on return from uSwitch 48 38 void *dummyReturn; // fake return compiler would have pushed on call to uInvoke 49 void *argument [2]; // for 16-byte ABI, 16-byte alignment starts here50 void *padding[ 2]; // padding to force 16-byte alignment, as "base" is 16-byte aligned39 void *argument; // for 16-byte ABI, 16-byte alignment starts here 40 void *padding[3]; // padding to force 16-byte alignment, as "base" is 16-byte aligned 51 41 }; 52 42 … … 55 45 56 46 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL; 57 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[0] = vtable; // argument to invoke 58 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[1] = vthis; // argument to invoke 47 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument = vthis; // argument to invoke 59 48 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke; 60 49 … … 72 61 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL; 73 62 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = coInvokeStub; 74 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = vtable; 75 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = vthis; 76 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[2] = invoke; 63 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = vthis; 64 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke; 77 65 #else 78 66 #error Only __i386__ and __x86_64__ is supported for threads in cfa -
src/libcfa/concurrency/invoke.h
rfa66f4e r5c81105 1 #include <stdbool.h> 2 #include <stdint.h> 1 3 4 #ifdef __CFORALL__ 5 extern "C" { 6 #endif 7 8 #if ! defined(__CFA_INVOKE_PRIVATE__) 2 9 #ifndef _INVOKE_H_ 3 10 #define _INVOKE_H_ 4 11 5 struct coVtable { 6 void (*main)(void*); 7 struct coroutine* (*this_coroutine)(void*); 8 }; 12 #define OFFSET_OF(type, field) ((intptr_t)( &((type*)0)->field)) 13 #define VPTR_OFFSET(type, vptr, field) (OFFSET_OF(type, field) - OFFSET_OF(type, vptr)) 9 14 10 struct coStack_t { 11 unsigned int size; // size of stack 12 void *storage; // pointer to stack 13 void *limit; // stack grows towards stack limit 14 void *base; // base of stack 15 void *context; // address of cfa_context_t 16 void *top; // address of top of storage 17 bool userStack; 18 }; 15 struct coVtable_t { 16 void (*main)(void*); 17 intptr_t offset_coroutine; 18 intptr_t offset_object; 19 }; 19 20 21 typedef struct coVtable_t* covptr_t; 20 22 21 enum coroutine_state { Start, Inactive, Active, Halt }; 23 static inline struct coroutine* get_coroutine(covptr_t* vthis) { 24 return (struct coroutine*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_coroutine) ); 25 } 22 26 23 struct coroutine { 24 struct coStack_t stack; 25 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 26 int errno_; // copy of global UNIX variable errno 27 enum coroutine_state state; // current execution status for coroutine 28 bool notHalted; // indicate if execuation state is not halted 27 static inline void* get_object(covptr_t* vthis) { 28 return (void*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_object) ); 29 } 29 30 30 struct coroutine *starter; // first coroutine to resume this one 31 struct coroutine *last; // last coroutine to resume this one 32 }; 31 struct coStack_t { 32 unsigned int size; // size of stack 33 void *storage; // pointer to stack 34 void *limit; // stack grows towards stack limit 35 void *base; // base of stack 36 void *context; // address of cfa_context_t 37 void *top; // address of top of storage 38 bool userStack; 39 }; 33 40 41 enum coroutine_state { Start, Inactive, Active, Halt }; 42 43 struct coroutine { 44 struct coStack_t stack; 45 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 46 int errno_; // copy of global UNIX variable errno 47 enum coroutine_state state; // current execution status for coroutine 48 bool notHalted; // indicate if execuation state is not halted 49 50 struct coroutine *starter; // first coroutine to resume this one 51 struct coroutine *last; // last coroutine to resume this one 52 }; 53 54 void invokeCoroutine(covptr_t* this); 55 void startCoroutine(covptr_t* this, void (*invoke)(covptr_t*)); 34 56 #endif //_INVOKE_H_ 57 #else //! defined(__CFA_INVOKE_PRIVATE__) 58 #ifndef _INVOKE_PRIVATE_H_ 59 #define _INVOKE_PRIVATE_H_ 60 61 struct machine_context_t { 62 void *SP; 63 void *FP; 64 void *PC; 65 }; 66 67 // assembler routines that performs the context switch 68 extern void coInvokeStub( void ); 69 void CtxSwitch( void *from, void *to ) asm ("CtxSwitch"); 70 71 #endif //_INVOKE_PRIVATE_H_ 72 #endif //! defined(__CFA_INVOKE_PRIVATE__) 73 #ifdef __CFORALL__ 74 } 75 #endif -
src/libcfa/concurrency/threads
rfa66f4e r5c81105 18 18 #define __THREADS_H__ 19 19 20 #include <stdbool.h> 21 22 extern "C" { 23 struct coVtable { 24 void (*main)(void*); 25 struct coroutine* (*this_coroutine)(void*); 26 }; 27 28 struct coStack_t { 29 unsigned int size; // size of stack 30 void *storage; // pointer to stack 31 void *limit; // stack grows towards stack limit 32 void *base; // base of stack 33 void *context; // address of cfa_context_t 34 void *top; // address of top of storage 35 bool userStack; 36 }; 37 38 39 enum coroutine_state { Start, Inactive, Active, Halt }; 40 41 struct coroutine { 42 coStack_t stack; 43 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 44 int errno_; // copy of global UNIX variable errno 45 coroutine_state state; // current execution status for coroutine 46 bool notHalted; // indicate if execuation state is not halted 47 48 coroutine *starter; // first coroutine to resume this one 49 coroutine *last; // last coroutine to resume this one 50 }; 51 } 20 #include "invoke.h" 52 21 53 22 void ?{}(coStack_t* this); 54 23 55 24 void ?{}(coroutine* this); 25 void ?{}(coroutine* this, covptr_t* object); 56 26 57 27 trait coroutine_t(dtype T) { 58 coroutine* this_coroutine(T* this);59 28 void co_main(T* this); 60 co Vtable* vtable(T* this);29 covptr_t* vtable(T* this); 61 30 }; 62 63 forall(dtype T | coroutine_t(T))64 void start(T* cor);65 31 66 32 void suspend(void); -
src/libcfa/concurrency/threads.c
rfa66f4e r5c81105 27 27 #include "libhdr.h" 28 28 29 extern "C" { extern void coInvokeStub( void ); } 29 #define __CFA_INVOKE_PRIVATE__ 30 #include "invoke.h" 30 31 31 32 // minimum feasible stack size in bytes 32 33 #define MinStackSize 1000 34 static size_t pageSize = 0; // architecture pagesize 33 35 34 36 static coroutine main_coroutine; 35 37 static coroutine* current_coroutine = &main_coroutine; 36 38 37 extern "C" { 38 struct machine_context_t { 39 void *SP; 40 void *FP; 41 void *PC; 42 }; 39 coroutine* this_coroutine(void) { 40 return current_coroutine; 43 41 } 44 42 45 extern "C" { void CtxSwitch( void *from, void *to ) asm ("CtxSwitch"); }// assembler routine that performs the context switch 43 void ctxSwitchDirect(coroutine* src, coroutine* dst); 44 void create_stack( coStack_t* this, unsigned int storageSize ); // used by all constructors 46 45 47 static size_t pageSize = 0; // architecture pagesize 46 void ?{}(coStack_t* this) { 47 this->size = 10240; // size of stack 48 this->storage = NULL; // pointer to stack 49 this->limit = NULL; // stack grows towards stack limit 50 this->base = NULL; // base of stack 51 this->context = NULL; // address of cfa_context_t 52 this->top = NULL; // address of top of storage 53 this->userStack = false; 54 55 create_stack(this, this->size); 56 } 57 58 void ?{}(coroutine* this) 59 { 60 this->name = "Anonymous Coroutine"; 61 this->errno_ = 0; 62 this->state = Start; 63 this->notHalted = true; 64 this->starter = NULL; 65 this->last = NULL; 66 } 67 68 void ?{}(coroutine* this, covptr_t* object) 69 { 70 this{}; 71 72 startCoroutine(object, invokeCoroutine); 73 } 74 75 void suspend() { 76 coroutine* src = this_coroutine(); // optimization 77 78 assertf( src->last != 0, 79 "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n" 80 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 81 src->name, src ); 82 assertf( src->last->notHalted, 83 "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n" 84 "Possible cause is terminated coroutine's main routine has already returned.", 85 src->name, src, src->last->name, src->last ); 86 87 ctxSwitchDirect( src, src->last ); 88 } 89 90 forall(dtype T | coroutine_t(T)) 91 void resume(T* cor) { 92 coroutine* src = this_coroutine(); // optimization 93 coroutine* dst = get_coroutine(vtable(cor)); 94 95 if ( src != dst ) { // not resuming self ? 96 assertf( dst->notHalted , 97 "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n" 98 "Possible cause is terminated coroutine's main routine has already returned.", 99 src->name, src, dst->name, dst ); 100 dst->last = src; // set last resumer 101 } // if 102 ctxSwitchDirect( src, dst ); // always done for performance testing 103 } 48 104 49 105 void ctxSwitchDirect(coroutine* src, coroutine* dst) { … … 65 121 // THREAD_GETMEM( This )->enableInterrupts(); 66 122 } //ctxSwitchDirect 67 68 void invokeCoroutine(coVtable* vtable, void* this);69 70 forall(dtype T | coroutine_t(T))71 void startCoroutine(T* this, void (*invoke)(coVtable*, void*));72 123 73 124 // used by all constructors … … 116 167 } 117 168 118 coroutine* this_coroutine() {119 return current_coroutine;120 }121 122 void ?{}(coStack_t* this) {123 this->size = 10240; // size of stack124 this->storage = NULL; // pointer to stack125 this->limit = NULL; // stack grows towards stack limit126 this->base = NULL; // base of stack127 this->context = NULL; // address of cfa_context_t128 this->top = NULL; // address of top of storage129 this->userStack = false;130 create_stack(this, this->size);131 }132 133 void ?{}(coroutine* this)134 {135 this->name = "Anonymous Coroutine";136 this->errno_ = 0;137 this->state = Start;138 this->notHalted = true;139 this->starter = NULL;140 this->last = NULL;141 }142 143 forall(dtype T | coroutine_t(T))144 void start(T* this) {145 startCoroutine(this, invokeCoroutine);146 }147 148 void suspend() {149 coroutine* src = this_coroutine(); // optimization150 151 assertf( src->last != 0,152 "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"153 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",154 src->name, src );155 assertf( src->last->notHalted,156 "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"157 "Possible cause is terminated coroutine's main routine has already returned.",158 src->name, src, src->last->name, src->last );159 160 ctxSwitchDirect( src, src->last );161 }162 163 forall(dtype T | coroutine_t(T))164 void resume(T* cor) {165 coroutine* src = this_coroutine(); // optimization166 coroutine* dst = this_coroutine(cor);167 168 if ( src != dst ) { // not resuming self ?169 assertf( dst->notHalted ,170 "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"171 "Possible cause is terminated coroutine's main routine has already returned.",172 src->name, src, dst->name, dst );173 dst->last = src; // set last resumer174 } // if175 ctxSwitchDirect( src, dst ); // always done for performance testing176 }177 178 169 // Local Variables: // 179 170 // mode: c //
Note: See TracChangeset
for help on using the changeset viewer.