Ignore:
File:
1 edited

Legend:

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

    r1eb239e4 r71c8b7e  
    1616#pragma once
    1717
     18#include <stdbool.h>
     19#include <stdint.h>
     20
    1821#include "invoke.h"
    1922#include "time_t.hfa"
    2023#include "coroutine.hfa"
    2124
    22 #include "containers/list.hfa"
    23 
    2425extern "C" {
    25 #include <bits/pthreadtypes.h>
     26#include <pthread.h>
     27#include <semaphore.h>
    2628}
    2729
     
    4547extern struct cluster * mainCluster;
    4648
    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
    5650coroutine processorCtx_t {
    5751        struct processor * proc;
     
    5953
    6054// Wrapper around kernel threads
    61 struct __attribute__((aligned(128))) processor {
     55struct processor {
    6256        // Main state
    63         inline __processor_id_t;
     57        // Coroutine ctx who does keeps the state of the processor
     58        struct processorCtx_t runner;
    6459
    6560        // Cluster from which to get threads
    6661        struct cluster * cltr;
    67 
    68         // Set to true to notify the processor should terminate
    69         volatile bool do_terminate;
    70 
    71         // Coroutine ctx who does keeps the state of the processor
    72         struct processorCtx_t runner;
    7362
    7463        // Name of the processor
     
    9281        __bin_sem_t idle;
    9382
     83        // Termination
     84        // Set to true to notify the processor should terminate
     85        volatile bool do_terminate;
     86
    9487        // Termination synchronisation (user semaphore)
    9588        semaphore terminated;
     
    9992
    10093        // 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;
    10798
    10899#ifdef __CFA_DEBUG__
     
    119110static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
    120111
    121 DLISTED_MGD_IMPL_OUT(processor)
     112static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; }
    122113
    123114//-----------------------------------------------------------------------------
     
    125116struct __io_data;
    126117
    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
    222120
    223121//-----------------------------------------------------------------------------
    224122// Cluster
    225 struct __attribute__((aligned(128))) cluster {
     123struct cluster {
     124        // Ready queue locks
     125        __spinlock_t ready_queue_lock;
     126
    226127        // Ready queue for threads
    227         __ready_queue_t ready_queue;
     128        __queue_t($thread) ready_queue;
    228129
    229130        // Name of the cluster
     
    233134        Duration preemption_rate;
    234135
    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;
    237141
    238142        // List of threads
     
    247151        } node;
    248152
    249         struct {
    250                 io_context * ctxs;
    251                 unsigned cnt;
    252         } io;
     153        struct __io_data * io;
    253154
    254155        #if !defined(__CFA_NO_STATISTICS__)
    255                 struct __stats_t * stats;
    256                 int print_stats;
     156                bool print_stats;
    257157        #endif
    258158};
    259159extern Duration default_preemption();
    260160
    261 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params);
     161void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags);
    262162void ^?{}(cluster & this);
    263163
    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}; }
     164static inline void ?{} (cluster & this)                                      { this{"Anonymous Cluster", default_preemption(), 0}; }
     165static inline void ?{} (cluster & this, Duration preemption_rate)            { this{"Anonymous Cluster", preemption_rate, 0}; }
     166static inline void ?{} (cluster & this, const char name[])                   { this{name, default_preemption(), 0}; }
     167static inline void ?{} (cluster & this, int flags)                           { this{"Anonymous Cluster", default_preemption(), flags}; }
     168static inline void ?{} (cluster & this, Duration preemption_rate, int flags) { this{"Anonymous Cluster", preemption_rate, flags}; }
     169static inline void ?{} (cluster & this, const char name[], int flags)        { this{name, default_preemption(), flags}; }
    276170
    277171static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
     
    281175
    282176#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;
    285179        }
    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 );
    292180#endif
    293181
Note: See TracChangeset for help on using the changeset viewer.