Changeset 1c01c58 for libcfa/src


Ignore:
Timestamp:
Sep 9, 2020, 5:03:40 PM (4 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
b9fa85b, c402739
Parents:
2b7f6f0
Message:

Rather large commit to get coroutine cancellation working.

This includes what you would expect, like new code in exceptions and a new
test, but it also includes a bunch of other things.

New coroutine state, currently just marks that the stack was cancelled. New
helpers for checking code structure and generating vtables. Changes to the
coroutine interface so resume may throw exceptions on cancellation, plus the
exception type that is thrown. Changes to the coroutine keyword generation to
generate exception code for each type of coroutine.

Location:
libcfa/src
Files:
7 edited

Legend:

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

    r2b7f6f0 r1c01c58  
    4747
    4848//-----------------------------------------------------------------------------
     49FORALL_DATA_INSTANCE(CoroutineCancelled,
     50                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
     51
     52struct __cfaehm_node {
     53        struct _Unwind_Exception unwind_exception;
     54        struct __cfaehm_node * next;
     55        int handler_index;
     56};
     57
     58forall(dtype T)
     59void mark_exception(CoroutineCancelled(T) *) {}
     60
     61forall(dtype T | sized(T))
     62void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
     63        dst->the_coroutine = src->the_coroutine;
     64        dst->the_exception = src->the_exception;
     65}
     66
     67forall(dtype T)
     68const char * msg(CoroutineCancelled(T) *) {
     69        return "CoroutineCancelled(...)";
     70}
     71
     72// This code should not be inlined. It is the error path on resume.
     73forall(dtype T | is_coroutine(T))
     74void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) {
     75        verify( desc->cancellation );
     76        desc->state = Cancelled;
     77        exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
     78
     79        CoroutineCancelled(T) except;
     80        except.the_coroutine = &cor;
     81        except.the_exception = except;
     82        throwResume except;
     83
     84        except->virtual_table->free( except );
     85        free( desc->cancellation );
     86        desc->cancellation = 0p;
     87}
     88
     89//-----------------------------------------------------------------------------
    4990// Global state variables
    5091
     
    180221        this->storage->limit = storage;
    181222        this->storage->base  = (void*)((intptr_t)storage + size);
     223        this->storage->exception_context.top_resume = 0p;
     224        this->storage->exception_context.current_exception = 0p;
    182225        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
    183226        *istorage |= userStack ? 0x1 : 0x0;
  • libcfa/src/concurrency/coroutine.hfa

    r2b7f6f0 r1c01c58  
    1818#include <assert.h>
    1919#include "invoke.h"
     20#include "../exception.hfa"
     21
     22//-----------------------------------------------------------------------------
     23// Exception thrown from resume when a coroutine stack is cancelled.
     24// Should not have to be be sized (see trac #196).
     25FORALL_DATA_EXCEPTION(CoroutineCancelled,
     26                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
     27        coroutine_t * the_coroutine;
     28        exception_t * the_exception;
     29);
     30
     31forall(dtype T)
     32void mark_exception(CoroutineCancelled(T) *);
     33
     34forall(dtype T | sized(T))
     35void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
     36
     37forall(dtype T)
     38const char * msg(CoroutineCancelled(T) *);
    2039
    2140//-----------------------------------------------------------------------------
     
    2342// Anything that implements this trait can be resumed.
    2443// Anything that is resumed is a coroutine.
    25 trait is_coroutine(dtype T) {
    26       void main(T & this);
    27       $coroutine * get_coroutine(T & this);
     44trait is_coroutine(dtype T | sized(T)
     45                | is_resumption_exception(CoroutineCancelled(T))
     46                | VTABLE_ASSERTION(CoroutineCancelled, (T))) {
     47        void main(T & this);
     48        $coroutine * get_coroutine(T & this);
    2849};
    2950
     
    112133        }
    113134}
     135
     136forall(dtype T | is_coroutine(T))
     137void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc );
    114138
    115139// Resume implementation inlined for performance
     
    145169        // always done for performance testing
    146170        $ctx_switch( src, dst );
     171        if ( unlikely(dst->cancellation) ) {
     172                __cfaehm_cancelled_coroutine( cor, dst );
     173        }
    147174
    148175        return cor;
  • libcfa/src/concurrency/exception.cfa

    r2b7f6f0 r1c01c58  
    5757
    5858STOP_AT_END_FUNCTION(coroutine_cancelstop,
    59         // TODO: Instead pass information to the last resumer.
     59        struct $coroutine * src = ($coroutine *)stop_param;
     60        struct $coroutine * dst = src->last;
     61
     62        $ctx_switch( src, dst );
    6063        abort();
    6164)
  • libcfa/src/concurrency/exception.hfa

    r2b7f6f0 r1c01c58  
    1818#include "bits/defs.hfa"
    1919#include "invoke.h"
    20 struct _Unwind_Exception;
    21 
    22 // It must also be usable as a C header file.
    2320
    2421#ifdef __cforall
    2522extern "C" {
     23
     24#define HIDE_EXPORTS
    2625#endif
     26#include "unwind.h"
    2727
    2828struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD;
     
    3232
    3333#ifdef __cforall
     34#undef HIDE_EXPORTS
    3435}
    3536#endif
  • libcfa/src/concurrency/invoke.h

    r2b7f6f0 r1c01c58  
    6868        };
    6969
    70         enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active };
     70        enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled };
    7171
    7272        struct $coroutine {
  • libcfa/src/exception.h

    r2b7f6f0 r1c01c58  
    7676// implemented in the .c file either so they all have to be inline.
    7777
    78 trait is_exception(dtype T) {
     78trait is_exception(dtype exceptT) {
    7979        /* The first field must be a pointer to a virtual table.
    8080         * That virtual table must be a decendent of the base exception virtual tab$
    8181         */
    82         void mark_exception(T *);
     82        void mark_exception(exceptT *);
    8383        // This is never used and should be a no-op.
    8484};
    8585
    86 trait is_termination_exception(dtype T | is_exception(T)) {
    87         void defaultTerminationHandler(T &);
     86trait is_termination_exception(dtype exceptT | is_exception(exceptT)) {
     87        void defaultTerminationHandler(exceptT &);
    8888};
    8989
    90 trait is_resumption_exception(dtype T | is_exception(T)) {
    91         void defaultResumptionHandler(T &);
     90trait is_resumption_exception(dtype exceptT | is_exception(exceptT)) {
     91        void defaultResumptionHandler(exceptT &);
    9292};
    9393
    94 forall(dtype T | is_termination_exception(T))
    95 static inline void $throw(T & except) {
     94forall(dtype exceptT | is_termination_exception(exceptT))
     95static inline void $throw(exceptT & except) {
    9696        __cfaehm_throw_terminate(
    9797                (exception_t *)&except,
     
    100100}
    101101
    102 forall(dtype T | is_resumption_exception(T))
    103 static inline void $throwResume(T & except) {
     102forall(dtype exceptT | is_resumption_exception(exceptT))
     103static inline void $throwResume(exceptT & except) {
    104104        __cfaehm_throw_resume(
    105105                (exception_t *)&except,
     
    108108}
    109109
    110 forall(dtype T | is_exception(T))
    111 static inline void cancel_stack(T & except) __attribute__((noreturn)) {
     110forall(dtype exceptT | is_exception(exceptT))
     111static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) {
    112112        __cfaehm_cancel_stack( (exception_t *)&except );
    113113}
    114114
    115 forall(dtype T | is_exception(T))
    116 static inline void defaultTerminationHandler(T & except) {
     115forall(dtype exceptT | is_exception(exceptT))
     116static inline void defaultTerminationHandler(exceptT & except) {
    117117        return cancel_stack( except );
    118118}
    119119
    120 forall(dtype T | is_exception(T))
    121 static inline void defaultResumptionHandler(T & except) {
     120forall(dtype exceptT | is_exception(exceptT))
     121static inline void defaultResumptionHandler(exceptT & except) {
    122122        throw except;
    123123}
  • libcfa/src/exception.hfa

    r2b7f6f0 r1c01c58  
    192192                size_t size; \
    193193                void (*copy)(exception_name * this, exception_name * other); \
    194                 void (*free)(exception_name & this); \
     194                void (*^?{})(exception_name & this); \
    195195                const char * (*msg)(exception_name * this); \
    196196                _CLOSE
     
    213213                size_t size; \
    214214                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
    215                 void (*free)(exception_name parameters & this); \
     215                void (*^?{})(exception_name parameters & this); \
    216216                const char * (*msg)(exception_name parameters * this); \
    217217                _CLOSE
Note: See TracChangeset for help on using the changeset viewer.