- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.hfa (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.hfa
r1eb239e4 r71c8b7e 16 16 #pragma once 17 17 18 #include <stdbool.h> 19 #include <stdint.h> 20 18 21 #include "invoke.h" 19 22 #include "time_t.hfa" 20 23 #include "coroutine.hfa" 21 24 22 #include "containers/list.hfa"23 24 25 extern "C" { 25 #include <bits/pthreadtypes.h> 26 #include <pthread.h> 27 #include <semaphore.h> 26 28 } 27 29 … … 45 47 extern struct cluster * mainCluster; 46 48 47 // Processor id, required for scheduling threads 48 struct __processor_id_t { 49 unsigned id; 50 51 #if !defined(__CFA_NO_STATISTICS__) 52 struct __stats_t * stats; 53 #endif 54 }; 55 49 // Processor 56 50 coroutine processorCtx_t { 57 51 struct processor * proc; … … 59 53 60 54 // Wrapper around kernel threads 61 struct __attribute__((aligned(128)))processor {55 struct processor { 62 56 // Main state 63 inline __processor_id_t; 57 // Coroutine ctx who does keeps the state of the processor 58 struct processorCtx_t runner; 64 59 65 60 // Cluster from which to get threads 66 61 struct cluster * cltr; 67 68 // Set to true to notify the processor should terminate69 volatile bool do_terminate;70 71 // Coroutine ctx who does keeps the state of the processor72 struct processorCtx_t runner;73 62 74 63 // Name of the processor … … 92 81 __bin_sem_t idle; 93 82 83 // Termination 84 // Set to true to notify the processor should terminate 85 volatile bool do_terminate; 86 94 87 // Termination synchronisation (user semaphore) 95 88 semaphore terminated; … … 99 92 100 93 // Link lists fields 101 DLISTED_MGD_IMPL_IN(processor) 102 103 #if !defined(__CFA_NO_STATISTICS__) 104 int print_stats; 105 bool print_halts; 106 #endif 94 struct __dbg_node_proc { 95 struct processor * next; 96 struct processor * prev; 97 } node; 107 98 108 99 #ifdef __CFA_DEBUG__ … … 119 110 static inline void ?{}(processor & this, const char name[]) { this{name, *mainCluster }; } 120 111 121 DLISTED_MGD_IMPL_OUT(processor) 112 static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; } 122 113 123 114 //----------------------------------------------------------------------------- … … 125 116 struct __io_data; 126 117 127 // IO poller user-thread 128 // Not using the "thread" keyword because we want to control 129 // more carefully when to start/stop it 130 struct $io_ctx_thread { 131 struct __io_data * ring; 132 single_sem sem; 133 volatile bool done; 134 $thread self; 135 }; 136 137 138 struct io_context { 139 $io_ctx_thread thrd; 140 }; 141 142 struct io_context_params { 143 int num_entries; 144 int num_ready; 145 int submit_aff; 146 bool eager_submits:1; 147 bool poller_submits:1; 148 bool poll_submit:1; 149 bool poll_complete:1; 150 }; 151 152 void ?{}(io_context_params & this); 153 154 void ?{}(io_context & this, struct cluster & cl); 155 void ?{}(io_context & this, struct cluster & cl, const io_context_params & params); 156 void ^?{}(io_context & this); 157 158 struct io_cancellation { 159 uint32_t target; 160 }; 161 162 static inline void ?{}(io_cancellation & this) { this.target = -1u; } 163 static inline void ^?{}(io_cancellation & this) {} 164 bool cancel(io_cancellation & this); 165 166 //----------------------------------------------------------------------------- 167 // Cluster Tools 168 169 // Intrusives lanes which are used by the relaxed ready queue 170 struct __attribute__((aligned(128))) __intrusive_lane_t; 171 void ?{}(__intrusive_lane_t & this); 172 void ^?{}(__intrusive_lane_t & this); 173 174 // Counter used for wether or not the lanes are all empty 175 struct __attribute__((aligned(128))) __snzi_node_t; 176 struct __snzi_t { 177 unsigned mask; 178 int root; 179 __snzi_node_t * nodes; 180 }; 181 182 void ?{}( __snzi_t & this, unsigned depth ); 183 void ^?{}( __snzi_t & this ); 184 185 //TODO adjust cache size to ARCHITECTURE 186 // Structure holding the relaxed ready queue 187 struct __ready_queue_t { 188 // Data tracking how many/which lanes are used 189 // Aligned to 128 for cache locality 190 __snzi_t snzi; 191 192 // Data tracking the actual lanes 193 // On a seperate cacheline from the used struct since 194 // used can change on each push/pop but this data 195 // only changes on shrink/grow 196 struct { 197 // Arary of lanes 198 __intrusive_lane_t * volatile data; 199 200 // Number of lanes (empty or not) 201 volatile size_t count; 202 } lanes; 203 }; 204 205 void ?{}(__ready_queue_t & this); 206 void ^?{}(__ready_queue_t & this); 207 208 // Idle Sleep 209 struct __cluster_idles { 210 // Spin lock protecting the queue 211 volatile uint64_t lock; 212 213 // Total number of processors 214 unsigned total; 215 216 // Total number of idle processors 217 unsigned idle; 218 219 // List of idle processors 220 dlist(processor, processor) list; 221 }; 118 #define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0 119 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 222 120 223 121 //----------------------------------------------------------------------------- 224 122 // Cluster 225 struct __attribute__((aligned(128))) cluster { 123 struct cluster { 124 // Ready queue locks 125 __spinlock_t ready_queue_lock; 126 226 127 // Ready queue for threads 227 __ ready_queue_tready_queue;128 __queue_t($thread) ready_queue; 228 129 229 130 // Name of the cluster … … 233 134 Duration preemption_rate; 234 135 235 // List of idle processors 236 __cluster_idles idles; 136 // List of processors 137 __spinlock_t idle_lock; 138 __dllist_t(struct processor) procs; 139 __dllist_t(struct processor) idles; 140 unsigned int nprocessors; 237 141 238 142 // List of threads … … 247 151 } node; 248 152 249 struct { 250 io_context * ctxs; 251 unsigned cnt; 252 } io; 153 struct __io_data * io; 253 154 254 155 #if !defined(__CFA_NO_STATISTICS__) 255 struct __stats_t * stats; 256 int print_stats; 156 bool print_stats; 257 157 #endif 258 158 }; 259 159 extern Duration default_preemption(); 260 160 261 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params);161 void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags); 262 162 void ^?{}(cluster & this); 263 163 264 static inline void ?{} (cluster & this) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), 1, default_params}; } 265 static inline void ?{} (cluster & this, Duration preemption_rate) { io_context_params default_params; this{"Anonymous Cluster", preemption_rate, 1, default_params}; } 266 static inline void ?{} (cluster & this, const char name[]) { io_context_params default_params; this{name, default_preemption(), 1, default_params}; } 267 static inline void ?{} (cluster & this, unsigned num_io) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), num_io, default_params}; } 268 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}; } 269 static inline void ?{} (cluster & this, const char name[], unsigned num_io) { io_context_params default_params; this{name, default_preemption(), num_io, default_params}; } 270 static inline void ?{} (cluster & this, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), 1, io_params}; } 271 static inline void ?{} (cluster & this, Duration preemption_rate, const io_context_params & io_params) { this{"Anonymous Cluster", preemption_rate, 1, io_params}; } 272 static inline void ?{} (cluster & this, const char name[], const io_context_params & io_params) { this{name, default_preemption(), 1, io_params}; } 273 static inline void ?{} (cluster & this, unsigned num_io, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), num_io, io_params}; } 274 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}; } 275 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}; } 164 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption(), 0}; } 165 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate, 0}; } 166 static inline void ?{} (cluster & this, const char name[]) { this{name, default_preemption(), 0}; } 167 static inline void ?{} (cluster & this, int flags) { this{"Anonymous Cluster", default_preemption(), flags}; } 168 static inline void ?{} (cluster & this, Duration preemption_rate, int flags) { this{"Anonymous Cluster", preemption_rate, flags}; } 169 static inline void ?{} (cluster & this, const char name[], int flags) { this{name, default_preemption(), flags}; } 276 170 277 171 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } … … 281 175 282 176 #if !defined(__CFA_NO_STATISTICS__) 283 static inline void print_stats_at_exit( cluster & this , int flags) {284 this.print_stats |= flags;177 static inline void print_stats_at_exit( cluster & this ) { 178 this.print_stats = true; 285 179 } 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 180 #endif 293 181
Note:
See TracChangeset
for help on using the changeset viewer.