- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.hfa (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.hfa
re3fea42 rdca5802 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 … … 107 107 // Cluster from which to get threads 108 108 struct cluster * cltr; 109 unsigned int id; 109 110 110 111 // Name of the processor … … 150 151 }; 151 152 152 void ?{}(processor & this, const char name[], struct cluster & cltr);153 void ?{}(processor & this, const char * name, struct cluster & cltr); 153 154 void ^?{}(processor & this); 154 155 155 156 static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } 156 157 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 static inline void ?{}(processor & this, const char * name) { this{name, *mainCluster }; } 158 159 159 160 static inline [processor *&, processor *& ] __get( processor & this ) { 160 161 return this.node.[next, prev]; 161 162 } 163 164 165 //----------------------------------------------------------------------------- 166 // Cluster Tools 167 168 // Cells use by the reader writer lock 169 // while not generic it only relies on a opaque pointer 170 struct __processor_id; 171 172 // Reader-Writer lock protecting the ready-queue 173 // while this lock is mostly generic some aspects 174 // have been hard-coded to for the ready-queue for 175 // simplicity and performance 176 struct __clusterRWLock_t { 177 // total cachelines allocated 178 unsigned int max; 179 180 // cachelines currently in use 181 volatile unsigned int alloc; 182 183 // cachelines ready to itereate over 184 // (!= to alloc when thread is in second half of doregister) 185 volatile unsigned int ready; 186 187 // writer lock 188 volatile bool lock; 189 190 // data pointer 191 __processor_id * data; 192 }; 193 194 void ?{}(__clusterRWLock_t & this); 195 void ^?{}(__clusterRWLock_t & this); 196 197 // Intrusives lanes which are used by the relaxed ready queue 198 struct __attribute__((aligned(128))) __intrusive_lane_t { 199 // spin lock protecting the queue 200 volatile bool lock; 201 202 // anchor for the head and the tail of the queue 203 struct __sentinel_t { 204 // Link lists fields 205 // instrusive link field for threads 206 // must be exactly as in thread_desc 207 __thread_desc_link link; 208 } before, after; 209 210 #if defined(__CFA_WITH_VERIFY__) 211 // id of last processor to acquire the lock 212 // needed only to check for mutual exclusion violations 213 unsigned int last_id; 214 215 // number of items on this list 216 // needed only to check for deadlocks 217 unsigned int count; 218 #endif 219 220 // Optional statistic counters 221 #if !defined(__CFA_NO_SCHED_STATS__) 222 struct __attribute__((aligned(64))) { 223 // difference between number of push and pops 224 ssize_t diff; 225 226 // total number of pushes and pops 227 size_t push; 228 size_t pop ; 229 } stat; 230 #endif 231 }; 232 233 void ?{}(__intrusive_lane_t & this); 234 void ^?{}(__intrusive_lane_t & this); 235 236 typedef unsigned long long __cfa_readyQ_mask_t; 237 238 // enum { 239 // __cfa_ready_queue_mask_size = (64 - sizeof(size_t)) / sizeof(size_t), 240 // __cfa_max_ready_queues = __cfa_ready_queue_mask_size * 8 * sizeof(size_t) 241 // }; 242 243 #define __cfa_lane_mask_size ((64 - sizeof(size_t)) / sizeof(__cfa_readyQ_mask_t)) 244 #define __cfa_max_lanes (__cfa_lane_mask_size * 8 * sizeof(__cfa_readyQ_mask_t)) 245 246 //TODO adjust cache size to ARCHITECTURE 247 // Structure holding the relaxed ready queue 248 struct __attribute__((aligned(128))) __ready_queue_t { 249 // Data tracking how many/which lanes are used 250 // Aligned to 128 for cache locality 251 struct { 252 // number of non-empty lanes 253 volatile size_t count; 254 255 // bit mask, set bits indentify which lanes are non-empty 256 volatile __cfa_readyQ_mask_t mask[ __cfa_lane_mask_size ]; 257 } used; 258 259 // Data tracking the actual lanes 260 // On a seperate cacheline from the used struct since 261 // used can change on each push/pop but this data 262 // only changes on shrink/grow 263 struct __attribute__((aligned(64))) { 264 // Arary of lanes 265 __intrusive_lane_t * volatile data; 266 267 // Number of lanes (empty or not) 268 volatile size_t count; 269 } lanes; 270 271 // Statistics 272 #if !defined(__CFA_NO_STATISTICS__) 273 __attribute__((aligned(64))) struct { 274 struct { 275 // Push statistic 276 struct { 277 // number of attemps at pushing something 278 volatile size_t attempt; 279 280 // number of successes at pushing 281 volatile size_t success; 282 } push; 283 284 // Pop statistic 285 struct { 286 // number of reads of the mask 287 // picking an empty __cfa_readyQ_mask_t counts here 288 // but not as an attempt 289 volatile size_t maskrds; 290 291 // number of attemps at poping something 292 volatile size_t attempt; 293 294 // number of successes at poping 295 volatile size_t success; 296 } pop; 297 } pick; 298 299 // stats on the "used" struct of the queue 300 // tracks average number of queues that are not empty 301 // when pushing / poping 302 struct { 303 volatile size_t value; 304 volatile size_t count; 305 } used; 306 } global_stats; 307 308 #endif 309 }; 310 311 void ?{}(__ready_queue_t & this); 312 void ^?{}(__ready_queue_t & this); 162 313 163 314 //----------------------------------------------------------------------------- … … 165 316 struct cluster { 166 317 // Ready queue locks 167 __ spinlock_t ready_queue_lock;318 __clusterRWLock_t ready_lock; 168 319 169 320 // Ready queue for threads 170 __ queue_t(thread_desc)ready_queue;321 __ready_queue_t ready_queue; 171 322 172 323 // Name of the cluster … … 178 329 // List of processors 179 330 __spinlock_t proc_list_lock; 180 __dllist_t(struct processor) procs;181 331 __dllist_t(struct processor) idles; 182 unsigned int nprocessors;183 332 184 333 // List of threads … … 195 344 extern Duration default_preemption(); 196 345 197 void ?{} (cluster & this, const char name[], Duration preemption_rate);346 void ?{} (cluster & this, const char * name, Duration preemption_rate); 198 347 void ^?{}(cluster & this); 199 348 200 349 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } 201 350 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()}; }351 static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; } 203 352 204 353 static inline [cluster *&, cluster *& ] __get( cluster & this ) {
Note:
See TracChangeset
for help on using the changeset viewer.