Changeset 80d9e49


Ignore:
Timestamp:
Dec 7, 2016, 2:47:53 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
550a338
Parents:
a68caae
Message:

Coroutines no longer require virtual pointers or any code beyond the get_coroutine routine

Location:
src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/invoke.c

    ra68caae r80d9e49  
    1313// Called from the kernel when starting a coroutine or task so must switch back to user mode.
    1414
    15 void invokeCoroutine(covptr_t* vthis)
    16 {
    17       LIB_DEBUG_PRINTF("Invoke : Received %p (v %p)\n", vthis, *vthis);
     15extern void __suspend__F___1(void);
    1816
    19       struct coroutine* cor = get_coroutine( vthis );
     17void invokeCoroutine(
     18      void (*main)(void *),
     19      struct coroutine *(*get_coroutine)(void *),
     20      void *this
     21) {
     22      LIB_DEBUG_PRINTF("Invoke : Received %p (main %p, get_c %p)\n", this, main, get_coroutine);
     23
     24      struct coroutine* cor = get_coroutine( this );
     25
     26      if(cor->state == Primed) {
     27            __suspend__F___1();
     28      }
    2029
    2130      cor->state = Active;
    2231
    23       (*vthis)->main( get_object(vthis) );
     32      main( this );
    2433}
    2534
    2635
    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);
     36void startCoroutine(
     37      void (*main)(void *),
     38      struct coroutine *(*get_coroutine)(void *),
     39      void *this,
     40      void (*invoke)(void *)
     41) {
     42      LIB_DEBUG_PRINTF("StartCoroutine : Passing in %p (main %p, get_c %p) to %p\n", this, main, get_coroutine, invoke);
    2943
    30       struct coroutine* this = get_coroutine( vthis );
    31       struct coStack_t* stack = &this->stack;
     44      struct coStack_t* stack = &get_coroutine( this )->stack;
    3245
    3346#if defined( __i386__ )
     
    3750            void *rturn;                                      // where to go on return from uSwitch
    3851            void *dummyReturn;                          // fake return compiler would have pushed on call to uInvoke
    39             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
     52            void *argument[3];                          // for 16-byte ABI, 16-byte alignment starts here
     53            void *padding;                              // padding to force 16-byte alignment, as "base" is 16-byte aligned
    4154        };
    4255
     
    4558
    4659        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    47         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument = vthis;     // argument to invoke
     60        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[0] = this;     // argument to invoke
    4861        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke;
    4962
     
    6174      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    6275      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = coInvokeStub;
    63       ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = vthis;
     76      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = this;
    6477      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke;
    6578#else
  • src/libcfa/concurrency/invoke.h

    ra68caae r80d9e49  
    1010#define _INVOKE_H_
    1111
    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))
    14 
    15       struct coVtable_t {
    16             void (*main)(void*);
    17             intptr_t offset_coroutine;
    18             intptr_t offset_object;
    19       };
    20 
    21       typedef struct coVtable_t* covptr_t;
    22 
    23       static inline struct coroutine* get_coroutine(covptr_t* vthis) {
    24             return (struct coroutine*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_coroutine) );
    25       }
    26 
    27       static inline void* get_object(covptr_t* vthis) {
    28             return (void*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_object) );
    29       }
    30 
    31       struct coStack_t {
     12     struct coStack_t {
    3213            unsigned int size;          // size of stack
    3314            void *storage;                      // pointer to stack
     
    3920      };
    4021
    41       enum coroutine_state { Start, Inactive, Active, Halt };
     22      enum coroutine_state { Start, Inactive, Active, Halt, Primed };
    4223
    4324      struct coroutine {
     
    5233      };
    5334
    54       void invokeCoroutine(covptr_t* this);
    55       void startCoroutine(covptr_t* this, void (*invoke)(covptr_t*));
    5635#endif //_INVOKE_H_
    5736#else //! defined(__CFA_INVOKE_PRIVATE__)
  • src/libcfa/concurrency/threads

    ra68caae r80d9e49  
    2323
    2424void ?{}(coroutine* this);
    25 void ?{}(coroutine* this, covptr_t* object);
    2625
    27 trait coroutine_t(dtype T) {
     26trait is_coroutine(dtype T) {
    2827      void co_main(T* this);
    29       covptr_t* vtable(T* this);
     28      coroutine* get_coroutine(T* this);
    3029};
    3130
    3231void suspend(void);
    3332
    34 forall(dtype T | coroutine_t(T))
     33forall(dtype T | is_coroutine(T))
    3534void resume(T* cor);
     35
     36forall(dtype T | is_coroutine(T))
     37void prime(T* cor);
    3638
    3739#endif //__THREADS_H__
  • src/libcfa/concurrency/threads.c

    ra68caae r80d9e49  
    3434static size_t pageSize = 0;                             // architecture pagesize
    3535
    36 static coroutine main_coroutine;
     36void ?{}(coStack_t* this, size_t size);
     37void ?{}(coroutine* this, size_t size);
     38
     39static coroutine main_coroutine = { 1000 };
    3740static coroutine* current_coroutine = &main_coroutine;
    3841
     
    4346void ctxSwitchDirect(coroutine* src, coroutine* dst);
    4447void create_stack( coStack_t* this, unsigned int storageSize ); // used by all constructors
     48
     49extern "C" {
     50      forall(dtype T | is_coroutine(T))
     51      void invokeCoroutine(T* this);
     52
     53      forall(dtype T | is_coroutine(T))
     54      void startCoroutine(T* this, void (*invoke)(T*));
     55}
    4556
    4657void ?{}(coStack_t* this) {
     
    5263        this->top               = NULL; // address of top of storage
    5364        this->userStack = false;       
     65}
     66
     67void ?{}(coStack_t* this, size_t size) {
     68        this{};
     69        this->size = size;
    5470
    5571        create_stack(this, this->size);
     
    6682}
    6783
    68 void ?{}(coroutine* this, covptr_t* object)
     84void ?{}(coroutine* this, size_t size)
    6985{
    7086        this{};
    71 
    72         startCoroutine(object, invokeCoroutine);
     87        (&this->stack){size};
    7388}
    7489
     
    88103}
    89104
    90 forall(dtype T | coroutine_t(T))
     105forall(dtype T | is_coroutine(T))
    91106void resume(T* cor) {
    92107        coroutine* src = this_coroutine();              // optimization
    93         coroutine* dst = get_coroutine(vtable(cor));
     108        coroutine* dst = get_coroutine(cor);
     109
     110        if( ((intptr_t)dst->stack.base) == 0 ) {
     111                create_stack(&dst->stack, dst->stack.size);
     112                startCoroutine(cor, invokeCoroutine);
     113        }
    94114
    95115        if ( src != dst ) {                             // not resuming self ?
     
    103123}
    104124
     125forall(dtype T | is_coroutine(T))
     126void prime(T* cor) {
     127        coroutine* this = get_coroutine(cor);
     128        assert(this->state == Start);
     129
     130        this->state = Primed;
     131        resume(cor);
     132}
     133
    105134void ctxSwitchDirect(coroutine* src, coroutine* dst) {
    106135        // THREAD_GETMEM( This )->disableInterrupts();
  • src/tests/coroutine.c

    ra68caae r80d9e49  
    44struct Fibonacci {
    55      int fn; // used for communication
    6       covptr_t v;
    76      coroutine c;
    8 };
    9 
    10 void co_main(Fibonacci* this);
    11 covptr_t* vtable(Fibonacci* this);
    12 
    13 //GENERATED in proposal for virtuals
    14 void co_main_fib(void* this) {
    15       co_main( (Fibonacci*) this );
    16 }
    17 
    18 //GENERATED in proposal for virtuals
    19 static coVtable_t FibonacciVtable = {
    20       co_main_fib,
    21       VPTR_OFFSET(Fibonacci, v, c),
    22       VPTR_OFFSET(Fibonacci, v, fn)     
    237};
    248
    259void ?{}(Fibonacci* this) {
    2610      this->fn = 0;
    27       this->v = &FibonacciVtable;  //GENERATED in proposal for virtuals
    28       (&this->c) { &this->v };
     11}
     12
     13coroutine* get_coroutine(Fibonacci* this) {
     14      return &this->c;
    2915}
    3016
     
    5743}
    5844
    59 covptr_t* vtable(Fibonacci* this) {
    60       return &this->v;
    61 }
    62 
    6345int main() {
    6446      Fibonacci f1, f2;
Note: See TracChangeset for help on using the changeset viewer.