Ignore:
File:
1 edited

Legend:

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

    rdd4e2d7 r504a7dc  
    7777//-----------------------------------------------------------------------------
    7878// I/O
    79 void __kernel_io_startup     ( cluster &, unsigned, bool );
     79void __kernel_io_startup     ( cluster &, int, bool );
    8080void __kernel_io_finish_start( cluster & );
    8181void __kernel_io_prepare_stop( cluster & );
     
    8484//-----------------------------------------------------------------------------
    8585// Utils
    86 #define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
     86#define KERNEL_STORAGE(T,X) __attribute((aligned(__alignof__(T)))) static char storage_##X[sizeof(T)]
    8787
    8888static inline uint32_t __tls_rand() {
     
    103103void unregister( struct cluster * cltr, struct processor * proc );
    104104
     105//=======================================================================
     106// Cluster lock API
     107//=======================================================================
     108struct __attribute__((aligned(64))) __processor_id {
     109        processor * volatile handle;
     110        volatile bool lock;
     111};
     112
     113// Lock-Free registering/unregistering of threads
     114// Register a processor to a given cluster and get its unique id in return
     115unsigned doregister2( struct cluster * cltr, struct processor * proc );
     116
     117// Unregister a processor from a given cluster using its id, getting back the original pointer
     118void     unregister2( struct cluster * cltr, struct processor * proc );
     119
     120//=======================================================================
     121// Reader-writer lock implementation
     122// Concurrent with doregister/unregister,
     123//    i.e., threads can be added at any point during or between the entry/exit
     124
     125//-----------------------------------------------------------------------
     126// simple spinlock underlying the RWLock
     127// Blocking acquire
     128static inline void __atomic_acquire(volatile bool * ll) {
     129        while( __builtin_expect(__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST), false) ) {
     130                while(__atomic_load_n(ll, (int)__ATOMIC_RELAXED))
     131                        asm volatile("pause");
     132        }
     133        /* paranoid */ verify(*ll);
     134}
     135
     136// Non-Blocking acquire
     137static inline bool __atomic_try_acquire(volatile bool * ll) {
     138        return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);
     139}
     140
     141// Release
     142static inline void __atomic_unlock(volatile bool * ll) {
     143        /* paranoid */ verify(*ll);
     144        __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
     145}
     146
     147//-----------------------------------------------------------------------
     148// Reader side : acquire when using the ready queue to schedule but not
     149//  creating/destroying queues
     150static inline void ready_schedule_lock( struct cluster * cltr, struct processor * proc) with(cltr->ready_lock) {
     151        unsigned iproc = proc->id;
     152        /*paranoid*/ verify(data[iproc].handle == proc);
     153        /*paranoid*/ verify(iproc < ready);
     154
     155        // Step 1 : make sure no writer are in the middle of the critical section
     156        while(__atomic_load_n(&lock, (int)__ATOMIC_RELAXED))
     157                asm volatile("pause");
     158
     159        // Fence needed because we don't want to start trying to acquire the lock
     160        // before we read a false.
     161        // Not needed on x86
     162        // std::atomic_thread_fence(std::memory_order_seq_cst);
     163
     164        // Step 2 : acquire our local lock
     165        __atomic_acquire( &data[iproc].lock );
     166        /*paranoid*/ verify(data[iproc].lock);
     167}
     168
     169static inline void ready_schedule_unlock( struct cluster * cltr, struct processor * proc) with(cltr->ready_lock) {
     170        unsigned iproc = proc->id;
     171        /*paranoid*/ verify(data[iproc].handle == proc);
     172        /*paranoid*/ verify(iproc < ready);
     173        /*paranoid*/ verify(data[iproc].lock);
     174        __atomic_unlock(&data[iproc].lock);
     175}
     176
     177//-----------------------------------------------------------------------
     178// Writer side : acquire when changing the ready queue, e.g. adding more
     179//  queues or removing them.
     180uint_fast32_t ready_mutate_lock( struct cluster & cltr );
     181
     182void ready_mutate_unlock( struct cluster & cltr, uint_fast32_t /* value returned by lock */ );
     183
     184//=======================================================================
     185// Ready-Queue API
     186//-----------------------------------------------------------------------
     187// push thread onto a ready queue for a cluster
     188// returns true if the list was previously empty, false otherwise
     189__attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);
     190
     191//-----------------------------------------------------------------------
     192// pop thread from the ready queue of a cluster
     193// returns 0p if empty
     194__attribute__((hot)) struct $thread * pop(struct cluster * cltr);
     195
     196//-----------------------------------------------------------------------
     197// Increase the width of the ready queue (number of lanes) by 4
     198void ready_queue_grow  (struct cluster * cltr);
     199
     200//-----------------------------------------------------------------------
     201// Decrease the width of the ready queue (number of lanes) by 4
     202void ready_queue_shrink(struct cluster * cltr);
     203
     204//-----------------------------------------------------------------------
     205// Statics call at the end of each thread to register statistics
     206#if !defined(__CFA_NO_STATISTICS__)
     207void stats_tls_tally(struct cluster * cltr);
     208#else
     209static inline void stats_tls_tally(struct cluster * cltr) {}
     210#endif
     211
    105212// Local Variables: //
    106213// mode: c //
Note: See TracChangeset for help on using the changeset viewer.