source: libcfa/src/concurrency/invoke.h @ 3381ed7

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 3381ed7 was 3381ed7, checked in by Thierry Delisle <tdelisle@…>, 22 months ago

Added park/unpark primitives thread and removed BlockInternal?.
Converted monitors to use park unpark.
Intrusive Queue now mark next field when thread is inside queue.
Added several asserts to kernel and monitor.
Added a few tests for park and unpark.

  • Property mode set to 100644
File size: 7.5 KB
Line 
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
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Thu Dec  5 16:26:03 2019
13// Update Count     : 44
14//
15
16#include "bits/containers.hfa"
17#include "bits/defs.hfa"
18#include "bits/locks.hfa"
19
20#ifdef __cforall
21extern "C" {
22#endif
23
24#if ! defined(__CFA_INVOKE_PRIVATE__)
25#ifndef _INVOKE_H_
26#define _INVOKE_H_
27
28#ifdef __ARM_ARCH
29        // function prototypes are only really used by these macros on ARM
30        void disable_global_interrupts();
31        void enable_global_interrupts();
32
33        #define TL_GET( member ) ( { __typeof__( kernelTLS.member ) target; \
34                disable_global_interrupts(); \
35                target = kernelTLS.member; \
36                enable_global_interrupts(); \
37                target; } )
38        #define TL_SET( member, value ) disable_global_interrupts(); \
39                kernelTLS.member = value; \
40                enable_global_interrupts();
41#else
42        #define TL_GET( member ) kernelTLS.member
43        #define TL_SET( member, value ) kernelTLS.member = value;
44#endif
45
46        #ifdef __cforall
47        extern "Cforall" {
48                extern __attribute__((aligned(128))) thread_local struct KernelThreadData {
49                        struct thread_desc    * volatile this_thread;
50                        struct processor      * volatile this_processor;
51
52                        struct {
53                                volatile unsigned short disable_count;
54                                volatile bool enabled;
55                                volatile bool in_progress;
56                        } preemption_state;
57
58                        uint32_t rand_seed;
59                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
60        }
61        #endif
62
63        struct __stack_context_t {
64                void * SP;
65                void * FP;
66        };
67
68        // low adresses  :           +----------------------+ <- start of allocation
69        //                           |  optional guard page |
70        //                           +----------------------+ <- __stack_t.limit
71        //                           |                      |
72        //                           |       /\ /\ /\       |
73        //                           |       || || ||       |
74        //                           |                      |
75        //                           |    program  stack    |
76        //                           |                      |
77        // __stack_info_t.storage -> +----------------------+ <- __stack_t.base
78        //                           |      __stack_t       |
79        // high adresses :           +----------------------+ <- end of allocation
80
81        struct __stack_t {
82                // stack grows towards stack limit
83                void * limit;
84
85                // base of stack
86                void * base;
87        };
88
89        struct __stack_info_t {
90                // pointer to stack
91                struct __stack_t * storage;
92        };
93
94        enum coroutine_state { Halted, Start, Primed, Inactive, Active, Rerun, Reschedule };
95        enum __Preemption_Reason { __NO_PREEMPTION, __ALARM_PREEMPTION, __POLL_PREEMPTION };
96        enum __Owner_Reason { __NO_OWNER, __ENTER_FREE, __ENTER_ACCEPT, __ENTER_DTOR_FREE, __ENTER_DTOR_ACCEPT, __ENTER_SIGNAL_BLOCK, __WAITFOR, __LEAVE, __LEAVE_THREAD, __WAIT };
97
98        struct coroutine_desc {
99                // context that is switch during a CtxSwitch
100                struct __stack_context_t context;
101
102                // stack information of the coroutine
103                struct __stack_info_t stack;
104
105                // textual name for coroutine/task
106                const char * name;
107
108                // current execution status for coroutine
109                enum coroutine_state state;
110
111                // first coroutine to resume this one
112                struct coroutine_desc * starter;
113
114                // last coroutine to resume this one
115                struct coroutine_desc * last;
116
117                // If non-null stack must be unwound with this exception
118                struct _Unwind_Exception * cancellation;
119
120        };
121
122        // struct which calls the monitor is accepting
123        struct __waitfor_mask_t {
124                // the index of the accepted function, -1 if none
125                short * accepted;
126
127                // list of acceptable functions, null if any
128                __cfa_anonymous_object( __small_array_t(struct __acceptable_t) );
129        };
130
131        struct monitor_desc {
132                // spinlock to protect internal data
133                struct __spinlock_t lock;
134
135                // current owner of the monitor
136                struct thread_desc * owner;
137
138                enum __Owner_Reason owner_reason;
139
140                // queue of threads that are blocked waiting for the monitor
141                __queue_t(struct thread_desc) entry_queue;
142
143                // stack of conditions to run next once we exit the monitor
144                __stack_t(struct __condition_criterion_t) signal_stack;
145
146                // monitor routines can be called recursively, we need to keep track of that
147                unsigned int recursion;
148
149                // mask used to know if some thread is waiting for something while holding the monitor
150                struct __waitfor_mask_t mask;
151
152                // node used to signal the dtor in a waitfor dtor
153                struct __condition_node_t * dtor_node;
154        };
155
156        struct __monitor_group_t {
157                // currently held monitors
158                __cfa_anonymous_object( __small_array_t(monitor_desc*) );
159
160                // last function that acquired monitors
161                fptr_t func;
162        };
163
164        struct thread_desc {
165                // Core threading fields
166                // context that is switch during a CtxSwitch
167                struct __stack_context_t context;
168
169                // current execution status for coroutine
170                volatile int state;
171                enum __Preemption_Reason preempted;
172
173                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
174
175                // coroutine body used to store context
176                struct coroutine_desc  self_cor;
177
178                // current active context
179                struct coroutine_desc * curr_cor;
180
181                // monitor body used for mutual exclusion
182                struct monitor_desc    self_mon;
183
184                // pointer to monitor with sufficient lifetime for current monitors
185                struct monitor_desc *  self_mon_p;
186
187                // pointer to the cluster on which the thread is running
188                struct cluster * curr_cluster;
189
190                // monitors currently held by this thread
191                struct __monitor_group_t monitors;
192
193                // Link lists fields
194                // instrusive link field for threads
195                struct thread_desc * next;
196
197                struct {
198                        struct thread_desc * next;
199                        struct thread_desc * prev;
200                } node;
201        };
202
203        #ifdef __cforall
204        extern "Cforall" {
205                static inline thread_desc *& get_next( thread_desc & this ) {
206                        return this.next;
207                }
208
209                static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) {
210                        return this.node.[next, prev];
211                }
212
213                static inline void ?{}(__monitor_group_t & this) {
214                        (this.data){0p};
215                        (this.size){0};
216                        (this.func){NULL};
217                }
218
219                static inline void ?{}(__monitor_group_t & this, struct monitor_desc ** data, __lock_size_t size, fptr_t func) {
220                        (this.data){data};
221                        (this.size){size};
222                        (this.func){func};
223                }
224
225                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {
226                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
227                        if( lhs.size != rhs.size ) return false;
228                        if( lhs.func != rhs.func ) return false;
229
230                        // Check that all the monitors match
231                        for( int i = 0; i < lhs.size; i++ ) {
232                                // If not a match, check next function
233                                if( lhs[i] != rhs[i] ) return false;
234                        }
235
236                        return true;
237                }
238
239                static inline void ?=?(__monitor_group_t & lhs, const __monitor_group_t & rhs) {
240                        lhs.data = rhs.data;
241                        lhs.size = rhs.size;
242                        lhs.func = rhs.func;
243                }
244        }
245        #endif
246
247#endif //_INVOKE_H_
248#else //! defined(__CFA_INVOKE_PRIVATE__)
249#ifndef _INVOKE_PRIVATE_H_
250#define _INVOKE_PRIVATE_H_
251
252        struct machine_context_t {
253                void *SP;
254                void *FP;
255                void *PC;
256        };
257
258        // assembler routines that performs the context switch
259        extern void CtxInvokeStub( void );
260        extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
261        // void CtxStore ( void * this ) asm ("CtxStore");
262        // void CtxRet   ( void * dst  ) asm ("CtxRet");
263
264#endif //_INVOKE_PRIVATE_H_
265#endif //! defined(__CFA_INVOKE_PRIVATE__)
266#ifdef __cforall
267}
268#endif
269
270// Local Variables: //
271// mode: c //
272// tab-width: 4 //
273// End: //
Note: See TracBrowser for help on using the repository browser.