Changes in / [4fa44e7:730f4f1]


Ignore:
Files:
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    r4fa44e7 r730f4f1  
    4848thread_headers_nosrc = concurrency/invoke.h
    4949thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa concurrency/monitor.hfa concurrency/mutex.hfa
    50 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa concurrency/ready_queue.cfa ${thread_headers:.hfa=.cfa}
     50thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa ${thread_headers:.hfa=.cfa}
    5151else
    5252headers =
  • libcfa/src/Makefile.in

    r4fa44e7 r730f4f1  
    166166        concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \
    167167        concurrency/invoke.c concurrency/io.cfa \
    168         concurrency/preemption.cfa concurrency/ready_queue.cfa \
    169         concurrency/coroutine.cfa concurrency/thread.cfa \
    170         concurrency/kernel.cfa concurrency/monitor.cfa \
    171         concurrency/mutex.cfa
     168        concurrency/preemption.cfa concurrency/coroutine.cfa \
     169        concurrency/thread.cfa concurrency/kernel.cfa \
     170        concurrency/monitor.cfa concurrency/mutex.cfa
    172171@BUILDLIB_TRUE@am__objects_3 = concurrency/coroutine.lo \
    173172@BUILDLIB_TRUE@ concurrency/thread.lo concurrency/kernel.lo \
     
    177176@BUILDLIB_TRUE@ concurrency/alarm.lo concurrency/invoke.lo \
    178177@BUILDLIB_TRUE@ concurrency/io.lo concurrency/preemption.lo \
    179 @BUILDLIB_TRUE@ concurrency/ready_queue.lo $(am__objects_3)
     178@BUILDLIB_TRUE@ $(am__objects_3)
    180179am_libcfathread_la_OBJECTS = $(am__objects_4)
    181180libcfathread_la_OBJECTS = $(am_libcfathread_la_OBJECTS)
     
    478477@BUILDLIB_FALSE@thread_headers =
    479478@BUILDLIB_TRUE@thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa concurrency/monitor.hfa concurrency/mutex.hfa
    480 @BUILDLIB_TRUE@thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa concurrency/ready_queue.cfa ${thread_headers:.hfa=.cfa}
     479@BUILDLIB_TRUE@thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa ${thread_headers:.hfa=.cfa}
    481480
    482481#----------------------------------------------------------------------------------------------------------------
     
    616615        concurrency/$(DEPDIR)/$(am__dirstamp)
    617616concurrency/preemption.lo: concurrency/$(am__dirstamp) \
    618         concurrency/$(DEPDIR)/$(am__dirstamp)
    619 concurrency/ready_queue.lo: concurrency/$(am__dirstamp) \
    620617        concurrency/$(DEPDIR)/$(am__dirstamp)
    621618concurrency/coroutine.lo: concurrency/$(am__dirstamp) \
  • libcfa/src/bits/debug.hfa

    r4fa44e7 r730f4f1  
    5252                || defined(__CFA_DEBUG_PRINT_IO__) || defined(__CFA_DEBUG_PRINT_IO_CORE__) \
    5353                || defined(__CFA_DEBUG_PRINT_MONITOR__) || defined(__CFA_DEBUG_PRINT_PREEMPTION__) \
    54                 || defined(__CFA_DEBUG_PRINT_RUNTIME_CORE__) || defined(__CFA_DEBUG_PRINT_EXCEPTION__) \
    55                 || defined(__CFA_DEBUG_PRINT_READY_QUEUE__)
     54                || defined(__CFA_DEBUG_PRINT_RUNTIME_CORE__) || defined(__CFA_DEBUG_PRINT_EXCEPTION__)
    5655        #include <stdio.h>
    5756        #include <unistd.h>
  • libcfa/src/bits/defs.hfa

    r4fa44e7 r730f4f1  
    5454    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
    5555}
    56 
    57 // #define __CFA_NO_BIT_TEST_AND_SET__
    58 
    59 #if defined( __i386 )
    60 static inline bool __atomic_bts(volatile unsigned long int * target, unsigned long int bit ) {
    61         #if defined(__CFA_NO_BIT_TEST_AND_SET__)
    62         unsigned long int mask = 1ul << bit;
    63         unsigned long int ret = __atomic_fetch_or(target, mask, (int)__ATOMIC_RELAXED);
    64         return (ret & mask) != 0;
    65     #else
    66         int result = 0;
    67         asm volatile(
    68             "LOCK btsl %[bit], %[target]\n\t"
    69             : "=@ccc" (result)
    70             : [target] "m" (*target), [bit] "r" (bit)
    71         );
    72         return result != 0;
    73     #endif
    74 }
    75 
    76 static inline bool __atomic_btr(volatile unsigned long int * target, unsigned long int bit ) {
    77         #if defined(__CFA_NO_BIT_TEST_AND_SET__)
    78         unsigned long int mask = 1ul << bit;
    79         unsigned long int ret = __atomic_fetch_and(target, ~mask, (int)__ATOMIC_RELAXED);
    80         return (ret & mask) != 0;
    81         #else
    82         int result = 0;
    83         asm volatile(
    84             "LOCK btrl %[bit], %[target]\n\t"
    85             :"=@ccc" (result)
    86             : [target] "m" (*target), [bit] "r" (bit)
    87         );
    88         return result != 0;
    89     #endif
    90 }
    91 #elif defined( __x86_64 )
    92 static inline bool __atomic_bts(volatile unsigned long long int * target, unsigned long long int bit ) {
    93         #if defined(__CFA_NO_BIT_TEST_AND_SET__)
    94         unsigned long long int mask = 1ul << bit;
    95         unsigned long long int ret = __atomic_fetch_or(target, mask, (int)__ATOMIC_RELAXED);
    96         return (ret & mask) != 0;
    97     #else
    98         int result = 0;
    99         asm volatile(
    100             "LOCK btsq %[bit], %[target]\n\t"
    101             : "=@ccc" (result)
    102             : [target] "m" (*target), [bit] "r" (bit)
    103         );
    104         return result != 0;
    105     #endif
    106 }
    107 
    108 static inline bool __atomic_btr(volatile unsigned long long int * target, unsigned long long int bit ) {
    109         #if defined(__CFA_NO_BIT_TEST_AND_SET__)
    110         unsigned long long int mask = 1ul << bit;
    111         unsigned long long int ret = __atomic_fetch_and(target, ~mask, (int)__ATOMIC_RELAXED);
    112         return (ret & mask) != 0;
    113         #else
    114         int result = 0;
    115         asm volatile(
    116             "LOCK btrq %[bit], %[target]\n\t"
    117             :"=@ccc" (result)
    118             : [target] "m" (*target), [bit] "r" (bit)
    119         );
    120         return result != 0;
    121     #endif
    122 }
    123 #elif defined( __ARM_ARCH )
    124     #error __atomic_bts and __atomic_btr not implemented for arm
    125 #else
    126         #error uknown hardware architecture
    127 #endif
  • libcfa/src/concurrency/invoke.h

    r4fa44e7 r730f4f1  
    161161        };
    162162
    163         // Link lists fields
    164         // instrusive link field for threads
    165         struct __thread_desc_link {
    166                 struct $thread * next;
    167                 struct $thread * prev;
    168                 unsigned long long ts;
    169         };
    170 
    171163        struct $thread {
    172164                // Core threading fields
     
    200192                // Link lists fields
    201193                // instrusive link field for threads
    202                 struct __thread_desc_link link;
     194                struct $thread * next;
    203195
    204196                struct {
     
    226218        #ifdef __cforall
    227219        extern "Cforall" {
    228 
    229220                static inline $thread *& get_next( $thread & this ) __attribute__((const)) {
    230                         return this.link.next;
     221                        return this.next;
    231222                }
    232223
  • libcfa/src/concurrency/kernel.cfa

    r4fa44e7 r730f4f1  
    120120static void __run_thread(processor * this, $thread * dst);
    121121static $thread * __halt(processor * this);
    122 static bool __wake_one(cluster * cltr);
     122static bool __wake_one(cluster * cltr, bool was_empty);
    123123static bool __wake_proc(processor *);
    124124
     
    197197        self_mon.recursion = 1;
    198198        self_mon_p = &self_mon;
    199         link.next = 0p;
    200         link.prev = 0p;
     199        next = 0p;
    201200
    202201        node.next = 0p;
     
    224223        this.name = name;
    225224        this.cltr = &cltr;
    226         id = -1u;
    227225        terminated{ 0 };
    228226        destroyer = 0p;
     
    262260        this.preemption_rate = preemption_rate;
    263261        ready_queue{};
    264         ready_lock{};
     262        ready_queue_lock{};
    265263
    266264        #if !defined(__CFA_NO_STATISTICS__)
     
    297295        __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this);
    298296
    299         // register the processor unless it's the main thread which is handled in the boot sequence
    300         if(this != mainProcessor) {
    301                 this->id = doregister2(this->cltr, this);
    302                 ready_queue_grow( this->cltr );
    303         }
    304 
    305297        doregister(this->cltr, this);
    306298
     
    326318                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    327319                                /* paranoid */ verifyf( readyThread->state == Ready || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);
    328                                 /* paranoid */ verifyf( readyThread->link.next == 0p, "Expected null got %p", readyThread->link.next );
     320                                /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next );
    329321
    330322                                // We found a thread run it
     
    342334        V( this->terminated );
    343335
    344         // unregister the processor unless it's the main thread which is handled in the boot sequence
    345         if(this != mainProcessor) {
    346                 ready_queue_shrink( this->cltr );
    347                 unregister2(this->cltr, this);
    348         }
    349         else {
    350                 // HACK : the coroutine context switch expects this_thread to be set
    351                 // and it make sense for it to be set in all other cases except here
    352                 // fake it
    353                 kernelTLS.this_thread = mainThread;
    354         }
    355 
    356336        __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this);
    357337
    358         stats_tls_tally(this->cltr);
     338        // HACK : the coroutine context switch expects this_thread to be set
     339        // and it make sense for it to be set in all other cases except here
     340        // fake it
     341        if( this == mainProcessor ) kernelTLS.this_thread = mainThread;
    359342}
    360343
     
    608591// Scheduler routines
    609592// KERNEL ONLY
    610 void __schedule_thread( $thread * thrd ) {
    611         /* paranoid */ verify( thrd );
    612         /* paranoid */ verify( thrd->state != Halted );
     593void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) {
    613594        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    614595        /* paranoid */ #if defined( __CFA_WITH_VERIFY__ )
    615         /* paranoid */  if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
    616                                         "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );
    617         /* paranoid */  if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,
    618                                         "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );
     596        /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
     597                          "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );
     598        /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,
     599                          "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );
    619600        /* paranoid */ #endif
    620         /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next );
     601        /* paranoid */ verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
    621602
    622603        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    623604
    624         ready_schedule_lock(thrd->curr_cluster, kernelTLS.this_processor);
    625                 push( thrd->curr_cluster, thrd );
    626 
    627                 __wake_one(thrd->curr_cluster);
    628         ready_schedule_unlock(thrd->curr_cluster, kernelTLS.this_processor);
     605        lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
     606        bool was_empty = !(ready_queue != 0);
     607        append( ready_queue, thrd );
     608        unlock( ready_queue_lock );
     609
     610        __wake_one(thrd->curr_cluster, was_empty);
    629611
    630612        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    635617        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    636618
    637         ready_schedule_lock(this, kernelTLS.this_processor);
    638                 $thread * head = pop( this );
    639         ready_schedule_unlock(this, kernelTLS.this_processor);
     619        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
     620        $thread * head = pop_head( ready_queue );
     621        unlock( ready_queue_lock );
    640622
    641623        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    721703        // If that is the case, abandon the preemption.
    722704        bool preempted = false;
    723         if(thrd->link.next == 0p) {
     705        if(thrd->next == 0p) {
    724706                preempted = true;
    725707                thrd->preempted = reason;
     
    781763                pending_preemption = false;
    782764                kernel_thread = pthread_self();
    783                 id = -1u;
    784765
    785766                runner{ &this };
     
    791772        mainProcessor = (processor *)&storage_mainProcessor;
    792773        (*mainProcessor){};
    793 
    794         mainProcessor->id = doregister2(mainCluster, mainProcessor);
    795774
    796775        //initialize the global state variables
     
    847826        kernel_stop_preemption();
    848827
    849         unregister2(mainCluster, mainProcessor);
    850 
    851828        // Destroy the main processor and its context in reverse order of construction
    852829        // These were manually constructed so we need manually destroy them
    853830        void ^?{}(processor & this) with( this ){
    854831                /* paranoid */ verify( this.do_terminate == true );
    855                 __cfaabi_dbg_print_safe("Kernel : destroyed main processor context %p\n", &runner);
    856832        }
    857833
     
    859835
    860836        // Final step, destroy the main thread since it is no longer needed
    861 
    862837        // Since we provided a stack to this taxk it will not destroy anything
    863838        /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1));
     
    912887
    913888// Wake a thread from the front if there are any
    914 static bool __wake_one(cluster * this) {
     889static bool __wake_one(cluster * this, __attribute__((unused)) bool force) {
     890        // if we don't want to force check if we know it's false
     891        // if( !this->idles.head && !force ) return false;
     892
    915893        // First, lock the cluster idle
    916894        lock( this->idle_lock __cfaabi_dbg_ctx2 );
  • libcfa/src/concurrency/kernel.hfa

    r4fa44e7 r730f4f1  
    6060        // Cluster from which to get threads
    6161        struct cluster * cltr;
    62         unsigned int id;
    6362
    6463        // Name of the processor
     
    9392
    9493        // Link lists fields
    95         struct __dbg_node_cltr {
    96                 processor * next;
    97                 processor * prev;
     94        struct __dbg_node_proc {
     95                struct processor * next;
     96                struct processor * prev;
    9897        } node;
    9998
     
    120119// #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1
    121120
    122 
    123 //-----------------------------------------------------------------------------
    124 // Cluster Tools
    125 
    126 // Cells use by the reader writer lock
    127 // while not generic it only relies on a opaque pointer
    128 struct __processor_id;
    129 
    130 // Reader-Writer lock protecting the ready-queue
    131 // while this lock is mostly generic some aspects
    132 // have been hard-coded to for the ready-queue for
    133 // simplicity and performance
    134 struct __clusterRWLock_t {
    135         // total cachelines allocated
    136         unsigned int max;
    137 
    138         // cachelines currently in use
    139         volatile unsigned int alloc;
    140 
    141         // cachelines ready to itereate over
    142         // (!= to alloc when thread is in second half of doregister)
    143         volatile unsigned int ready;
    144 
    145         // writer lock
    146         volatile bool lock;
    147 
    148         // data pointer
    149         __processor_id * data;
    150 };
    151 
    152 void  ?{}(__clusterRWLock_t & this);
    153 void ^?{}(__clusterRWLock_t & this);
    154 
    155 // Intrusives lanes which are used by the relaxed ready queue
    156 struct __attribute__((aligned(128))) __intrusive_lane_t {
    157         // spin lock protecting the queue
    158         volatile bool lock;
    159 
    160         // anchor for the head and the tail of the queue
    161         struct __sentinel_t {
    162                 // Link lists fields
    163                 // instrusive link field for threads
    164                 // must be exactly as in $thread
    165                 __thread_desc_link link;
    166         } before, after;
    167 
    168 #if defined(__CFA_WITH_VERIFY__)
    169         // id of last processor to acquire the lock
    170         // needed only to check for mutual exclusion violations
    171         unsigned int last_id;
    172 
    173         // number of items on this list
    174         // needed only to check for deadlocks
    175         unsigned int count;
    176 #endif
    177 
    178         // Optional statistic counters
    179         #if !defined(__CFA_NO_SCHED_STATS__)
    180                 struct __attribute__((aligned(64))) {
    181                         // difference between number of push and pops
    182                         ssize_t diff;
    183 
    184                         // total number of pushes and pops
    185                         size_t  push;
    186                         size_t  pop ;
    187                 } stat;
    188         #endif
    189 };
    190 
    191 void  ?{}(__intrusive_lane_t & this);
    192 void ^?{}(__intrusive_lane_t & this);
    193 
    194 typedef unsigned long long __cfa_readyQ_mask_t;
    195 
    196 // enum {
    197 //      __cfa_ready_queue_mask_size = (64 - sizeof(size_t)) / sizeof(size_t),
    198 //      __cfa_max_ready_queues = __cfa_ready_queue_mask_size * 8 * sizeof(size_t)
    199 // };
    200 
    201 #define __cfa_lane_mask_size ((64 - sizeof(size_t)) / sizeof(__cfa_readyQ_mask_t))
    202 #define __cfa_max_lanes (__cfa_lane_mask_size * 8 * sizeof(__cfa_readyQ_mask_t))
    203 
    204 //TODO adjust cache size to ARCHITECTURE
    205 // Structure holding the relaxed ready queue
    206 struct __attribute__((aligned(128))) __ready_queue_t {
    207         // Data tracking how many/which lanes are used
    208         // Aligned to 128 for cache locality
    209         struct {
    210                 // number of non-empty lanes
    211                 volatile size_t count;
    212 
    213                 // bit mask, set bits indentify which lanes are non-empty
    214                 volatile __cfa_readyQ_mask_t mask[ __cfa_lane_mask_size ];
    215         } used;
    216 
    217         // Data tracking the actual lanes
    218         // On a seperate cacheline from the used struct since
    219         // used can change on each push/pop but this data
    220         // only changes on shrink/grow
    221         struct __attribute__((aligned(64))) {
    222                 // Arary of lanes
    223                 __intrusive_lane_t * volatile data;
    224 
    225                 // Number of lanes (empty or not)
    226                 volatile size_t count;
    227         } lanes;
    228 
    229         // Statistics
    230         #if !defined(__CFA_NO_STATISTICS__)
    231                 __attribute__((aligned(64))) struct {
    232                         struct {
    233                                 // Push statistic
    234                                 struct {
    235                                         // number of attemps at pushing something
    236                                         volatile size_t attempt;
    237 
    238                                         // number of successes at pushing
    239                                         volatile size_t success;
    240                                 } push;
    241 
    242                                 // Pop statistic
    243                                 struct {
    244                                         // number of reads of the mask
    245                                         // picking an empty __cfa_readyQ_mask_t counts here
    246                                         // but not as an attempt
    247                                         volatile size_t maskrds;
    248 
    249                                         // number of attemps at poping something
    250                                         volatile size_t attempt;
    251 
    252                                         // number of successes at poping
    253                                         volatile size_t success;
    254                                 } pop;
    255                         } pick;
    256 
    257                         // stats on the "used" struct of the queue
    258                         // tracks average number of queues that are not empty
    259                         // when pushing / poping
    260                         struct {
    261                                 volatile size_t value;
    262                                 volatile size_t count;
    263                         } used;
    264                 } global_stats;
    265 
    266         #endif
    267 };
    268 
    269 void  ?{}(__ready_queue_t & this);
    270 void ^?{}(__ready_queue_t & this);
    271 
    272121//-----------------------------------------------------------------------------
    273122// Cluster
    274123struct cluster {
    275124        // Ready queue locks
    276         __clusterRWLock_t ready_lock;
     125        __spinlock_t ready_queue_lock;
    277126
    278127        // Ready queue for threads
    279         __ready_queue_t ready_queue;
     128        __queue_t($thread) ready_queue;
    280129
    281130        // Name of the cluster
  • libcfa/src/concurrency/kernel_private.hfa

    r4fa44e7 r730f4f1  
    8484//-----------------------------------------------------------------------------
    8585// Utils
    86 #define KERNEL_STORAGE(T,X) __attribute((aligned(__alignof__(T)))) static char storage_##X[sizeof(T)]
     86#define KERNEL_STORAGE(T,X) 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 //=======================================================================
    108 struct __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
    115 unsigned doregister2( struct cluster * cltr, struct processor * proc );
    116 
    117 // Unregister a processor from a given cluster using its id, getting back the original pointer
    118 void     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
    128 static 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
    137 static inline bool __atomic_try_acquire(volatile bool * ll) {
    138         return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);
    139 }
    140 
    141 // Release
    142 static 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
    150 static 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 
    169 static 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.
    180 uint_fast32_t ready_mutate_lock( struct cluster & cltr );
    181 
    182 void 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
    198 void ready_queue_grow  (struct cluster * cltr);
    199 
    200 //-----------------------------------------------------------------------
    201 // Decrease the width of the ready queue (number of lanes) by 4
    202 void 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__)
    207 void stats_tls_tally(struct cluster * cltr);
    208 #else
    209 static inline void stats_tls_tally(struct cluster * cltr) {}
    210 #endif
    211 
    212105// Local Variables: //
    213106// mode: c //
  • libcfa/src/concurrency/monitor.cfa

    r4fa44e7 r730f4f1  
    114114
    115115                // Some one else has the monitor, wait in line for it
    116                 /* paranoid */ verify( thrd->link.next == 0p );
     116                /* paranoid */ verify( thrd->next == 0p );
    117117                append( this->entry_queue, thrd );
    118                 /* paranoid */ verify( thrd->link.next == 1p );
     118                /* paranoid */ verify( thrd->next == 1p );
    119119
    120120                unlock( this->lock );
     
    199199
    200200                // Some one else has the monitor, wait in line for it
    201                 /* paranoid */ verify( thrd->link.next == 0p );
     201                /* paranoid */ verify( thrd->next == 0p );
    202202                append( this->entry_queue, thrd );
    203                 /* paranoid */ verify( thrd->link.next == 1p );
     203                /* paranoid */ verify( thrd->next == 1p );
    204204                unlock( this->lock );
    205205
     
    761761        $thread * new_owner = pop_head( this->entry_queue );
    762762        /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    763         /* paranoid */ verify( !new_owner || new_owner->link.next == 0p );
     763        /* paranoid */ verify( !new_owner || new_owner->next == 0p );
    764764        __set_owner( this, new_owner );
    765765
     
    883883        }
    884884
    885         __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? (thread*)node->waiting_thread : (thread*)0p );
     885        __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : 0p );
    886886        return ready2run ? node->waiting_thread : 0p;
    887887}
     
    907907        // For each thread in the entry-queue
    908908        for(    $thread ** thrd_it = &entry_queue.head;
    909                 *thrd_it;
    910                 thrd_it = &(*thrd_it)->link.next
     909                *thrd_it != 1p;
     910                thrd_it = &(*thrd_it)->next
    911911        ) {
    912912                // For each acceptable check if it matches
  • libcfa/src/concurrency/preemption.cfa

    r4fa44e7 r730f4f1  
    121121        // If there are still alarms pending, reset the timer
    122122        if( & (*alarms)`first ) {
    123                 __cfadbg_print_buffer_decl(preemption, " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
     123                __cfaabi_dbg_print_buffer_decl( " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
    124124                Duration delta = (*alarms)`first.alarm - currtime;
    125125                Duration capped = max(delta, 50`us);
  • libcfa/src/concurrency/thread.cfa

    r4fa44e7 r730f4f1  
    3535        self_mon_p = &self_mon;
    3636        curr_cluster = &cl;
    37         link.next = 0p;
    38         link.prev = 0p;
     37        next = 0p;
    3938
    4039        node.next = 0p;
  • libcfa/src/stdhdr/assert.h

    r4fa44e7 r730f4f1  
    3333        #define verify(x) assert(x)
    3434        #define verifyf(x, ...) assertf(x, __VA_ARGS__)
    35         #define verifyfail(...)
    3635        #define __CFA_WITH_VERIFY__
    3736#else
    3837        #define verify(x)
    3938        #define verifyf(x, ...)
    40         #define verifyfail(...)
    4139#endif
    4240
  • tests/concurrent/examples/datingService.cfa

    r4fa44e7 r730f4f1  
    3535                signal_block( Boys[ccode] );                                    // restart boy to set phone number
    3636        } // if
    37         // sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode;
     37        //sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode;
    3838        return BoyPhoneNo;
    3939} // DatingService girl
     
    4747                signal_block( Girls[ccode] );                                   // restart girl to set phone number
    4848        } // if
    49         // sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
     49        //sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
    5050        return GirlPhoneNo;
    5151} // DatingService boy
  • tests/concurrent/waitfor/when.cfa

    r4fa44e7 r730f4f1  
    5757
    5858void arbiter( global_t & mutex this ) {
    59         // There is a race at start where callers can get in before the arbiter.
    60         // It doesn't really matter here so just restart the loop correctly and move on
    61         this.last_call = 6;
    62 
    6359        for( int i = 0; i < N; i++ ) {
    6460                   when( this.last_call == 6 ) waitfor( call1 : this ) { if( this.last_call != 1) { serr | "Expected last_call to be 1 got" | this.last_call; } }
Note: See TracChangeset for help on using the changeset viewer.