Changeset ab8c6a6


Ignore:
Timestamp:
Oct 26, 2020, 12:17:28 PM (3 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:
342be43
Parents:
912cc7d7
Message:

Thread Cancellation, a test for it and a required fix to Specialization.

Files:
2 added
6 edited

Legend:

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

    r912cc7d7 rab8c6a6  
    1919#include <unwind.h>
    2020#undef HIDE_EXPORTS
     21
     22extern void __cfactx_thrd_leave();
    2123}
    2224
     
    5254
    5355STOP_AT_END_FUNCTION(thread_cancelstop,
    54         // TODO: Instead pass information to the joiner.
    55         abort();
     56    __cfactx_thrd_leave();
     57    __cabi_abort( "Resumed cancelled thread" );
    5658)
    5759
     
    8587                stop_param = (void *)0x22;
    8688        } else {
     89                this_thread->self_cor.cancellation = unwind_exception;
     90
    8791                stop_func = thread_cancelstop;
    8892                stop_param = this_thread;
  • libcfa/src/concurrency/monitor.cfa

    r912cc7d7 rab8c6a6  
    306306        /* paranoid */ verify( thrd->state == Halted );
    307307        unpark( new_owner );
    308 }
    309 
    310 // Join a thread
    311 forall( dtype T | is_thread(T) )
    312 T & join( T & this ) {
    313         $monitor *    m = get_monitor(this);
    314         void (*dtor)(T& mutex this) = ^?{};
    315         monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
    316         {
    317                 return this;
    318         }
    319308}
    320309
  • libcfa/src/concurrency/thread.cfa

    r912cc7d7 rab8c6a6  
    1919
    2020#include "kernel_private.hfa"
     21#include "exception.hfa"
    2122
    2223#define __CFA_INVOKE_PRIVATE__
     
    5859}
    5960
     61FORALL_DATA_INSTANCE(ThreadCancelled, (dtype thread_t), (thread_t))
     62
     63forall(dtype T)
     64void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src) {
     65        dst->virtual_table = src->virtual_table;
     66        dst->the_thread = src->the_thread;
     67        dst->the_exception = src->the_exception;
     68}
     69
     70forall(dtype T)
     71const char * msg(ThreadCancelled(T) *) {
     72        return "ThreadCancelled";
     73}
     74
     75struct __cfaehm_node {
     76        struct _Unwind_Exception unwind_exception;
     77        struct __cfaehm_node * next;
     78        int handler_index;
     79};
     80
     81forall(dtype T)
     82static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
     83        abort( "Unhandled thread cancellation.\n" );
     84}
     85
     86forall(dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
     87void ?{}( thread_dtor_guard_t & this,
     88                T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
     89        $monitor * m = get_monitor(thrd);
     90        void (*dtor)(T& mutex this) = ^?{};
     91        bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
     92        (this.mg){&m, (void(*)())dtor, join};
     93        {
     94                $thread * desc = get_thread(thrd);
     95                struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
     96                if ( likely(0p == cancellation) ) {
     97                        return;
     98                } else if ( Cancelled == desc->state ) {
     99                        return;
     100                }
     101                desc->state = Cancelled;
     102                if (!join) {
     103                        defaultResumptionHandler = default_thread_cancel_handler;
     104                }
     105                ThreadCancelled(T) except;
     106                // TODO: Remove explitate vtable set once trac#186 is fixed.
     107                except.virtual_table = &get_exception_vtable(&except);
     108                except.the_thread = &thrd;
     109                except.the_exception = (exception_t *)(1 + (__cfaehm_node *)cancellation);
     110                throwResume except;
     111
     112                except.the_exception->virtual_table->free( except.the_exception );
     113                free( cancellation );
     114                desc->self_cor.cancellation = 0p;
     115        }
     116}
     117
     118void ^?{}( thread_dtor_guard_t & this ) {
     119        ^(this.mg){};
     120}
     121
    60122//-----------------------------------------------------------------------------
    61123// Starting and stopping threads
     
    93155}
    94156
     157//-----------------------------------------------------------------------------
     158forall(dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
     159T & join( T & this ) {
     160        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
     161        return this;
     162}
     163
    95164// Local Variables: //
    96165// mode: c //
  • libcfa/src/concurrency/thread.hfa

    r912cc7d7 rab8c6a6  
    2222#include "kernel.hfa"
    2323#include "monitor.hfa"
     24#include "exception.hfa"
    2425
    2526//-----------------------------------------------------------------------------
    2627// thread trait
    2728trait is_thread(dtype T) {
    28       void ^?{}(T& mutex this);
    29       void main(T& this);
    30       $thread* get_thread(T& this);
     29        void ^?{}(T& mutex this);
     30        void main(T& this);
     31        $thread* get_thread(T& this);
    3132};
     33
     34FORALL_DATA_EXCEPTION(ThreadCancelled, (dtype thread_t), (thread_t)) (
     35        thread_t * the_thread;
     36        exception_t * the_exception;
     37);
     38
     39forall(dtype T)
     40void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src);
     41
     42forall(dtype T)
     43const char * msg(ThreadCancelled(T) *);
    3244
    3345// define that satisfies the trait without using the thread keyword
     
    6577static inline void ?{}($thread & this, const char * const name, struct cluster & cl )                   { this{ name, cl, 0p, 65000 }; }
    6678static inline void ?{}($thread & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, 0p, stackSize }; }
     79
     80struct thread_dtor_guard_t {
     81        monitor_dtor_guard_t mg;
     82};
     83
     84forall( dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
     85void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
     86void ^?{}( thread_dtor_guard_t & this );
    6787
    6888//-----------------------------------------------------------------------------
     
    108128//----------
    109129// join
    110 forall( dtype T | is_thread(T) )
     130forall( dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
    111131T & join( T & this );
    112132
  • src/Concurrency/Keywords.cc

    r912cc7d7 rab8c6a6  
    4646        }
    4747
     48        // Only detects threads constructed with the keyword thread.
     49        inline static bool isThread( DeclarationWithType * decl ) {
     50                Type * baseType = decl->get_type()->stripDeclarator();
     51                StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
     52                if ( nullptr == instType ) { return false; }
     53                return instType->baseStruct->is_thread();
     54        }
     55
    4856        //=============================================================================================
    4957        // Pass declarations
     
    119127                        "get_thread",
    120128                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
    121                         "",
     129                        "ThreadCancelled",
    122130                        true,
    123131                        AggregateDecl::Thread
     
    290298                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
    291299                void validate( DeclarationWithType * );
    292                 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    293                 void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     300                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     301                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     302                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
    294303
    295304                static void implement( std::list< Declaration * > & translationUnit ) {
     
    302311                StructDecl* guard_decl = nullptr;
    303312                StructDecl* dtor_guard_decl = nullptr;
     313                StructDecl* thread_guard_decl = nullptr;
    304314
    305315                static std::unique_ptr< Type > generic_func;
     
    801811                bool first = false;
    802812                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
    803                 bool isDtor = CodeGen::isDestructor( decl->name );
     813                bool const isDtor = CodeGen::isDestructor( decl->name );
    804814
    805815                // Is this function relevant to monitors
     
    849859
    850860                // Instrument the body
    851                 if( isDtor ) {
    852                         addDtorStatments( decl, body, mutexArgs );
     861                if ( isDtor && isThread( mutexArgs.front() ) ) {
     862                        if( !thread_guard_decl ) {
     863                                SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
     864                        }
     865                        addThreadDtorStatements( decl, body, mutexArgs );
     866                }
     867                else if ( isDtor ) {
     868                        addDtorStatements( decl, body, mutexArgs );
    853869                }
    854870                else {
    855                         addStatments( decl, body, mutexArgs );
     871                        addStatements( decl, body, mutexArgs );
    856872                }
    857873        }
     
    870886                        assert( !dtor_guard_decl );
    871887                        dtor_guard_decl = decl;
     888                }
     889                else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
     890                        assert( !thread_guard_decl );
     891                        thread_guard_decl = decl;
    872892                }
    873893        }
     
    908928        }
    909929
    910         void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     930        void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    911931                Type * arg_type = args.front()->get_type()->clone();
    912932                arg_type->set_mutex( false );
     
    957977
    958978                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    959                 body->push_front( new DeclStmt( monitors) );
    960         }
    961 
    962         void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     979                body->push_front( new DeclStmt( monitors ) );
     980        }
     981
     982        void MutexKeyword::addThreadDtorStatements(
     983                        FunctionDecl*, CompoundStmt * body,
     984                        const std::list<DeclarationWithType * > & args ) {
     985                assert( args.size() == 1 );
     986                DeclarationWithType * arg = args.front();
     987                Type * arg_type = arg->get_type()->clone();
     988                assert( arg_type->get_mutex() );
     989                arg_type->set_mutex( false );
     990
     991                // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
     992                body->push_front(
     993                        new DeclStmt( new ObjectDecl(
     994                                "__guard",
     995                                noStorageClasses,
     996                                LinkageSpec::Cforall,
     997                                nullptr,
     998                                new StructInstType(
     999                                        noQualifiers,
     1000                                        thread_guard_decl
     1001                                ),
     1002                                new ListInit(
     1003                                        {
     1004                                                new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
     1005                                                new SingleInit( new UntypedExpr(
     1006                                                        new NameExpr( "intptr" ), {
     1007                                                                new ConstantExpr( Constant::from_int( 0 ) ),
     1008                                                        }
     1009                                                ) ),
     1010                                        },
     1011                                        noDesignators,
     1012                                        true
     1013                                )
     1014                        ))
     1015                );
     1016        }
     1017
     1018        void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    9631019                ObjectDecl * monitors = new ObjectDecl(
    9641020                        "__monitors",
  • src/GenPoly/Specialize.cc

    r912cc7d7 rab8c6a6  
    321321        }
    322322
     323        // Fold it into Specialize if we find a good way.
     324        struct StaticThunks final : public WithShortCircuiting {
     325                void previsit( Declaration * ) {
     326                        visit_children = false;
     327                }
     328                void postvisit( FunctionDecl * decl ) {
     329                        if ( isPrefix( decl->name, "_thunk" ) ) {
     330                                decl->storageClasses.is_static = true;
     331                        }
     332                }
     333        };
     334
    323335        void convertSpecializations( std::list< Declaration* >& translationUnit ) {
    324336                PassVisitor<Specialize> spec;
    325337                mutateAll( translationUnit, spec );
     338                PassVisitor<StaticThunks> staticThunks;
     339                acceptAll( translationUnit, staticThunks );
    326340        }
    327341} // namespace GenPoly
Note: See TracChangeset for help on using the changeset viewer.