Ignore:
Timestamp:
Oct 30, 2020, 12:36:16 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:
0ab3b73, 36d0a80
Parents:
b9537e6 (diff), 4ae78c1 (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' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
libcfa/src/concurrency
Files:
12 edited

Legend:

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

    rb9537e6 rf7e4f8e8  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 26 22:06:09 2020
    13 // Update Count     : 21
     12// Last Modified On : Fri Oct 23 23:05:24 2020
     13// Update Count     : 22
    1414//
    1515
     
    2424#include <unistd.h>
    2525#include <sys/mman.h>                                                                   // mprotect
    26 extern "C" {
    27 // use this define to make unwind.h play nice, definitely a hack
    28 #define HIDE_EXPORTS
    2926#include <unwind.h>
    30 #undef HIDE_EXPORTS
    31 }
    3227
    3328#include "kernel_private.hfa"
     29#include "exception.hfa"
    3430
    3531#define __CFA_INVOKE_PRIVATE__
     
    4945FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
    5046
    51 struct __cfaehm_node {
    52         struct _Unwind_Exception unwind_exception;
    53         struct __cfaehm_node * next;
    54         int handler_index;
    55 };
    56 
    5747forall(dtype T)
    5848void mark_exception(CoroutineCancelled(T) *) {}
     
    6050forall(dtype T)
    6151void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
     52        dst->virtual_table = src->virtual_table;
    6253        dst->the_coroutine = src->the_coroutine;
    6354        dst->the_exception = src->the_exception;
     
    7465        verify( desc->cancellation );
    7566        desc->state = Cancelled;
    76         exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
     67        exception_t * except = __cfaehm_cancellation_exception( desc->cancellation );
    7768
    7869        // TODO: Remove explitate vtable set once trac#186 is fixed.
     
    217208                size = libFloor(create_size - stack_data_size - diff, libAlign());
    218209        } // if
    219         assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
     210        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize );
    220211
    221212        this->storage = (__stack_t *)((intptr_t)storage + size);
  • libcfa/src/concurrency/exception.cfa

    rb9537e6 rf7e4f8e8  
    1010// Created On       : Mon Aug 17 10:41:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Aug 25 14:41:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Wed Oct 28 14:34:00 2020
     13// Update Count     : 1
    1414//
    1515
    16 extern "C" {
    17 // use this define to make unwind.h play nice, definitely a hack
    18 #define HIDE_EXPORTS
    19 #include <unwind.h>
    20 #undef HIDE_EXPORTS
    21 }
     16#define __cforall_thread__
    2217
    23 #include "invoke.h"
    2418#include "exception.hfa"
     19
    2520#include "coroutine.hfa"
    2621
    2722extern struct $thread * mainThread;
     23extern "C" {
     24extern void __cfactx_thrd_leave();
     25}
    2826
    2927// Common pattern for all the stop functions, wait until the end then act.
     
    5250
    5351STOP_AT_END_FUNCTION(thread_cancelstop,
    54         // TODO: Instead pass information to the joiner.
    55         abort();
     52        __cfactx_thrd_leave();
     53        __cabi_abort( "Resumed cancelled thread" );
    5654)
    5755
     
    8583                stop_param = (void *)0x22;
    8684        } else {
     85                this_thread->self_cor.cancellation = unwind_exception;
     86
    8787                stop_func = thread_cancelstop;
    8888                stop_param = this_thread;
  • libcfa/src/concurrency/exception.hfa

    rb9537e6 rf7e4f8e8  
    1616#pragma once
    1717
     18// This is an internal bridge between the two modes and must be C compatable.
     19
     20#include <unwind.h>
    1821#include "bits/defs.hfa"
    1922#include "invoke.h"
     23#include "exception.h"
    2024
    2125#ifdef __cforall
    2226extern "C" {
    23 
    24 #define HIDE_EXPORTS
    2527#endif
    26 #include "unwind.h"
    2728
    2829struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD;
     
    3233
    3334#ifdef __cforall
    34 #undef HIDE_EXPORTS
    3535}
    3636#endif
  • libcfa/src/concurrency/invoke.h

    rb9537e6 rf7e4f8e8  
    157157
    158158                // current execution status for coroutine
     159                // Possible values are:
     160                //    - TICKET_BLOCKED (-1) thread is blocked
     161                //    - TICKET_RUNNING ( 0) thread is running
     162                //    - TICKET_UNBLOCK ( 1) thread should ignore next block
    159163                volatile int ticket;
    160164                enum __Coroutine_State state:8;
  • libcfa/src/concurrency/io/setup.cfa

    rb9537e6 rf7e4f8e8  
    250250                                        // Fixup the thread state
    251251                                        thrd.state = Blocked;
    252                                         thrd.ticket = 0;
     252                                        thrd.ticket = TICKET_BLOCKED;
    253253                                        thrd.preempted = __NO_PREEMPTION;
    254254
  • libcfa/src/concurrency/kernel.cfa

    rb9537e6 rf7e4f8e8  
    252252                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    253253                /* paranoid */ verify( thrd_dst->context.SP );
     254                /* paranoid */ verify( thrd_dst->state != Halted );
    254255                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    255256                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
     
    287288                if(unlikely(thrd_dst->state == Halted)) {
    288289                        // The thread has halted, it should never be scheduled/run again
    289                         // We may need to wake someone up here since
    290                         unpark( this->destroyer );
    291                         this->destroyer = 0p;
     290                        // finish the thread
     291                        __thread_finish( thrd_dst );
    292292                        break RUNNING;
    293293                }
     
    299299                int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
    300300                switch(old_ticket) {
    301                         case 1:
     301                        case TICKET_RUNNING:
    302302                                // This is case 1, the regular case, nothing more is needed
    303303                                break RUNNING;
    304                         case 2:
     304                        case TICKET_UNBLOCK:
    305305                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    306306                                // In this case, just run it again.
     
    410410        int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
    411411        switch(old_ticket) {
    412                 case 1:
     412                case TICKET_RUNNING:
    413413                        // Wake won the race, the thread will reschedule/rerun itself
    414414                        break;
    415                 case 0:
     415                case TICKET_BLOCKED:
    416416                        /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
    417417                        /* paranoid */ verify( thrd->state == Blocked );
     
    422422                default:
    423423                        // This makes no sense, something is wrong abort
    424                         abort();
     424                        abort("Thread %p (%s) has mismatch park/unpark\n", thrd, thrd->self_cor.name);
    425425        }
    426426}
     
    448448}
    449449
    450 // KERNEL ONLY
    451 void __leave_thread() {
    452         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    453         returnToKernel();
    454         abort();
     450extern "C" {
     451        // Leave the thread monitor
     452        // last routine called by a thread.
     453        // Should never return
     454        void __cfactx_thrd_leave() {
     455                $thread * thrd = TL_GET( this_thread );
     456                $monitor * this = &thrd->self_mon;
     457
     458                // Lock the monitor now
     459                lock( this->lock __cfaabi_dbg_ctx2 );
     460
     461                disable_interrupts();
     462
     463                thrd->state = Halted;
     464
     465                if( thrd != this->owner || this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); }
     466
     467                // Leave the thread
     468                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     469                returnToKernel();
     470                abort();
     471
     472                // Control flow should never reach here!
     473        }
    455474}
    456475
  • libcfa/src/concurrency/kernel.hfa

    rb9537e6 rf7e4f8e8  
    7979        // Handle to pthreads
    8080        pthread_t kernel_thread;
    81 
    82         // RunThread data
    83         // Action to do after a thread is ran
    84         $thread * destroyer;
    8581
    8682        // Preemption data
  • libcfa/src/concurrency/kernel/startup.cfa

    rb9537e6 rf7e4f8e8  
    441441
    442442static void ?{}( $thread & this, current_stack_info_t * info) with( this ) {
    443         ticket = 1;
     443        ticket = TICKET_RUNNING;
    444444        state = Start;
    445445        self_cor{ info };
     
    474474        this.cltr = &_cltr;
    475475        full_proc = true;
    476         destroyer = 0p;
    477476        do_terminate = false;
    478477        preemption_alarm = 0p;
  • libcfa/src/concurrency/kernel_private.hfa

    rb9537e6 rf7e4f8e8  
    3939;
    4040
    41 //Block current thread and release/wake-up the following resources
    42 void __leave_thread() __attribute__((noreturn));
     41//release/wake-up the following resources
     42void __thread_finish( $thread * thrd );
    4343
    4444//-----------------------------------------------------------------------------
     
    6565// KERNEL ONLY unpark with out disabling interrupts
    6666void __unpark( struct __processor_id_t *, $thread * thrd );
     67
     68#define TICKET_BLOCKED (-1) // thread is blocked
     69#define TICKET_RUNNING ( 0) // thread is running
     70#define TICKET_UNBLOCK ( 1) // thread should ignore next block
    6771
    6872static inline bool __post(single_sem & this, struct __processor_id_t * id) {
  • libcfa/src/concurrency/monitor.cfa

    rb9537e6 rf7e4f8e8  
    281281}
    282282
    283 extern "C" {
    284         // Leave the thread monitor
    285         // last routine called by a thread.
    286         // Should never return
    287         void __cfactx_thrd_leave() {
    288                 $thread * thrd = TL_GET( this_thread );
    289                 $monitor * this = &thrd->self_mon;
    290 
    291                 // Lock the monitor now
    292                 lock( this->lock __cfaabi_dbg_ctx2 );
    293 
    294                 disable_interrupts();
    295 
    296                 thrd->state = Halted;
    297 
    298                 /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    299 
    300                 // Leaving a recursion level, decrement the counter
    301                 this->recursion -= 1;
    302 
    303                 // If we haven't left the last level of recursion
    304                 // it must mean there is an error
    305                 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); }
    306 
    307                 // Fetch the next thread, can be null
    308                 $thread * new_owner = next_thread( this );
    309 
    310                 // Release the monitor lock
    311                 unlock( this->lock );
    312 
    313                 // Unpark the next owner if needed
    314                 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    315                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    316                 /* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
    317                 /* paranoid */ verify( thrd->state == Halted );
    318 
    319                 kernelTLS.this_processor->destroyer = new_owner;
    320 
    321                 // Leave the thread
    322                 __leave_thread();
    323 
    324                 // Control flow should never reach here!
    325         }
    326 }
    327 
    328 // Join a thread
    329 forall( dtype T | is_thread(T) )
    330 T & join( T & this ) {
    331         $monitor *    m = get_monitor(this);
    332         void (*dtor)(T& mutex this) = ^?{};
    333         monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
    334         {
    335                 return this;
    336         }
     283void __thread_finish( $thread * thrd ) {
     284        $monitor * this = &thrd->self_mon;
     285
     286        // Lock the monitor now
     287        /* paranoid */ verify( this->lock.lock );
     288        /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
     289        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     290        /* paranoid */ verify( thrd->state == Halted );
     291        /* paranoid */ verify( this->recursion == 1 );
     292
     293        // Leaving a recursion level, decrement the counter
     294        this->recursion -= 1;
     295        this->owner = 0p;
     296
     297        // Fetch the next thread, can be null
     298        $thread * new_owner = next_thread( this );
     299
     300        // Release the monitor lock
     301        unlock( this->lock );
     302
     303        // Unpark the next owner if needed
     304        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     305        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     306        /* paranoid */ verify( thrd->state == Halted );
     307        unpark( new_owner );
    337308}
    338309
  • libcfa/src/concurrency/thread.cfa

    rb9537e6 rf7e4f8e8  
    1919
    2020#include "kernel_private.hfa"
     21#include "exception.hfa"
    2122
    2223#define __CFA_INVOKE_PRIVATE__
     
    2829        context{ 0p, 0p };
    2930        self_cor{ name, storage, storageSize };
    30         ticket = 1;
     31        ticket = TICKET_RUNNING;
    3132        state = Start;
    3233        preempted = __NO_PREEMPTION;
     
    5657        unregister(curr_cluster, this);
    5758        ^self_cor{};
     59}
     60
     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
     75forall(dtype T)
     76static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
     77        abort( "Unhandled thread cancellation.\n" );
     78}
     79
     80forall(dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
     81void ?{}( thread_dtor_guard_t & this,
     82                T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
     83        $monitor * m = get_monitor(thrd);
     84        void (*dtor)(T& mutex this) = ^?{};
     85        bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
     86        (this.mg){&m, (void(*)())dtor, join};
     87
     88        // After the guard set-up and any wait, check for cancellation.
     89        $thread * desc = get_thread(thrd);
     90        struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
     91        if ( likely( 0p == cancellation ) ) {
     92                return;
     93        } else if ( Cancelled == desc->state ) {
     94                return;
     95        }
     96        desc->state = Cancelled;
     97        if (!join) {
     98                defaultResumptionHandler = default_thread_cancel_handler;
     99        }
     100
     101        ThreadCancelled(T) except;
     102        // TODO: Remove explitate vtable set once trac#186 is fixed.
     103        except.virtual_table = &get_exception_vtable(&except);
     104        except.the_thread = &thrd;
     105        except.the_exception = __cfaehm_cancellation_exception( cancellation );
     106        throwResume except;
     107
     108        except.the_exception->virtual_table->free( except.the_exception );
     109        free( cancellation );
     110        desc->self_cor.cancellation = 0p;
     111}
     112
     113void ^?{}( thread_dtor_guard_t & this ) {
     114        ^(this.mg){};
    58115}
    59116
     
    93150}
    94151
     152//-----------------------------------------------------------------------------
     153forall(dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
     154T & join( T & this ) {
     155        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
     156        return this;
     157}
     158
    95159// Local Variables: //
    96160// mode: c //
  • libcfa/src/concurrency/thread.hfa

    rb9537e6 rf7e4f8e8  
    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
Note: See TracChangeset for help on using the changeset viewer.