source: libcfa/src/concurrency/invoke.h @ 9dc3eb21

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 9dc3eb21 was 1c01c58, checked in by Andrew Beach <ajbeach@…>, 4 years ago

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.

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[8def349]1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// invoke.h --
8//
9// Author           : Thierry Delisle
10// Created On       : Tue Jan 17 12:27:26 2016
[6b0b624]11// Last Modified By : Peter A. Buhr
[09d4b22]12// Last Modified On : Thu Dec  5 16:26:03 2019
13// Update Count     : 44
[8def349]14//
15
[73abe95]16#include "bits/containers.hfa"
17#include "bits/defs.hfa"
18#include "bits/locks.hfa"
[3e2b9c9]19#include "kernel/fwd.hfa"
[78b3f52]20
[0cf5b79]21#ifdef __cforall
[5c81105]22extern "C" {
23#endif
24
25#if ! defined(__CFA_INVOKE_PRIVATE__)
[78b3f52]26#ifndef _INVOKE_H_
27#define _INVOKE_H_
28
[80ec409]29        struct __cfaehm_try_resume_node;
30        struct __cfaehm_base_exception_t;
31        struct exception_context_t {
32                struct __cfaehm_try_resume_node * top_resume;
33                struct __cfaehm_base_exception_t * current_exception;
34        };
35
[b2f6113]36        struct __stack_context_t {
37                void * SP;
38                void * FP;
39        };
40
41        // low adresses  :           +----------------------+ <- start of allocation
42        //                           |  optional guard page |
43        //                           +----------------------+ <- __stack_t.limit
44        //                           |                      |
45        //                           |       /\ /\ /\       |
46        //                           |       || || ||       |
47        //                           |                      |
48        //                           |    program  stack    |
49        //                           |                      |
50        // __stack_info_t.storage -> +----------------------+ <- __stack_t.base
51        //                           |      __stack_t       |
52        // high adresses :           +----------------------+ <- end of allocation
53
54        struct __stack_t {
55                // stack grows towards stack limit
56                void * limit;
57
58                // base of stack
59                void * base;
[80ec409]60
61                // Information for exception handling.
62                struct exception_context_t exception_context;
[b2f6113]63        };
64
65        struct __stack_info_t {
66                // pointer to stack
67                struct __stack_t * storage;
[025278e]68        };
69
[1c01c58]70        enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled };
[025278e]71
[ac2b598]72        struct $coroutine {
[c7a900a]73                // context that is switch during a __cfactx_switch
[b2f6113]74                struct __stack_context_t context;
75
[76e069f]76                // stack information of the coroutine
[b2f6113]77                struct __stack_info_t stack;
[76e069f]78
[e8e457e]79                // textual name for coroutine/task
[76e069f]80                const char * name;
81
82                // current execution status for coroutine
[ff79d5e]83                enum __Coroutine_State state;
[b2f6113]84
[76e069f]85                // first coroutine to resume this one
[ac2b598]86                struct $coroutine * starter;
[76e069f]87
88                // last coroutine to resume this one
[ac2b598]89                struct $coroutine * last;
[76e069f]90
91                // If non-null stack must be unwound with this exception
92                struct _Unwind_Exception * cancellation;
93
[025278e]94        };
95
[80ec409]96        static inline struct __stack_t * __get_stack( struct $coroutine * cor ) {
97                return (struct __stack_t*)(((uintptr_t)cor->stack.storage) & ((uintptr_t)-2));
98        }
[210b8b3]99
[f23b685]100        // struct which calls the monitor is accepting
[025278e]101        struct __waitfor_mask_t {
102                // the index of the accepted function, -1 if none
103                short * accepted;
104
105                // list of acceptable functions, null if any
[b1672e1]106                __cfa_anonymous_object( __small_array_t(struct __acceptable_t) );
[025278e]107        };
108
[ac2b598]109        struct $monitor {
[025278e]110                // spinlock to protect internal data
[ea7d2b0]111                struct __spinlock_t lock;
[025278e]112
113                // current owner of the monitor
[ac2b598]114                struct $thread * owner;
[025278e]115
116                // queue of threads that are blocked waiting for the monitor
[ac2b598]117                __queue_t(struct $thread) entry_queue;
[025278e]118
119                // stack of conditions to run next once we exit the monitor
[0cf5b79]120                __stack_t(struct __condition_criterion_t) signal_stack;
[025278e]121
122                // monitor routines can be called recursively, we need to keep track of that
123                unsigned int recursion;
124
125                // mask used to know if some thread is waiting for something while holding the monitor
126                struct __waitfor_mask_t mask;
127
128                // node used to signal the dtor in a waitfor dtor
129                struct __condition_node_t * dtor_node;
130        };
131
132        struct __monitor_group_t {
133                // currently held monitors
[ac2b598]134                __cfa_anonymous_object( __small_array_t($monitor*) );
[025278e]135
136                // last function that acquired monitors
[c1a9c86]137                fptr_t func;
[025278e]138        };
139
[b798713]140        // Link lists fields
141        // instrusive link field for threads
142        struct __thread_desc_link {
[6a490b2]143                struct $thread * next;
144                struct $thread * prev;
[1b143de]145                volatile unsigned long long ts;
[d72c074]146                int preferred;
[b798713]147        };
148
[ac2b598]149        struct $thread {
[025278e]150                // Core threading fields
[c7a900a]151                // context that is switch during a __cfactx_switch
[e8e457e]152                struct __stack_context_t context;
153
154                // current execution status for coroutine
[ff79d5e]155                volatile int ticket;
156                enum __Coroutine_State state:8;
157                enum __Preemption_Reason preempted:8;
[e8e457e]158
[5c1a531]159                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
160
[37ba662]161                // pointer to the cluster on which the thread is running
162                struct cluster * curr_cluster;
163
164                // Link lists fields
165                // instrusive link field for threads
166                struct __thread_desc_link link;
167
[025278e]168                // coroutine body used to store context
[ac2b598]169                struct $coroutine  self_cor;
[025278e]170
[82c948c]171                // current active context
[ac2b598]172                struct $coroutine * curr_cor;
[82c948c]173
[025278e]174                // monitor body used for mutual exclusion
[ac2b598]175                struct $monitor    self_mon;
[025278e]176
177                // pointer to monitor with sufficient lifetime for current monitors
[ac2b598]178                struct $monitor *  self_mon_p;
[025278e]179
180                // monitors currently held by this thread
181                struct __monitor_group_t monitors;
182
[de94a60]183                struct {
[ac2b598]184                        struct $thread * next;
185                        struct $thread * prev;
[de94a60]186                } node;
[ae66348]187
188                #ifdef __CFA_DEBUG__
189                        // previous function to park/unpark the thread
[ae7be7a]190                        const char * park_caller;
[ff79d5e]191                        int park_result;
192                        enum __Coroutine_State park_state;
[ae66348]193                        bool park_stale;
[ae7be7a]194                        const char * unpark_caller;
[ff79d5e]195                        int unpark_result;
196                        enum __Coroutine_State unpark_state;
[ae66348]197                        bool unpark_stale;
198                #endif
[212c2187]199        };
200
[ae66348]201        #ifdef __CFA_DEBUG__
202                void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]);
203        #else
204                #define __cfaabi_dbg_record_thrd(x, y, z)
205        #endif
206
[212c2187]207        #ifdef __cforall
208        extern "Cforall" {
[6a490b2]209
[ac2b598]210                static inline $thread *& get_next( $thread & this ) __attribute__((const)) {
[b798713]211                        return this.link.next;
[0cf5b79]212                }
213
[ac2b598]214                static inline [$thread *&, $thread *& ] __get( $thread & this ) __attribute__((const)) {
[de94a60]215                        return this.node.[next, prev];
216                }
217
[0cf5b79]218                static inline void ?{}(__monitor_group_t & this) {
[121be3e]219                        (this.data){0p};
[0cf5b79]220                        (this.size){0};
221                        (this.func){NULL};
222                }
223
[ac2b598]224                static inline void ?{}(__monitor_group_t & this, struct $monitor ** data, __lock_size_t size, fptr_t func) {
[0cf5b79]225                        (this.data){data};
226                        (this.size){size};
227                        (this.func){func};
[025278e]228                }
229
[8c50aed]230                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) __attribute__((const)) {
[0cf5b79]231                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
[025278e]232                        if( lhs.size != rhs.size ) return false;
233                        if( lhs.func != rhs.func ) return false;
234
235                        // Check that all the monitors match
236                        for( int i = 0; i < lhs.size; i++ ) {
237                                // If not a match, check next function
238                                if( lhs[i] != rhs[i] ) return false;
239                        }
240
241                        return true;
242                }
[0cf5b79]243
244                static inline void ?=?(__monitor_group_t & lhs, const __monitor_group_t & rhs) {
245                        lhs.data = rhs.data;
246                        lhs.size = rhs.size;
247                        lhs.func = rhs.func;
248                }
[025278e]249        }
250        #endif
[b18830e]251
[5c81105]252#endif //_INVOKE_H_
253#else //! defined(__CFA_INVOKE_PRIVATE__)
254#ifndef _INVOKE_PRIVATE_H_
255#define _INVOKE_PRIVATE_H_
[b227f68]256
[025278e]257        struct machine_context_t {
258                void *SP;
259                void *FP;
260                void *PC;
261        };
262
263        // assembler routines that performs the context switch
[c7a900a]264        extern void __cfactx_invoke_stub( void );
265        extern void __cfactx_switch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("__cfactx_switch");
[212c2187]266        // void CtxStore ( void * this ) asm ("CtxStore");
267        // void CtxRet   ( void * dst  ) asm ("CtxRet");
[025278e]268
[5c81105]269#endif //_INVOKE_PRIVATE_H_
270#endif //! defined(__CFA_INVOKE_PRIVATE__)
[0cf5b79]271#ifdef __cforall
[5c81105]272}
273#endif
[6b0b624]274
275// Local Variables: //
276// mode: c //
277// tab-width: 4 //
278// End: //
Note: See TracBrowser for help on using the repository browser.