Ignore:
File:
1 edited

Legend:

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

    rdca5802 re3fea42  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec  4 07:54:51 2019
    13 // Update Count     : 18
     12// Last Modified On : Tue Feb  4 12:29:26 2020
     13// Update Count     : 22
    1414//
    1515
     
    107107        // Cluster from which to get threads
    108108        struct cluster * cltr;
    109         unsigned int id;
    110109
    111110        // Name of the processor
     
    151150};
    152151
    153 void  ?{}(processor & this, const char * name, struct cluster & cltr);
     152void  ?{}(processor & this, const char name[], struct cluster & cltr);
    154153void ^?{}(processor & this);
    155154
    156155static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    157156static inline void  ?{}(processor & this, struct cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    158 static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
     157static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
    159158
    160159static inline [processor *&, processor *& ] __get( processor & this ) {
    161160        return this.node.[next, prev];
    162161}
    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);
    313162
    314163//-----------------------------------------------------------------------------
     
    316165struct cluster {
    317166        // Ready queue locks
    318         __clusterRWLock_t ready_lock;
     167        __spinlock_t ready_queue_lock;
    319168
    320169        // Ready queue for threads
    321         __ready_queue_t ready_queue;
     170        __queue_t(thread_desc) ready_queue;
    322171
    323172        // Name of the cluster
     
    329178        // List of processors
    330179        __spinlock_t proc_list_lock;
     180        __dllist_t(struct processor) procs;
    331181        __dllist_t(struct processor) idles;
     182        unsigned int nprocessors;
    332183
    333184        // List of threads
     
    344195extern Duration default_preemption();
    345196
    346 void ?{} (cluster & this, const char * name, Duration preemption_rate);
     197void ?{} (cluster & this, const char name[], Duration preemption_rate);
    347198void ^?{}(cluster & this);
    348199
    349200static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    350201static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
    351 static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
     202static inline void ?{} (cluster & this, const char name[])        { this{name, default_preemption()}; }
    352203
    353204static inline [cluster *&, cluster *& ] __get( cluster & this ) {
Note: See TracChangeset for help on using the changeset viewer.