Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into dkobets-vector

File:
1 edited

Legend:

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

    rbdfc032 reef8dfb  
    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
    1616#pragma once
    17 
    18 #include <stdbool.h>
    1917
    2018#include "invoke.h"
     
    2220#include "coroutine.hfa"
    2321
     22#include "containers/list.hfa"
     23
    2424extern "C" {
    25 #include <pthread.h>
    26 #include <semaphore.h>
     25        #include <bits/pthreadtypes.h>
     26        #include <linux/types.h>
    2727}
    2828
     
    3232        __spinlock_t lock;
    3333        int count;
    34         __queue_t(thread_desc) waiting;
     34        __queue_t($thread) waiting;
    3535};
    3636
    3737void  ?{}(semaphore & this, int count = 1);
    3838void ^?{}(semaphore & this);
    39 void   P (semaphore & this);
    40 void   V (semaphore & this);
     39bool   P (semaphore & this);
     40bool   V (semaphore & this);
     41bool   V (semaphore & this, unsigned count);
    4142
    4243
     
    4546extern struct cluster * mainCluster;
    4647
    47 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
    48 
    49 typedef void (*__finish_callback_fptr_t)(void);
    50 
    51 //TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
    52 struct FinishAction {
    53         FinishOpCode action_code;
    54         /*
    55         // Union of possible actions
    56         union {
    57                 // Option 1 : locks and threads
    58                 struct {
    59                         // 1 thread or N thread
    60                         union {
    61                                 thread_desc * thrd;
    62                                 struct {
    63                                         thread_desc ** thrds;
    64                                         unsigned short thrd_count;
    65                                 };
    66                         };
    67                         // 1 lock or N lock
    68                         union {
    69                                 __spinlock_t * lock;
    70                                 struct {
    71                                         __spinlock_t ** locks;
    72                                         unsigned short lock_count;
    73                                 };
    74                         };
    75                 };
    76                 // Option 2 : action pointer
    77                 __finish_callback_fptr_t callback;
    78         };
    79         /*/
    80         thread_desc * thrd;
    81         thread_desc ** thrds;
    82         unsigned short thrd_count;
    83         __spinlock_t * lock;
    84         __spinlock_t ** locks;
    85         unsigned short lock_count;
    86         __finish_callback_fptr_t callback;
    87         //*/
    88 };
    89 static inline void ?{}(FinishAction & this) {
    90         this.action_code = No_Action;
    91         this.thrd = 0p;
    92         this.lock = 0p;
    93 }
    94 static inline void ^?{}(FinishAction &) {}
    95 
    96 // Processor
     48// Processor id, required for scheduling threads
     49struct __processor_id_t {
     50        unsigned id:24;
     51        bool full_proc:1;
     52
     53        #if !defined(__CFA_NO_STATISTICS__)
     54                struct __stats_t * stats;
     55        #endif
     56};
     57
    9758coroutine processorCtx_t {
    9859        struct processor * proc;
     
    10061
    10162// Wrapper around kernel threads
    102 struct processor {
     63struct __attribute__((aligned(128))) processor {
    10364        // Main state
     65        inline __processor_id_t;
     66
     67        // Cluster from which to get threads
     68        struct cluster * cltr;
     69
     70        // Set to true to notify the processor should terminate
     71        volatile bool do_terminate;
     72
    10473        // Coroutine ctx who does keeps the state of the processor
    10574        struct processorCtx_t runner;
    10675
    107         // Cluster from which to get threads
    108         struct cluster * cltr;
    109 
    11076        // Name of the processor
    11177        const char * name;
     
    11379        // Handle to pthreads
    11480        pthread_t kernel_thread;
    115 
    116         // RunThread data
    117         // Action to do after a thread is ran
    118         struct FinishAction finish;
    11981
    12082        // Preemption data
     
    12587        bool pending_preemption;
    12688
    127         // Idle lock
    128         __bin_sem_t idleLock;
    129 
    130         // Termination
    131         // Set to true to notify the processor should terminate
    132         volatile bool do_terminate;
    133 
    134         // Termination synchronisation
     89        // Idle lock (kernel semaphore)
     90        __bin_sem_t idle;
     91
     92        // Termination synchronisation (user semaphore)
    13593        semaphore terminated;
    13694
     
    13997
    14098        // Link lists fields
    141         struct __dbg_node_proc {
    142                 struct processor * next;
    143                 struct processor * prev;
    144         } node;
     99        DLISTED_MGD_IMPL_IN(processor)
     100
     101        #if !defined(__CFA_NO_STATISTICS__)
     102                int print_stats;
     103                bool print_halts;
     104        #endif
    145105
    146106#ifdef __CFA_DEBUG__
     
    150110};
    151111
    152 void  ?{}(processor & this, const char * name, struct cluster & cltr);
     112void  ?{}(processor & this, const char name[], struct cluster & cltr);
    153113void ^?{}(processor & this);
    154114
    155115static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    156116static inline void  ?{}(processor & this, struct cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    157 static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
    158 
    159 static inline [processor *&, processor *& ] __get( processor & this ) {
    160         return this.node.[next, prev];
    161 }
     117static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
     118
     119DLISTED_MGD_IMPL_OUT(processor)
     120
     121//-----------------------------------------------------------------------------
     122// I/O
     123struct __io_data;
     124
     125// IO poller user-thread
     126// Not using the "thread" keyword because we want to control
     127// more carefully when to start/stop it
     128struct $io_ctx_thread {
     129        struct __io_data * ring;
     130        single_sem sem;
     131        volatile bool done;
     132        $thread self;
     133};
     134
     135
     136struct io_context {
     137        $io_ctx_thread thrd;
     138};
     139
     140struct io_context_params {
     141        int num_entries;
     142        int num_ready;
     143        int submit_aff;
     144        bool eager_submits:1;
     145        bool poller_submits:1;
     146        bool poll_submit:1;
     147        bool poll_complete:1;
     148};
     149
     150void  ?{}(io_context_params & this);
     151
     152void  ?{}(io_context & this, struct cluster & cl);
     153void  ?{}(io_context & this, struct cluster & cl, const io_context_params & params);
     154void ^?{}(io_context & this);
     155
     156struct io_cancellation {
     157        __u64 target;
     158};
     159
     160static inline void  ?{}(io_cancellation & this) { this.target = -1u; }
     161static inline void ^?{}(io_cancellation &) {}
     162bool cancel(io_cancellation & this);
     163
     164//-----------------------------------------------------------------------------
     165// Cluster Tools
     166
     167// Intrusives lanes which are used by the relaxed ready queue
     168struct __attribute__((aligned(128))) __intrusive_lane_t;
     169void  ?{}(__intrusive_lane_t & this);
     170void ^?{}(__intrusive_lane_t & this);
     171
     172// Counter used for wether or not the lanes are all empty
     173struct __attribute__((aligned(128))) __snzi_node_t;
     174struct __snzi_t {
     175        unsigned mask;
     176        int root;
     177        __snzi_node_t * nodes;
     178};
     179
     180void  ?{}( __snzi_t & this, unsigned depth );
     181void ^?{}( __snzi_t & this );
     182
     183//TODO adjust cache size to ARCHITECTURE
     184// Structure holding the relaxed ready queue
     185struct __ready_queue_t {
     186        // Data tracking how many/which lanes are used
     187        // Aligned to 128 for cache locality
     188        __snzi_t snzi;
     189
     190        // Data tracking the actual lanes
     191        // On a seperate cacheline from the used struct since
     192        // used can change on each push/pop but this data
     193        // only changes on shrink/grow
     194        struct {
     195                // Arary of lanes
     196                __intrusive_lane_t * volatile data;
     197
     198                // Number of lanes (empty or not)
     199                volatile size_t count;
     200        } lanes;
     201};
     202
     203void  ?{}(__ready_queue_t & this);
     204void ^?{}(__ready_queue_t & this);
     205
     206// Idle Sleep
     207struct __cluster_idles {
     208        // Spin lock protecting the queue
     209        volatile uint64_t lock;
     210
     211        // Total number of processors
     212        unsigned total;
     213
     214        // Total number of idle processors
     215        unsigned idle;
     216
     217        // List of idle processors
     218        dlist(processor, processor) list;
     219};
    162220
    163221//-----------------------------------------------------------------------------
    164222// Cluster
    165 struct cluster {
    166         // Ready queue locks
    167         __spinlock_t ready_queue_lock;
    168 
     223struct __attribute__((aligned(128))) cluster {
    169224        // Ready queue for threads
    170         __queue_t(thread_desc) ready_queue;
     225        __ready_queue_t ready_queue;
    171226
    172227        // Name of the cluster
     
    176231        Duration preemption_rate;
    177232
    178         // List of processors
    179         __spinlock_t proc_list_lock;
    180         __dllist_t(struct processor) procs;
    181         __dllist_t(struct processor) idles;
    182         unsigned int nprocessors;
     233        // List of idle processors
     234        __cluster_idles idles;
    183235
    184236        // List of threads
    185237        __spinlock_t thread_list_lock;
    186         __dllist_t(struct thread_desc) threads;
     238        __dllist_t(struct $thread) threads;
    187239        unsigned int nthreads;
    188240
     
    192244                cluster * prev;
    193245        } node;
     246
     247        struct {
     248                io_context * ctxs;
     249                unsigned cnt;
     250        } io;
     251
     252        #if !defined(__CFA_NO_STATISTICS__)
     253                struct __stats_t * stats;
     254                int print_stats;
     255        #endif
    194256};
    195257extern Duration default_preemption();
    196258
    197 void ?{} (cluster & this, const char * name, Duration preemption_rate);
     259void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params);
    198260void ^?{}(cluster & this);
    199261
    200 static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    201 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()}; }
    203 
    204 static inline [cluster *&, cluster *& ] __get( cluster & this ) {
    205         return this.node.[next, prev];
    206 }
    207 
    208 static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE
    209 static inline struct cluster   * active_cluster  () { return TL_GET( this_processor )->cltr; }
     262static inline void ?{} (cluster & this)                                            { io_context_params default_params;    this{"Anonymous Cluster", default_preemption(), 1, default_params}; }
     263static inline void ?{} (cluster & this, Duration preemption_rate)                  { io_context_params default_params;    this{"Anonymous Cluster", preemption_rate, 1, default_params}; }
     264static inline void ?{} (cluster & this, const char name[])                         { io_context_params default_params;    this{name, default_preemption(), 1, default_params}; }
     265static inline void ?{} (cluster & this, unsigned num_io)                           { io_context_params default_params;    this{"Anonymous Cluster", default_preemption(), num_io, default_params}; }
     266static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io) { io_context_params default_params;    this{"Anonymous Cluster", preemption_rate, num_io, default_params}; }
     267static inline void ?{} (cluster & this, const char name[], unsigned num_io)        { io_context_params default_params;    this{name, default_preemption(), num_io, default_params}; }
     268static inline void ?{} (cluster & this, const io_context_params & io_params)                                            { this{"Anonymous Cluster", default_preemption(), 1, io_params}; }
     269static inline void ?{} (cluster & this, Duration preemption_rate, const io_context_params & io_params)                  { this{"Anonymous Cluster", preemption_rate, 1, io_params}; }
     270static inline void ?{} (cluster & this, const char name[], const io_context_params & io_params)                         { this{name, default_preemption(), 1, io_params}; }
     271static inline void ?{} (cluster & this, unsigned num_io, const io_context_params & io_params)                           { this{"Anonymous Cluster", default_preemption(), num_io, io_params}; }
     272static 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}; }
     273static inline void ?{} (cluster & this, const char name[], unsigned num_io, const io_context_params & io_params)        { this{name, default_preemption(), num_io, io_params}; }
     274
     275static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
     276
     277static inline struct processor * active_processor() { return publicTLS_get( this_processor ); } // UNSAFE
     278static inline struct cluster   * active_cluster  () { return publicTLS_get( this_processor )->cltr; }
     279
     280#if !defined(__CFA_NO_STATISTICS__)
     281        void print_stats_now( cluster & this, int flags );
     282
     283        static inline void print_stats_at_exit( cluster & this, int flags ) {
     284                this.print_stats |= flags;
     285        }
     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#endif
    210293
    211294// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.