Changeset 58fe85a for libcfa/src/concurrency/kernel.hfa
- Timestamp:
- Jan 7, 2021, 3:27:00 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:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (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
r3c64c668 r58fe85a 16 16 #pragma once 17 17 18 #include <stdbool.h>19 20 18 #include "invoke.h" 21 19 #include "time_t.hfa" 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 … … 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 // 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 48 58 coroutine processorCtx_t { 49 59 struct processor * proc; … … 51 61 52 62 // Wrapper around kernel threads 53 struct processor {63 struct __attribute__((aligned(128))) processor { 54 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 55 73 // Coroutine ctx who does keeps the state of the processor 56 74 struct processorCtx_t runner; 57 75 58 // Cluster from which to get threads59 struct cluster * cltr;60 61 76 // Name of the processor 62 77 const char * name; … … 64 79 // Handle to pthreads 65 80 pthread_t kernel_thread; 66 67 // RunThread data68 // Action to do after a thread is ran69 $thread * destroyer;70 81 71 82 // Preemption data … … 76 87 bool pending_preemption; 77 88 78 // Idle lock 79 __bin_sem_t idleLock; 80 81 // Termination 82 // Set to true to notify the processor should terminate 83 volatile bool do_terminate; 84 85 // Termination synchronisation 89 // Idle lock (kernel semaphore) 90 __bin_sem_t idle; 91 92 // Termination synchronisation (user semaphore) 86 93 semaphore terminated; 87 94 … … 90 97 91 98 // Link lists fields 92 struct __dbg_node_proc { 93 struct processor * next; 94 struct processor * prev; 95 } node; 99 DLISTED_MGD_IMPL_IN(processor) 100 101 #if !defined(__CFA_NO_STATISTICS__) 102 int print_stats; 103 bool print_halts; 104 #endif 96 105 97 106 #ifdef __CFA_DEBUG__ … … 108 117 static inline void ?{}(processor & this, const char name[]) { this{name, *mainCluster }; } 109 118 110 static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; } 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 }; 111 220 112 221 //----------------------------------------------------------------------------- 113 222 // Cluster 114 struct cluster { 115 // Ready queue locks 116 __spinlock_t ready_queue_lock; 117 223 struct __attribute__((aligned(128))) cluster { 118 224 // Ready queue for threads 119 __ queue_t($thread)ready_queue;225 __ready_queue_t ready_queue; 120 226 121 227 // Name of the cluster … … 125 231 Duration preemption_rate; 126 232 127 // List of processors 128 __spinlock_t proc_list_lock; 129 __dllist_t(struct processor) procs; 130 __dllist_t(struct processor) idles; 131 unsigned int nprocessors; 233 // List of idle processors 234 __cluster_idles idles; 132 235 133 236 // List of threads … … 141 244 cluster * prev; 142 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 143 256 }; 144 257 extern Duration default_preemption(); 145 258 146 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); 147 260 void ^?{}(cluster & this); 148 261 149 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } 150 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; } 151 static inline void ?{} (cluster & this, const char name[]) { this{name, default_preemption()}; } 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}; } 152 274 153 275 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } 154 276 155 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE 156 static inline struct cluster * active_cluster () { return TL_GET( this_processor )->cltr; } 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 157 293 158 294 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.