Changeset eef8dfb for libcfa/src/concurrency/kernel.hfa
- Timestamp:
- Jan 7, 2021, 2:55:57 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 58fe85a
- Parents:
- bdfc032 (diff), 44e37ef (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.hfa
rbdfc032 reef8dfb 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 4 07:54:51 201913 // Update Count : 1812 // Last Modified On : Tue Feb 4 12:29:26 2020 13 // Update Count : 22 14 14 // 15 15 16 16 #pragma once 17 18 #include <stdbool.h>19 17 20 18 #include "invoke.h" … … 22 20 #include "coroutine.hfa" 23 21 22 #include "containers/list.hfa" 23 24 24 extern "C" { 25 #include <pthread.h>26 #include <semaphore.h>25 #include <bits/pthreadtypes.h> 26 #include <linux/types.h> 27 27 } 28 28 … … 32 32 __spinlock_t lock; 33 33 int count; 34 __queue_t( thread_desc) waiting;34 __queue_t($thread) waiting; 35 35 }; 36 36 37 37 void ?{}(semaphore & this, int count = 1); 38 38 void ^?{}(semaphore & this); 39 void P (semaphore & this); 40 void V (semaphore & this); 39 bool P (semaphore & this); 40 bool V (semaphore & this); 41 bool V (semaphore & this, unsigned count); 41 42 42 43 … … 45 46 extern struct cluster * mainCluster; 46 47 47 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback }; 48 49 typedef void (*__finish_callback_fptr_t)(void); 50 51 //TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI) 52 struct FinishAction { 53 FinishOpCode action_code; 54 /* 55 // Union of possible actions 56 union { 57 // Option 1 : locks and threads 58 struct { 59 // 1 thread or N thread 60 union { 61 thread_desc * thrd; 62 struct { 63 thread_desc ** thrds; 64 unsigned short thrd_count; 65 }; 66 }; 67 // 1 lock or N lock 68 union { 69 __spinlock_t * lock; 70 struct { 71 __spinlock_t ** locks; 72 unsigned short lock_count; 73 }; 74 }; 75 }; 76 // Option 2 : action pointer 77 __finish_callback_fptr_t callback; 78 }; 79 /*/ 80 thread_desc * thrd; 81 thread_desc ** thrds; 82 unsigned short thrd_count; 83 __spinlock_t * lock; 84 __spinlock_t ** locks; 85 unsigned short lock_count; 86 __finish_callback_fptr_t callback; 87 //*/ 88 }; 89 static inline void ?{}(FinishAction & this) { 90 this.action_code = No_Action; 91 this.thrd = 0p; 92 this.lock = 0p; 93 } 94 static inline void ^?{}(FinishAction &) {} 95 96 // Processor 48 // Processor id, required for scheduling threads 49 struct __processor_id_t { 50 unsigned id:24; 51 bool full_proc:1; 52 53 #if !defined(__CFA_NO_STATISTICS__) 54 struct __stats_t * stats; 55 #endif 56 }; 57 97 58 coroutine processorCtx_t { 98 59 struct processor * proc; … … 100 61 101 62 // Wrapper around kernel threads 102 struct processor {63 struct __attribute__((aligned(128))) processor { 103 64 // Main state 65 inline __processor_id_t; 66 67 // Cluster from which to get threads 68 struct cluster * cltr; 69 70 // Set to true to notify the processor should terminate 71 volatile bool do_terminate; 72 104 73 // Coroutine ctx who does keeps the state of the processor 105 74 struct processorCtx_t runner; 106 75 107 // Cluster from which to get threads108 struct cluster * cltr;109 110 76 // Name of the processor 111 77 const char * name; … … 113 79 // Handle to pthreads 114 80 pthread_t kernel_thread; 115 116 // RunThread data117 // Action to do after a thread is ran118 struct FinishAction finish;119 81 120 82 // Preemption data … … 125 87 bool pending_preemption; 126 88 127 // Idle lock 128 __bin_sem_t idleLock; 129 130 // Termination 131 // Set to true to notify the processor should terminate 132 volatile bool do_terminate; 133 134 // Termination synchronisation 89 // Idle lock (kernel semaphore) 90 __bin_sem_t idle; 91 92 // Termination synchronisation (user semaphore) 135 93 semaphore terminated; 136 94 … … 139 97 140 98 // Link lists fields 141 struct __dbg_node_proc { 142 struct processor * next; 143 struct processor * prev; 144 } node; 99 DLISTED_MGD_IMPL_IN(processor) 100 101 #if !defined(__CFA_NO_STATISTICS__) 102 int print_stats; 103 bool print_halts; 104 #endif 145 105 146 106 #ifdef __CFA_DEBUG__ … … 150 110 }; 151 111 152 void ?{}(processor & this, const char * name, struct cluster & cltr);112 void ?{}(processor & this, const char name[], struct cluster & cltr); 153 113 void ^?{}(processor & this); 154 114 155 115 static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } 156 116 static inline void ?{}(processor & this, struct cluster & cltr) { this{ "Anonymous Processor", cltr}; } 157 static inline void ?{}(processor & this, const char * name) { this{name, *mainCluster }; } 158 159 static inline [processor *&, processor *& ] __get( processor & this ) { 160 return this.node.[next, prev]; 161 } 117 static inline void ?{}(processor & this, const char name[]) { this{name, *mainCluster }; } 118 119 DLISTED_MGD_IMPL_OUT(processor) 120 121 //----------------------------------------------------------------------------- 122 // I/O 123 struct __io_data; 124 125 // IO poller user-thread 126 // Not using the "thread" keyword because we want to control 127 // more carefully when to start/stop it 128 struct $io_ctx_thread { 129 struct __io_data * ring; 130 single_sem sem; 131 volatile bool done; 132 $thread self; 133 }; 134 135 136 struct io_context { 137 $io_ctx_thread thrd; 138 }; 139 140 struct io_context_params { 141 int num_entries; 142 int num_ready; 143 int submit_aff; 144 bool eager_submits:1; 145 bool poller_submits:1; 146 bool poll_submit:1; 147 bool poll_complete:1; 148 }; 149 150 void ?{}(io_context_params & this); 151 152 void ?{}(io_context & this, struct cluster & cl); 153 void ?{}(io_context & this, struct cluster & cl, const io_context_params & params); 154 void ^?{}(io_context & this); 155 156 struct io_cancellation { 157 __u64 target; 158 }; 159 160 static inline void ?{}(io_cancellation & this) { this.target = -1u; } 161 static inline void ^?{}(io_cancellation &) {} 162 bool cancel(io_cancellation & this); 163 164 //----------------------------------------------------------------------------- 165 // Cluster Tools 166 167 // Intrusives lanes which are used by the relaxed ready queue 168 struct __attribute__((aligned(128))) __intrusive_lane_t; 169 void ?{}(__intrusive_lane_t & this); 170 void ^?{}(__intrusive_lane_t & this); 171 172 // Counter used for wether or not the lanes are all empty 173 struct __attribute__((aligned(128))) __snzi_node_t; 174 struct __snzi_t { 175 unsigned mask; 176 int root; 177 __snzi_node_t * nodes; 178 }; 179 180 void ?{}( __snzi_t & this, unsigned depth ); 181 void ^?{}( __snzi_t & this ); 182 183 //TODO adjust cache size to ARCHITECTURE 184 // Structure holding the relaxed ready queue 185 struct __ready_queue_t { 186 // Data tracking how many/which lanes are used 187 // Aligned to 128 for cache locality 188 __snzi_t snzi; 189 190 // Data tracking the actual lanes 191 // On a seperate cacheline from the used struct since 192 // used can change on each push/pop but this data 193 // only changes on shrink/grow 194 struct { 195 // Arary of lanes 196 __intrusive_lane_t * volatile data; 197 198 // Number of lanes (empty or not) 199 volatile size_t count; 200 } lanes; 201 }; 202 203 void ?{}(__ready_queue_t & this); 204 void ^?{}(__ready_queue_t & this); 205 206 // Idle Sleep 207 struct __cluster_idles { 208 // Spin lock protecting the queue 209 volatile uint64_t lock; 210 211 // Total number of processors 212 unsigned total; 213 214 // Total number of idle processors 215 unsigned idle; 216 217 // List of idle processors 218 dlist(processor, processor) list; 219 }; 162 220 163 221 //----------------------------------------------------------------------------- 164 222 // Cluster 165 struct cluster { 166 // Ready queue locks 167 __spinlock_t ready_queue_lock; 168 223 struct __attribute__((aligned(128))) cluster { 169 224 // Ready queue for threads 170 __ queue_t(thread_desc)ready_queue;225 __ready_queue_t ready_queue; 171 226 172 227 // Name of the cluster … … 176 231 Duration preemption_rate; 177 232 178 // List of processors 179 __spinlock_t proc_list_lock; 180 __dllist_t(struct processor) procs; 181 __dllist_t(struct processor) idles; 182 unsigned int nprocessors; 233 // List of idle processors 234 __cluster_idles idles; 183 235 184 236 // List of threads 185 237 __spinlock_t thread_list_lock; 186 __dllist_t(struct thread_desc) threads;238 __dllist_t(struct $thread) threads; 187 239 unsigned int nthreads; 188 240 … … 192 244 cluster * prev; 193 245 } node; 246 247 struct { 248 io_context * ctxs; 249 unsigned cnt; 250 } io; 251 252 #if !defined(__CFA_NO_STATISTICS__) 253 struct __stats_t * stats; 254 int print_stats; 255 #endif 194 256 }; 195 257 extern Duration default_preemption(); 196 258 197 void ?{} (cluster & this, const char * name, Duration preemption_rate);259 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params); 198 260 void ^?{}(cluster & this); 199 261 200 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } 201 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; } 202 static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; } 203 204 static inline [cluster *&, cluster *& ] __get( cluster & this ) { 205 return this.node.[next, prev]; 206 } 207 208 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE 209 static inline struct cluster * active_cluster () { return TL_GET( this_processor )->cltr; } 262 static inline void ?{} (cluster & this) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), 1, default_params}; } 263 static inline void ?{} (cluster & this, Duration preemption_rate) { io_context_params default_params; this{"Anonymous Cluster", preemption_rate, 1, default_params}; } 264 static inline void ?{} (cluster & this, const char name[]) { io_context_params default_params; this{name, default_preemption(), 1, default_params}; } 265 static inline void ?{} (cluster & this, unsigned num_io) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), num_io, default_params}; } 266 static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io) { io_context_params default_params; this{"Anonymous Cluster", preemption_rate, num_io, default_params}; } 267 static inline void ?{} (cluster & this, const char name[], unsigned num_io) { io_context_params default_params; this{name, default_preemption(), num_io, default_params}; } 268 static inline void ?{} (cluster & this, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), 1, io_params}; } 269 static inline void ?{} (cluster & this, Duration preemption_rate, const io_context_params & io_params) { this{"Anonymous Cluster", preemption_rate, 1, io_params}; } 270 static inline void ?{} (cluster & this, const char name[], const io_context_params & io_params) { this{name, default_preemption(), 1, io_params}; } 271 static inline void ?{} (cluster & this, unsigned num_io, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), num_io, io_params}; } 272 static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io, const io_context_params & io_params) { this{"Anonymous Cluster", preemption_rate, num_io, io_params}; } 273 static inline void ?{} (cluster & this, const char name[], unsigned num_io, const io_context_params & io_params) { this{name, default_preemption(), num_io, io_params}; } 274 275 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } 276 277 static inline struct processor * active_processor() { return publicTLS_get( this_processor ); } // UNSAFE 278 static inline struct cluster * active_cluster () { return publicTLS_get( this_processor )->cltr; } 279 280 #if !defined(__CFA_NO_STATISTICS__) 281 void print_stats_now( cluster & this, int flags ); 282 283 static inline void print_stats_at_exit( cluster & this, int flags ) { 284 this.print_stats |= flags; 285 } 286 287 static inline void print_stats_at_exit( processor & this, int flags ) { 288 this.print_stats |= flags; 289 } 290 291 void print_halts( processor & this ); 292 #endif 210 293 211 294 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.