Changeset 596f987b for src


Ignore:
Timestamp:
Dec 15, 2016, 12:40:01 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
66f8528
Parents:
12d44bb
Message:

Some optimization and clean-up of coroutines

Location:
src/libcfa/concurrency
Files:
4 edited

Legend:

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

    r12d44bb r596f987b  
    1313// Called from the kernel when starting a coroutine or task so must switch back to user mode.
    1414
    15 extern void __suspend__F___1(void);
     15extern void __suspend_no_inline__F___1(void);
    1616
    1717void CtxInvokeCoroutine(
     
    2525
    2626      if(cor->state == Primed) {
    27             __suspend__F___1();
     27            __suspend_no_inline__F___1();
    2828      }
    2929
  • src/libcfa/concurrency/invoke.h

    r12d44bb r596f987b  
    1010#define _INVOKE_H_
    1111
    12      struct coStack_t {
     12      #define unlikely(x)    __builtin_expect(!!(x), 0)
     13
     14      struct coStack_t {
    1315            unsigned int size;          // size of stack
    1416            void *storage;                      // pointer to stack
     
    3840#define _INVOKE_PRIVATE_H_
    3941     
    40      struct machine_context_t {
     42      struct machine_context_t {
    4143            void *SP;
    4244            void *FP;
  • src/libcfa/concurrency/threads

    r12d44bb r596f987b  
    1818#define __THREADS_H__
    1919
     20#include "assert"       //
    2021#include "invoke.h"
    2122
    22 void ?{}(coStack_t* this);
    23 
    24 void ?{}(coroutine* this);
    25 
     23//-----------------------------------------------------------------------------
     24// Coroutine trait
     25// Anything that implements this trait can be resumed.
     26// Anything that is resumed is a coroutine.
    2627trait is_coroutine(dtype T) {
    2728      void co_main(T* this);
     
    2930};
    3031
    31 void suspend(void);
     32//-----------------------------------------------------------------------------
     33// Ctors and dtors
     34void ?{}(coStack_t* this);
     35void ?{}(coroutine* this);
     36void ^?{}(coStack_t* this);
     37void ^?{}(coroutine* this);
     38
     39//-----------------------------------------------------------------------------
     40// Public coroutine API
     41static inline void suspend();
    3242
    3343forall(dtype T | is_coroutine(T))
    34 void resume(T* cor);
     44static inline void resume(T* cor);
    3545
    3646forall(dtype T | is_coroutine(T))
    3747void prime(T* cor);
     48
     49//-----------------------------------------------------------------------------
     50// PRIVATE exposed because of inline
     51
     52// Start coroutine routines
     53extern "C" {
     54      forall(dtype T | is_coroutine(T))
     55      void CtxInvokeCoroutine(T* this);
     56
     57      forall(dtype T | is_coroutine(T))
     58      void CtxStart(T* this, void (*invoke)(T*));
     59}
     60
     61// Get current coroutine
     62extern coroutine* current_coroutine; //PRIVATE, never use directly
     63static inline coroutine* this_coroutine(void) {
     64        return current_coroutine;
     65}
     66
     67// Private wrappers for context switch and stack creation
     68extern void corCxtSw(coroutine* src, coroutine* dst);
     69extern void create_stack( coStack_t* this, unsigned int storageSize );
     70
     71// Suspend implementation inlined for performance
     72static inline void suspend() {
     73      coroutine* src = this_coroutine();                // optimization
     74
     75        assertf( src->last != 0,
     76                "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"
     77                "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
     78                src->name, src );
     79        assertf( src->last->notHalted,
     80                "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"
     81                "Possible cause is terminated coroutine's main routine has already returned.",
     82                src->name, src, src->last->name, src->last );
     83
     84        corCxtSw( src, src->last );
     85}
     86
     87// Resume implementation inlined for performance
     88forall(dtype T | is_coroutine(T))
     89static inline void resume(T* cor) {
     90        coroutine* src = this_coroutine();              // optimization
     91        coroutine* dst = get_coroutine(cor);
     92
     93      if( unlikely(!dst->stack.base) ) {
     94                create_stack(&dst->stack, dst->stack.size);
     95                CtxStart(cor, CtxInvokeCoroutine);
     96        }
     97
     98      // not resuming self ?
     99        if ( src != dst ) {
     100                assertf( dst->notHalted ,
     101                        "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
     102                        "Possible cause is terminated coroutine's main routine has already returned.",
     103                        src->name, src, dst->name, dst );
     104
     105            // set last resumer
     106                dst->last = src;
     107        } // if
     108
     109      // always done for performance testing
     110        corCxtSw( src, dst );
     111}
    38112
    39113#endif //__THREADS_H__
  • src/libcfa/concurrency/threads.c

    r12d44bb r596f987b  
    2424
    2525#include "threads"
    26 #include "assert"
    2726#include "libhdr.h"
    2827
     
    3029#include "invoke.h"
    3130
     31//-----------------------------------------------------------------------------
     32// Global state variables
     33
    3234// minimum feasible stack size in bytes
    3335#define MinStackSize 1000
    34 static size_t pageSize = 0;                             // architecture pagesize
     36static size_t pageSize = 0;                             // architecture pagesize HACK, should go in proper runtime singleton
    3537
     38//Extra private desctructor for the main
     39//FIXME the main should not actually allocate a stack
     40//Since the main is never resumed the extra stack does not cause
     41//any problem but it is wasted memory
    3642void ?{}(coStack_t* this, size_t size);
    3743void ?{}(coroutine* this, size_t size);
    3844
    39 static coroutine main_coroutine = { 1000 };
    40 static coroutine* current_coroutine = &main_coroutine;
     45//Main coroutine
     46//FIXME do not construct a stack for the main
     47coroutine main_coroutine = { 1000 };
    4148
    42 coroutine* this_coroutine(void) {
    43         return current_coroutine;
    44 }
     49//Current coroutine
     50//Will need to be in TLS when multi-threading is added
     51coroutine* current_coroutine = &main_coroutine;
    4552
    46 void corCxtSw(coroutine* src, coroutine* dst);
    47 void create_stack( coStack_t* this, unsigned int storageSize ); // used by all constructors
    48 
    49 extern "C" {
    50       forall(dtype T | is_coroutine(T))
    51       void CtxInvokeCoroutine(T* this);
    52 
    53       forall(dtype T | is_coroutine(T))
    54       void CtxStart(T* this, void (*invoke)(T*));
    55 }
    56 
     53//-----------------------------------------------------------------------------
     54// Coroutine ctors and dtors
    5755void ?{}(coStack_t* this) {
    5856        this->size              = 10240;        // size of stack
     
    7270}
    7371
    74 void ?{}(coroutine* this)
    75 {
     72void ?{}(coroutine* this) {
    7673        this->name = "Anonymous Coroutine";
    7774        this->errno_ = 0;
     
    8279}
    8380
    84 void ?{}(coroutine* this, size_t size)
    85 {
     81void ?{}(coroutine* this, size_t size) {
    8682        this{};
    8783        (&this->stack){size};
    8884}
    8985
    90 void suspend() {
    91       coroutine* src = this_coroutine();                // optimization
    92 
    93         assertf( src->last != 0,
    94                 "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"
    95                 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    96                 src->name, src );
    97         assertf( src->last->notHalted,
    98                 "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"
    99                 "Possible cause is terminated coroutine's main routine has already returned.",
    100                 src->name, src, src->last->name, src->last );
    101 
    102         corCxtSw( src, src->last );
     86void ^?{}(coStack_t* this) {
     87        if ( ! this->userStack ) {
     88                LIB_DEBUG_DO(
     89                        if ( mprotect( this->storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
     90                                abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", this, errno, strerror( errno ) );
     91                        }
     92                );
     93                free( this->storage );
     94        }
    10395}
    10496
    105 forall(dtype T | is_coroutine(T))
    106 void resume(T* cor) {
    107         coroutine* src = this_coroutine();              // optimization
    108         coroutine* dst = get_coroutine(cor);
     97void ^?{}(coroutine* this) {}
    10998
    110         if( dst->stack.base == NULL ) {
    111                 create_stack(&dst->stack, dst->stack.size);
    112                 CtxStart(cor, CtxInvokeCoroutine);
    113         }
    114 
    115         if ( src != dst ) {                             // not resuming self ?
    116                 assertf( dst->notHalted ,
    117                         "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
    118                         "Possible cause is terminated coroutine's main routine has already returned.",
    119                         src->name, src, dst->name, dst );
    120                 dst->last = src;                                        // set last resumer
    121         } // if
    122         corCxtSw( src, dst );                           // always done for performance testing
    123 }
    124 
     99// Part of the Public API
     100// Not inline since only ever called once per coroutine
    125101forall(dtype T | is_coroutine(T))
    126102void prime(T* cor) {
     
    130106        this->state = Primed;
    131107        resume(cor);
     108}
     109
     110// We need to call suspend from invoke.c, so we expose this wrapper that
     111// is not inline (We can't inline Cforall in C)
     112void suspend_no_inline(void) {
     113        suspend();
    132114}
    133115
     
    151133} //ctxSwitchDirect
    152134
    153 // used by all constructors
    154135void create_stack( coStack_t* this, unsigned int storageSize ) {
    155136        //TEMP HACK do this on proper kernel startup
Note: See TracChangeset for help on using the changeset viewer.