Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into dkobets-vector

File:
1 edited

Legend:

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

    rbdfc032 reef8dfb  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec  5 14:37:29 2019
    13 // Update Count     : 15
     12// Last Modified On : Tue Dec 15 12:06:04 2020
     13// Update Count     : 23
    1414//
    1515
     
    1818#include "coroutine.hfa"
    1919
    20 extern "C" {
    2120#include <stddef.h>
    2221#include <malloc.h>
     
    2423#include <string.h>
    2524#include <unistd.h>
    26 // use this define to make unwind.h play nice, definetely a hack
    27 #define HIDE_EXPORTS
     25#include <sys/mman.h>                                                                   // mprotect
    2826#include <unwind.h>
    29 #undef HIDE_EXPORTS
    30 #include <sys/mman.h>
    31 }
    3227
    3328#include "kernel_private.hfa"
     29#include "exception.hfa"
     30#include "math.hfa"
     31
     32#define CFA_COROUTINE_USE_MMAP 0
    3433
    3534#define __CFA_INVOKE_PRIVATE__
     
    3736
    3837extern "C" {
    39         void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     38        void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__));
    4039        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
    4140        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
     
    4746
    4847//-----------------------------------------------------------------------------
     48FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
     49
     50forall(dtype T)
     51void mark_exception(CoroutineCancelled(T) *) {}
     52
     53forall(dtype T)
     54void 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
     60forall(dtype T)
     61const char * msg(CoroutineCancelled(T) *) {
     62        return "CoroutineCancelled(...)";
     63}
     64
     65// This code should not be inlined. It is the error path on resume.
     66forall(dtype T | is_coroutine(T))
     67void __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//-----------------------------------------------------------------------------
    4985// Global state variables
    5086
    5187// minimum feasible stack size in bytes
    52 #define MinStackSize 1000
     88static const size_t MinStackSize = 1000;
    5389extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
     90extern int __map_prot;
    5491
    5592void __stack_prepare( __stack_info_t * this, size_t create_size );
     93void __stack_clean  ( __stack_info_t * this );
    5694
    5795//-----------------------------------------------------------------------------
     
    74112        bool userStack = ((intptr_t)this.storage & 0x1) != 0;
    75113        if ( ! userStack && this.storage ) {
    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 
    91 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
     114                __stack_clean( &this );
     115        }
     116}
     117
     118void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ) with( this ) {
    92119        (this.context){0p, 0p};
    93120        (this.stack){storage, storageSize};
     
    99126}
    100127
    101 void ^?{}(coroutine_desc& this) {
     128void ^?{}($coroutine& this) {
    102129        if(this.state != Halted && this.state != Start && this.state != Primed) {
    103                 coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    104                 coroutine_desc * dst = &this;
     130                $coroutine * src = active_coroutine();
     131                $coroutine * dst = &this;
    105132
    106133                struct _Unwind_Exception storage;
     
    115142                }
    116143
    117                 CoroutineCtxSwitch( src, dst );
     144                $ctx_switch( src, dst );
    118145        }
    119146}
     
    123150forall(dtype T | is_coroutine(T))
    124151void prime(T& cor) {
    125         coroutine_desc* this = get_coroutine(cor);
     152        $coroutine* this = get_coroutine(cor);
    126153        assert(this->state == Start);
    127154
     
    134161        assert(__page_size != 0l);
    135162        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
     163        size = ceiling(size, __page_size);
    136164
    137165        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
    138166        void * storage;
    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 
     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 ) );
     171                }
     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
     175                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
    146191        __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 ) );
    150                 }
    151                 storage = (void *)(((intptr_t)storage) + __page_size);
    152         );
    153192
    154193        verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul );
    155194        return [storage, size];
     195}
     196
     197void __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);
    156217}
    157218
     
    175236                size = libFloor(create_size - stack_data_size - diff, libAlign());
    176237        } // if
    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);
     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));
    180241        this->storage->limit = storage;
    181         this->storage->base  = (void*)((intptr_t)storage + size);
     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;
    182245        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
    183246        *istorage |= userStack ? 0x1 : 0x0;
     
    187250// is not inline (We can't inline Cforall in C)
    188251extern "C" {
    189         void __leave_coroutine( struct coroutine_desc * src ) {
    190                 coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
     252        void __cfactx_cor_leave( struct $coroutine * src ) {
     253                $coroutine * starter = src->cancellation != 0 ? src->last : src->starter;
    191254
    192255                src->state = Halted;
     
    201264                        src->name, src, starter->name, starter );
    202265
    203                 CoroutineCtxSwitch( src, starter );
    204         }
    205 
    206         struct coroutine_desc * __finish_coroutine(void) {
    207                 struct coroutine_desc * cor = kernelTLS.this_thread->curr_cor;
     266                $ctx_switch( src, starter );
     267        }
     268
     269        struct $coroutine * __cfactx_cor_finish(void) {
     270                struct $coroutine * cor = active_coroutine();
    208271
    209272                if(cor->state == Primed) {
    210                         suspend();
     273                        __cfactx_suspend();
    211274                }
    212275
Note: See TracChangeset for help on using the changeset viewer.