Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/coroutine.cfa

    rdd92fe9 r09f357ec  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Dec 15 12:06:04 2020
    13 // Update Count     : 23
     12// Last Modified On : Thu Dec  5 14:37:29 2019
     13// Update Count     : 15
    1414//
    1515
     
    1818#include "coroutine.hfa"
    1919
     20extern "C" {
    2021#include <stddef.h>
    2122#include <malloc.h>
     
    2324#include <string.h>
    2425#include <unistd.h>
    25 #include <sys/mman.h>                                                                   // mprotect
     26// use this define to make unwind.h play nice, definetely a hack
     27#define HIDE_EXPORTS
    2628#include <unwind.h>
     29#undef HIDE_EXPORTS
     30#include <sys/mman.h>
     31}
    2732
    2833#include "kernel_private.hfa"
    29 #include "exception.hfa"
    30 #include "math.hfa"
    31 
    32 #define CFA_COROUTINE_USE_MMAP 0
    3334
    3435#define __CFA_INVOKE_PRIVATE__
     
    3637
    3738extern "C" {
    38         void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__));
     39        void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
    3940        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
    4041        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
     
    4647
    4748//-----------------------------------------------------------------------------
    48 FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
    49 
    50 forall(dtype T)
    51 void mark_exception(CoroutineCancelled(T) *) {}
    52 
    53 forall(dtype T)
    54 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    55         dst->virtual_table = src->virtual_table;
    56         dst->the_coroutine = src->the_coroutine;
    57         dst->the_exception = src->the_exception;
    58 }
    59 
    60 forall(dtype T)
    61 const char * msg(CoroutineCancelled(T) *) {
    62         return "CoroutineCancelled(...)";
    63 }
    64 
    65 // This code should not be inlined. It is the error path on resume.
    66 forall(dtype T | is_coroutine(T))
    67 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) {
    68         verify( desc->cancellation );
    69         desc->state = Cancelled;
    70         exception_t * except = __cfaehm_cancellation_exception( desc->cancellation );
    71 
    72         // TODO: Remove explitate vtable set once trac#186 is fixed.
    73         CoroutineCancelled(T) except;
    74         except.virtual_table = &get_exception_vtable(&except);
    75         except.the_coroutine = &cor;
    76         except.the_exception = except;
    77         throwResume except;
    78 
    79         except->virtual_table->free( except );
    80         free( desc->cancellation );
    81         desc->cancellation = 0p;
    82 }
    83 
    84 //-----------------------------------------------------------------------------
    8549// Global state variables
    8650
    8751// minimum feasible stack size in bytes
    88 static const size_t MinStackSize = 1000;
     52#define MinStackSize 1000
    8953extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
    90 extern int __map_prot;
    9154
    9255void __stack_prepare( __stack_info_t * this, size_t create_size );
    93 void __stack_clean  ( __stack_info_t * this );
    9456
    9557//-----------------------------------------------------------------------------
     
    11274        bool userStack = ((intptr_t)this.storage & 0x1) != 0;
    11375        if ( ! userStack && this.storage ) {
    114                 __stack_clean( &this );
    115         }
    116 }
    117 
    118 void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ) with( this ) {
     76                __attribute__((may_alias)) intptr_t * istorage = (intptr_t *)&this.storage;
     77                *istorage &= (intptr_t)-1;
     78
     79                void * storage = this.storage->limit;
     80                __cfaabi_dbg_debug_do(
     81                        storage = (char*)(storage) - __page_size;
     82                        if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) {
     83                                abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
     84                        }
     85                );
     86                __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
     87                free( storage );
     88        }
     89}
     90
     91void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
    11992        (this.context){0p, 0p};
    12093        (this.stack){storage, storageSize};
     
    12699}
    127100
    128 void ^?{}($coroutine& this) {
     101void ^?{}(coroutine_desc& this) {
    129102        if(this.state != Halted && this.state != Start && this.state != Primed) {
    130                 $coroutine * src = active_coroutine();
    131                 $coroutine * dst = &this;
     103                coroutine_desc * src = TL_GET( this_thread )->curr_cor;
     104                coroutine_desc * dst = &this;
    132105
    133106                struct _Unwind_Exception storage;
     
    142115                }
    143116
    144                 $ctx_switch( src, dst );
     117                CoroutineCtxSwitch( src, dst );
    145118        }
    146119}
     
    150123forall(dtype T | is_coroutine(T))
    151124void prime(T& cor) {
    152         $coroutine* this = get_coroutine(cor);
     125        coroutine_desc* this = get_coroutine(cor);
    153126        assert(this->state == Start);
    154127
     
    161134        assert(__page_size != 0l);
    162135        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
    163         size = ceiling(size, __page_size);
    164136
    165137        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
    166138        void * storage;
    167         #if CFA_COROUTINE_USE_MMAP
    168                 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    169                 if(storage == ((void*)-1)) {
    170                         abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
     139        __cfaabi_dbg_debug_do(
     140                storage = memalign( __page_size, size + __page_size );
     141        );
     142        __cfaabi_dbg_no_debug_do(
     143                storage = (void*)malloc(size);
     144        );
     145
     146        __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size);
     147        __cfaabi_dbg_debug_do(
     148                if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     149                        abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    171150                }
    172                 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
    173                         abort( "coroutine stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    174                 } // if
    175151                storage = (void *)(((intptr_t)storage) + __page_size);
    176         #else
    177                 __cfaabi_dbg_debug_do(
    178                         storage = memalign( __page_size, size + __page_size );
    179                 );
    180                 __cfaabi_dbg_no_debug_do(
    181                         storage = (void*)malloc(size);
    182                 );
    183 
    184                 __cfaabi_dbg_debug_do(
    185                         if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
    186                                 abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    187                         }
    188                         storage = (void *)(((intptr_t)storage) + __page_size);
    189                 );
    190         #endif
    191         __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size);
     152        );
    192153
    193154        verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul );
    194155        return [storage, size];
    195 }
    196 
    197 void __stack_clean  ( __stack_info_t * this ) {
    198         size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t);
    199         void * storage = this->storage->limit;
    200 
    201         #if CFA_COROUTINE_USE_MMAP
    202                 storage = (void *)(((intptr_t)storage) - __page_size);
    203                 if(munmap(storage, size + __page_size) == -1) {
    204                         abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) );
    205                 }
    206         #else
    207                 __cfaabi_dbg_debug_do(
    208                         storage = (char*)(storage) - __page_size;
    209                         if ( mprotect( storage, __page_size, __map_prot ) == -1 ) {
    210                                 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    211                         }
    212                 );
    213 
    214                 free( storage );
    215         #endif
    216         __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
    217156}
    218157
     
    236175                size = libFloor(create_size - stack_data_size - diff, libAlign());
    237176        } // if
    238         assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize );
    239 
    240         this->storage = (__stack_t *)((intptr_t)storage + size - sizeof(__stack_t));
     177        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
     178
     179        this->storage = (__stack_t *)((intptr_t)storage + size);
    241180        this->storage->limit = storage;
    242         this->storage->base  = (void*)((intptr_t)storage + size - sizeof(__stack_t));
    243         this->storage->exception_context.top_resume = 0p;
    244         this->storage->exception_context.current_exception = 0p;
     181        this->storage->base  = (void*)((intptr_t)storage + size);
    245182        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
    246183        *istorage |= userStack ? 0x1 : 0x0;
     
    250187// is not inline (We can't inline Cforall in C)
    251188extern "C" {
    252         void __cfactx_cor_leave( struct $coroutine * src ) {
    253                 $coroutine * starter = src->cancellation != 0 ? src->last : src->starter;
     189        void __leave_coroutine( struct coroutine_desc * src ) {
     190                coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
    254191
    255192                src->state = Halted;
     
    264201                        src->name, src, starter->name, starter );
    265202
    266                 $ctx_switch( src, starter );
    267         }
    268 
    269         struct $coroutine * __cfactx_cor_finish(void) {
    270                 struct $coroutine * cor = active_coroutine();
     203                CoroutineCtxSwitch( src, starter );
     204        }
     205
     206        struct coroutine_desc * __finish_coroutine(void) {
     207                struct coroutine_desc * cor = kernelTLS.this_thread->curr_cor;
    271208
    272209                if(cor->state == Primed) {
    273                         __cfactx_suspend();
     210                        suspend();
    274211                }
    275212
Note: See TracChangeset for help on using the changeset viewer.