- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.hfa (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.hfa
r6d1790c r121be3e 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 12:29:26 202013 // Update Count : 2212 // Last Modified On : Wed Dec 4 07:54:51 2019 13 // Update Count : 18 14 14 // 15 15 16 16 #pragma once 17 18 #include <stdbool.h> 17 19 18 20 #include "invoke.h" … … 20 22 #include "coroutine.hfa" 21 23 22 #include "containers/list.hfa"23 24 24 extern "C" { 25 #include <bits/pthreadtypes.h>26 #include <linux/types.h>25 #include <pthread.h> 26 #include <semaphore.h> 27 27 } 28 28 … … 32 32 __spinlock_t lock; 33 33 int count; 34 __queue_t( $thread) waiting;34 __queue_t(thread_desc) waiting; 35 35 }; 36 36 37 37 void ?{}(semaphore & this, int count = 1); 38 38 void ^?{}(semaphore & this); 39 bool P (semaphore & this); 40 bool V (semaphore & this); 41 bool V (semaphore & this, unsigned count); 39 void P (semaphore & this); 40 void V (semaphore & this); 42 41 43 42 … … 46 45 extern struct cluster * mainCluster; 47 46 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 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 58 97 coroutine processorCtx_t { 59 98 struct processor * proc; … … 61 100 62 101 // Wrapper around kernel threads 63 struct __attribute__((aligned(128)))processor {102 struct processor { 64 103 // Main state 65 inline __processor_id_t; 104 // Coroutine ctx who does keeps the state of the processor 105 struct processorCtx_t runner; 66 106 67 107 // Cluster from which to get threads 68 108 struct cluster * cltr; 69 109 70 // Set to true to notify the processor should terminate71 volatile bool do_terminate;72 73 // Coroutine ctx who does keeps the state of the processor74 struct processorCtx_t runner;75 76 110 // Name of the processor 77 111 const char * name; … … 79 113 // Handle to pthreads 80 114 pthread_t kernel_thread; 115 116 // RunThread data 117 // Action to do after a thread is ran 118 struct FinishAction finish; 81 119 82 120 // Preemption data … … 87 125 bool pending_preemption; 88 126 89 // Idle lock (kernel semaphore) 90 __bin_sem_t idle; 91 92 // Termination synchronisation (user semaphore) 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 93 135 semaphore terminated; 94 136 … … 97 139 98 140 // Link lists fields 99 DLISTED_MGD_IMPL_IN(processor) 100 101 #if !defined(__CFA_NO_STATISTICS__) 102 int print_stats; 103 bool print_halts; 104 #endif 141 struct __dbg_node_proc { 142 struct processor * next; 143 struct processor * prev; 144 } node; 105 145 106 146 #ifdef __CFA_DEBUG__ … … 110 150 }; 111 151 112 void ?{}(processor & this, const char name[], struct cluster & cltr);152 void ?{}(processor & this, const char * name, struct cluster & cltr); 113 153 void ^?{}(processor & this); 114 154 115 155 static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } 116 156 static inline void ?{}(processor & this, struct cluster & cltr) { this{ "Anonymous Processor", cltr}; } 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 }; 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 } 220 162 221 163 //----------------------------------------------------------------------------- 222 164 // Cluster 223 struct __attribute__((aligned(128))) cluster { 165 struct cluster { 166 // Ready queue locks 167 __spinlock_t ready_queue_lock; 168 224 169 // Ready queue for threads 225 __ ready_queue_tready_queue;170 __queue_t(thread_desc) ready_queue; 226 171 227 172 // Name of the cluster … … 231 176 Duration preemption_rate; 232 177 233 // List of idle processors 234 __cluster_idles idles; 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; 235 183 236 184 // List of threads 237 185 __spinlock_t thread_list_lock; 238 __dllist_t(struct $thread) threads;186 __dllist_t(struct thread_desc) threads; 239 187 unsigned int nthreads; 240 188 … … 244 192 cluster * prev; 245 193 } 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 #endif256 194 }; 257 195 extern Duration default_preemption(); 258 196 259 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params);197 void ?{} (cluster & this, const char * name, Duration preemption_rate); 260 198 void ^?{}(cluster & this); 261 199 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 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; } 293 210 294 211 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.