Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel.hfa

    re3fea42 rdca5802  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 12:29:26 2020
    13 // Update Count     : 22
     12// Last Modified On : Wed Dec  4 07:54:51 2019
     13// Update Count     : 18
    1414//
    1515
     
    107107        // Cluster from which to get threads
    108108        struct cluster * cltr;
     109        unsigned int id;
    109110
    110111        // Name of the processor
     
    150151};
    151152
    152 void  ?{}(processor & this, const char name[], struct cluster & cltr);
     153void  ?{}(processor & this, const char * name, struct cluster & cltr);
    153154void ^?{}(processor & this);
    154155
    155156static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    156157static inline void  ?{}(processor & this, struct cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    157 static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
     158static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
    158159
    159160static inline [processor *&, processor *& ] __get( processor & this ) {
    160161        return this.node.[next, prev];
    161162}
     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
     170struct __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
     176struct __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
     194void  ?{}(__clusterRWLock_t & this);
     195void ^?{}(__clusterRWLock_t & this);
     196
     197// Intrusives lanes which are used by the relaxed ready queue
     198struct __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
     233void  ?{}(__intrusive_lane_t & this);
     234void ^?{}(__intrusive_lane_t & this);
     235
     236typedef 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
     248struct __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
     311void  ?{}(__ready_queue_t & this);
     312void ^?{}(__ready_queue_t & this);
    162313
    163314//-----------------------------------------------------------------------------
     
    165316struct cluster {
    166317        // Ready queue locks
    167         __spinlock_t ready_queue_lock;
     318        __clusterRWLock_t ready_lock;
    168319
    169320        // Ready queue for threads
    170         __queue_t(thread_desc) ready_queue;
     321        __ready_queue_t ready_queue;
    171322
    172323        // Name of the cluster
     
    178329        // List of processors
    179330        __spinlock_t proc_list_lock;
    180         __dllist_t(struct processor) procs;
    181331        __dllist_t(struct processor) idles;
    182         unsigned int nprocessors;
    183332
    184333        // List of threads
     
    195344extern Duration default_preemption();
    196345
    197 void ?{} (cluster & this, const char name[], Duration preemption_rate);
     346void ?{} (cluster & this, const char * name, Duration preemption_rate);
    198347void ^?{}(cluster & this);
    199348
    200349static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    201350static 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()}; }
     351static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
    203352
    204353static inline [cluster *&, cluster *& ] __get( cluster & this ) {
Note: See TracChangeset for help on using the changeset viewer.