Changes in / [2cd0434:fef8293]


Ignore:
Location:
src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/CtxSwitch-x86_64.S

    r2cd0434 rfef8293  
    8181.globl  coInvokeStub
    8282coInvokeStub:
    83         movq %rbx, %rdi
    84         jmp *%r12
     83        movq %rbx, %rdi
     84        movq %r12, %rsi
     85        jmp *%r13
    8586
    8687// Local Variables: //
  • src/libcfa/concurrency/invoke.c

    r2cd0434 rfef8293  
    77#include "invoke.h"
    88
    9 #define __CFA_INVOKE_PRIVATE__
    10 #include "invoke.h"
     9struct machine_context_t {
     10        void *SP;
     11        void *FP;
     12        void *PC;
     13};
     14
     15extern void coInvokeStub( void );
    1116
    1217// magically invoke the "main" of the most derived class
    1318// Called from the kernel when starting a coroutine or task so must switch back to user mode.
     19void __invokeCoroutine__F_P9scoVtablePv__1(struct coVtable *vtable, void* vthis)
     20{
     21      LIB_DEBUG_PRINTF("Invoke : Received %p (v %p)\n", vthis, vtable);
    1422
    15 void invokeCoroutine(covptr_t* vthis)
    16 {
    17       LIB_DEBUG_PRINTF("Invoke : Received %p (v %p)\n", vthis, *vthis);
    18 
    19       struct coroutine* cor = get_coroutine( vthis );
     23      struct coroutine* cor = vtable->this_coroutine(vthis);
    2024
    2125      cor->state = Active;
    2226
    23       (*vthis)->main( get_object(vthis) );
     27      vtable->main(vthis);
    2428}
    2529
     30void __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);
    2638
    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 );
     39      struct coVtable * vtable = get_vtable( vthis );
     40      struct coroutine* this = this_coroutine( vthis );
    3141      struct coStack_t* stack = &this->stack;
    3242
     
    3747            void *rturn;                                      // where to go on return from uSwitch
    3848            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
     49            void *argument[2];                          // for 16-byte ABI, 16-byte alignment starts here
     50            void *padding[2];                           // padding to force 16-byte alignment, as "base" is 16-byte aligned
    4151        };
    4252
     
    4555
    4656        ((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
     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
    4859        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke;
    4960
     
    6172      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    6273      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = coInvokeStub;
    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;
     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;
    6577#else
    6678      #error Only __i386__ and __x86_64__ is supported for threads in cfa
  • src/libcfa/concurrency/invoke.h

    r2cd0434 rfef8293  
    1 #include <stdbool.h>
    2 #include <stdint.h>
    31
    4 #ifdef __CFORALL__
    5 extern "C" {
    6 #endif
    7 
    8 #if ! defined(__CFA_INVOKE_PRIVATE__)
    92#ifndef _INVOKE_H_
    103#define _INVOKE_H_
    114
    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))
     5struct coVtable {
     6      void (*main)(void*);
     7      struct coroutine* (*this_coroutine)(void*);
     8};
    149
    15       struct coVtable_t {
    16             void (*main)(void*);
    17             intptr_t offset_coroutine;
    18             intptr_t offset_object;
    19       };
     10struct 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};
    2019
    21       typedef struct coVtable_t* covptr_t;
    2220
    23       static inline struct coroutine* get_coroutine(covptr_t* vthis) {
    24             return (struct coroutine*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_coroutine) );
    25       }
     21enum coroutine_state { Start, Inactive, Active, Halt };
    2622
    27       static inline void* get_object(covptr_t* vthis) {
    28             return (void*) ( ((intptr_t)vthis) + ((intptr_t)(*vthis)->offset_object) );
    29       }
     23struct 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
    3029
    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       };
     30      struct coroutine *starter;                // first coroutine to resume this one
     31      struct coroutine *last;                   // last coroutine to resume this one
     32};
    4033
    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*));
    5634#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

    r2cd0434 rfef8293  
    1818#define __THREADS_H__
    1919
    20 #include "invoke.h"
     20#include <stdbool.h>
     21
     22extern "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}
    2152
    2253void ?{}(coStack_t* this);
    2354
    2455void ?{}(coroutine* this);
    25 void ?{}(coroutine* this, covptr_t* object);
    2656
    2757trait coroutine_t(dtype T) {
     58      coroutine* this_coroutine(T* this);
    2859      void co_main(T* this);
    29       covptr_t* vtable(T* this);
     60      coVtable* vtable(T* this);
    3061};
     62
     63forall(dtype T | coroutine_t(T))
     64void start(T* cor);
    3165
    3266void suspend(void);
  • src/libcfa/concurrency/threads.c

    r2cd0434 rfef8293  
    2727#include "libhdr.h"
    2828
    29 #define __CFA_INVOKE_PRIVATE__
    30 #include "invoke.h"
     29extern "C" { extern void coInvokeStub( void ); }
    3130
    3231// minimum feasible stack size in bytes
    3332#define MinStackSize 1000
    34 static size_t pageSize = 0;                             // architecture pagesize
    3533
    3634static coroutine main_coroutine;
    3735static coroutine* current_coroutine = &main_coroutine;
    3836
    39 coroutine* this_coroutine(void) {
    40         return current_coroutine;
     37extern "C" {
     38        struct machine_context_t {
     39                void *SP;
     40                void *FP;
     41                void *PC;
     42        };
    4143}
    4244
    43 void ctxSwitchDirect(coroutine* src, coroutine* dst);
    44 void create_stack( coStack_t* this, unsigned int storageSize ); // used by all constructors
     45extern "C" { void CtxSwitch( void *from, void *to ) asm ("CtxSwitch"); }// assembler routine that performs the context switch
    4546
    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 }
     47static size_t pageSize = 0;                             // architecture pagesize
    10448
    10549void ctxSwitchDirect(coroutine* src, coroutine* dst) {
     
    12165        // THREAD_GETMEM( This )->enableInterrupts();
    12266} //ctxSwitchDirect
     67
     68void invokeCoroutine(coVtable* vtable, void* this);
     69
     70forall(dtype T | coroutine_t(T))
     71void startCoroutine(T* this, void (*invoke)(coVtable*, void*));
    12372
    12473// used by all constructors
     
    167116}
    168117
     118coroutine* this_coroutine() {
     119        return current_coroutine;
     120}
     121
     122void ?{}(coStack_t* this) {
     123        this->size              = 10240;        // size of stack
     124        this->storage   = NULL; // pointer to stack
     125        this->limit             = NULL; // stack grows towards stack limit
     126        this->base              = NULL; // base of stack
     127        this->context   = NULL; // address of cfa_context_t
     128        this->top               = NULL; // address of top of storage
     129        this->userStack = false;       
     130        create_stack(this, this->size);
     131}
     132
     133void ?{}(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
     143forall(dtype T | coroutine_t(T))
     144void start(T* this) {
     145        startCoroutine(this, invokeCoroutine);
     146}
     147
     148void suspend() {
     149      coroutine* src = this_coroutine();                // optimization
     150
     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
     163forall(dtype T | coroutine_t(T))
     164void resume(T* cor) {
     165        coroutine* src = this_coroutine();              // optimization
     166        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 resumer
     174        } // if
     175        ctxSwitchDirect( src, dst );                            // always done for performance testing
     176}
     177
    169178// Local Variables: //
    170179// mode: c //
  • src/tests/coroutine.c

    r2cd0434 rfef8293  
    33
    44struct Fibonacci {
     5      coroutine c;
     6      coVtable v;
    57      int fn; // used for communication
    6       covptr_t v;
    7       coroutine c;
    88};
    99
     10coroutine* this_coroutine(Fibonacci* this);
    1011void co_main(Fibonacci* this);
    11 covptr_t* vtable(Fibonacci* this);
     12coVtable* vtable(Fibonacci* this);
    1213
    13 //GENERATED in proposal for virtuals
    1414void co_main_fib(void* this) {
    1515      co_main( (Fibonacci*) this );
    1616}
    1717
    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)     
    23 };
     18coroutine* this_coroutine_fib(void* this) {
     19      return this_coroutine( (Fibonacci*) this);
     20}
    2421
    2522void ?{}(Fibonacci* this) {
    2623      this->fn = 0;
    27       this->v = &FibonacciVtable;  //GENERATED in proposal for virtuals
    28       (&this->c) { &this->v };
     24      this->v.main = co_main_fib;
     25      this->v.this_coroutine = this_coroutine_fib;
     26      start(this);
    2927}
    3028
     
    3230#ifdef MORE_DEBUG
    3331      sout | "Starting main of coroutine " | this | endl;
    34       sout | "Started from " | this->c.last | endl;
     32      sout | "Started from " | this_coroutine(this)->last | endl;
    3533#endif
    3634      int fn1, fn2;             // retained between resumes
     
    5755}
    5856
    59 covptr_t* vtable(Fibonacci* this) {
     57coroutine* this_coroutine(Fibonacci* this) {
     58      return &this->c;
     59}
     60
     61coVtable* vtable(Fibonacci* this) {
    6062      return &this->v;
    6163}
     
    6466      Fibonacci f1, f2;
    6567#ifdef MORE_DEBUG     
    66       Fibonacci *pf1 = &f1, *pf2 = &f2;
    67       coroutine *cf1 = &f1.c, *cf2 = &f2.c;
    68       covptr_t  *vf1 = vtable(pf1), *vf2 = vtable(pf2);
    69       coroutine *cv1 = get_coroutine(vf1), *cv2 = get_coroutine(vf2);
    70       Fibonacci *ov1 = (Fibonacci *)get_object(vf1), *ov2 = (Fibonacci *)get_object(vf2);
    71 
    72       sout | "User coroutines : " | pf1 | ' ' | pf2 | endl;
    73       sout | "Coroutine data  : " | cf1 | ' ' | cf2 | endl;
    74       sout | "Vptr address    : " | vf1 | ' ' | vf2 | endl;
    75       sout | "Vptr obj data   : " | ov1 | ' ' | ov2 | endl;
    76       sout | "Vptr cor data   : " | cv1 | ' ' | cv2 | endl;
     68      sout | "User coroutines : " | &f1 | ' ' | &f1 | endl;
    7769#endif
    7870      for ( int i = 1; i <= 10; i += 1 ) {
Note: See TracChangeset for help on using the changeset viewer.