source: libcfa/src/concurrency/invoke.h@ 930e57e

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 930e57e was 1c01c58, checked in by Andrew Beach <ajbeach@…>, 5 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.