Changes in / [4fa44e7:730f4f1]
- Files:
-
- 1 deleted
- 14 edited
-
libcfa/src/Makefile.am (modified) (1 diff)
-
libcfa/src/Makefile.in (modified) (4 diffs)
-
libcfa/src/bits/debug.hfa (modified) (1 diff)
-
libcfa/src/bits/defs.hfa (modified) (1 diff)
-
libcfa/src/concurrency/invoke.h (modified) (3 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (15 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel_private.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/preemption.cfa (modified) (1 diff)
-
libcfa/src/concurrency/ready_queue.cfa (deleted)
-
libcfa/src/concurrency/thread.cfa (modified) (1 diff)
-
libcfa/src/stdhdr/assert.h (modified) (1 diff)
-
tests/concurrent/examples/datingService.cfa (modified) (2 diffs)
-
tests/concurrent/waitfor/when.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
r4fa44e7 r730f4f1 48 48 thread_headers_nosrc = concurrency/invoke.h 49 49 thread_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}50 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa ${thread_headers:.hfa=.cfa} 51 51 else 52 52 headers = -
libcfa/src/Makefile.in
r4fa44e7 r730f4f1 166 166 concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \ 167 167 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 172 171 @BUILDLIB_TRUE@am__objects_3 = concurrency/coroutine.lo \ 173 172 @BUILDLIB_TRUE@ concurrency/thread.lo concurrency/kernel.lo \ … … 177 176 @BUILDLIB_TRUE@ concurrency/alarm.lo concurrency/invoke.lo \ 178 177 @BUILDLIB_TRUE@ concurrency/io.lo concurrency/preemption.lo \ 179 @BUILDLIB_TRUE@ concurrency/ready_queue.lo$(am__objects_3)178 @BUILDLIB_TRUE@ $(am__objects_3) 180 179 am_libcfathread_la_OBJECTS = $(am__objects_4) 181 180 libcfathread_la_OBJECTS = $(am_libcfathread_la_OBJECTS) … … 478 477 @BUILDLIB_FALSE@thread_headers = 479 478 @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} 481 480 482 481 #---------------------------------------------------------------------------------------------------------------- … … 616 615 concurrency/$(DEPDIR)/$(am__dirstamp) 617 616 concurrency/preemption.lo: concurrency/$(am__dirstamp) \ 618 concurrency/$(DEPDIR)/$(am__dirstamp)619 concurrency/ready_queue.lo: concurrency/$(am__dirstamp) \620 617 concurrency/$(DEPDIR)/$(am__dirstamp) 621 618 concurrency/coroutine.lo: concurrency/$(am__dirstamp) \ -
libcfa/src/bits/debug.hfa
r4fa44e7 r730f4f1 52 52 || defined(__CFA_DEBUG_PRINT_IO__) || defined(__CFA_DEBUG_PRINT_IO_CORE__) \ 53 53 || 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__) 56 55 #include <stdio.h> 57 56 #include <unistd.h> -
libcfa/src/bits/defs.hfa
r4fa44e7 r730f4f1 54 54 return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 55 55 } 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 #else66 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 #endif74 }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 #else82 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 #endif90 }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 #else98 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 #endif106 }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 #else114 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 #endif122 }123 #elif defined( __ARM_ARCH )124 #error __atomic_bts and __atomic_btr not implemented for arm125 #else126 #error uknown hardware architecture127 #endif -
libcfa/src/concurrency/invoke.h
r4fa44e7 r730f4f1 161 161 }; 162 162 163 // Link lists fields164 // instrusive link field for threads165 struct __thread_desc_link {166 struct $thread * next;167 struct $thread * prev;168 unsigned long long ts;169 };170 171 163 struct $thread { 172 164 // Core threading fields … … 200 192 // Link lists fields 201 193 // instrusive link field for threads 202 struct __thread_desc_link link;194 struct $thread * next; 203 195 204 196 struct { … … 226 218 #ifdef __cforall 227 219 extern "Cforall" { 228 229 220 static inline $thread *& get_next( $thread & this ) __attribute__((const)) { 230 return this. link.next;221 return this.next; 231 222 } 232 223 -
libcfa/src/concurrency/kernel.cfa
r4fa44e7 r730f4f1 120 120 static void __run_thread(processor * this, $thread * dst); 121 121 static $thread * __halt(processor * this); 122 static bool __wake_one(cluster * cltr );122 static bool __wake_one(cluster * cltr, bool was_empty); 123 123 static bool __wake_proc(processor *); 124 124 … … 197 197 self_mon.recursion = 1; 198 198 self_mon_p = &self_mon; 199 link.next = 0p; 200 link.prev = 0p; 199 next = 0p; 201 200 202 201 node.next = 0p; … … 224 223 this.name = name; 225 224 this.cltr = &cltr; 226 id = -1u;227 225 terminated{ 0 }; 228 226 destroyer = 0p; … … 262 260 this.preemption_rate = preemption_rate; 263 261 ready_queue{}; 264 ready_ lock{};262 ready_queue_lock{}; 265 263 266 264 #if !defined(__CFA_NO_STATISTICS__) … … 297 295 __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this); 298 296 299 // register the processor unless it's the main thread which is handled in the boot sequence300 if(this != mainProcessor) {301 this->id = doregister2(this->cltr, this);302 ready_queue_grow( this->cltr );303 }304 305 297 doregister(this->cltr, this); 306 298 … … 326 318 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 327 319 /* 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 ); 329 321 330 322 // We found a thread run it … … 342 334 V( this->terminated ); 343 335 344 // unregister the processor unless it's the main thread which is handled in the boot sequence345 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 set351 // and it make sense for it to be set in all other cases except here352 // fake it353 kernelTLS.this_thread = mainThread;354 }355 356 336 __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this); 357 337 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; 359 342 } 360 343 … … 608 591 // Scheduler routines 609 592 // KERNEL ONLY 610 void __schedule_thread( $thread * thrd ) { 611 /* paranoid */ verify( thrd ); 612 /* paranoid */ verify( thrd->state != Halted ); 593 void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) { 613 594 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 614 595 /* 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 ); 619 600 /* 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 ); 621 602 622 603 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 623 604 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); 629 611 630 612 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 635 617 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 636 618 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 ); 640 622 641 623 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 721 703 // If that is the case, abandon the preemption. 722 704 bool preempted = false; 723 if(thrd-> link.next == 0p) {705 if(thrd->next == 0p) { 724 706 preempted = true; 725 707 thrd->preempted = reason; … … 781 763 pending_preemption = false; 782 764 kernel_thread = pthread_self(); 783 id = -1u;784 765 785 766 runner{ &this }; … … 791 772 mainProcessor = (processor *)&storage_mainProcessor; 792 773 (*mainProcessor){}; 793 794 mainProcessor->id = doregister2(mainCluster, mainProcessor);795 774 796 775 //initialize the global state variables … … 847 826 kernel_stop_preemption(); 848 827 849 unregister2(mainCluster, mainProcessor);850 851 828 // Destroy the main processor and its context in reverse order of construction 852 829 // These were manually constructed so we need manually destroy them 853 830 void ^?{}(processor & this) with( this ){ 854 831 /* paranoid */ verify( this.do_terminate == true ); 855 __cfaabi_dbg_print_safe("Kernel : destroyed main processor context %p\n", &runner);856 832 } 857 833 … … 859 835 860 836 // Final step, destroy the main thread since it is no longer needed 861 862 837 // Since we provided a stack to this taxk it will not destroy anything 863 838 /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1)); … … 912 887 913 888 // Wake a thread from the front if there are any 914 static bool __wake_one(cluster * this) { 889 static 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 915 893 // First, lock the cluster idle 916 894 lock( this->idle_lock __cfaabi_dbg_ctx2 ); -
libcfa/src/concurrency/kernel.hfa
r4fa44e7 r730f4f1 60 60 // Cluster from which to get threads 61 61 struct cluster * cltr; 62 unsigned int id;63 62 64 63 // Name of the processor … … 93 92 94 93 // 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; 98 97 } node; 99 98 … … 120 119 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 121 120 122 123 //-----------------------------------------------------------------------------124 // Cluster Tools125 126 // Cells use by the reader writer lock127 // while not generic it only relies on a opaque pointer128 struct __processor_id;129 130 // Reader-Writer lock protecting the ready-queue131 // while this lock is mostly generic some aspects132 // have been hard-coded to for the ready-queue for133 // simplicity and performance134 struct __clusterRWLock_t {135 // total cachelines allocated136 unsigned int max;137 138 // cachelines currently in use139 volatile unsigned int alloc;140 141 // cachelines ready to itereate over142 // (!= to alloc when thread is in second half of doregister)143 volatile unsigned int ready;144 145 // writer lock146 volatile bool lock;147 148 // data pointer149 __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 queue156 struct __attribute__((aligned(128))) __intrusive_lane_t {157 // spin lock protecting the queue158 volatile bool lock;159 160 // anchor for the head and the tail of the queue161 struct __sentinel_t {162 // Link lists fields163 // instrusive link field for threads164 // must be exactly as in $thread165 __thread_desc_link link;166 } before, after;167 168 #if defined(__CFA_WITH_VERIFY__)169 // id of last processor to acquire the lock170 // needed only to check for mutual exclusion violations171 unsigned int last_id;172 173 // number of items on this list174 // needed only to check for deadlocks175 unsigned int count;176 #endif177 178 // Optional statistic counters179 #if !defined(__CFA_NO_SCHED_STATS__)180 struct __attribute__((aligned(64))) {181 // difference between number of push and pops182 ssize_t diff;183 184 // total number of pushes and pops185 size_t push;186 size_t pop ;187 } stat;188 #endif189 };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 ARCHITECTURE205 // Structure holding the relaxed ready queue206 struct __attribute__((aligned(128))) __ready_queue_t {207 // Data tracking how many/which lanes are used208 // Aligned to 128 for cache locality209 struct {210 // number of non-empty lanes211 volatile size_t count;212 213 // bit mask, set bits indentify which lanes are non-empty214 volatile __cfa_readyQ_mask_t mask[ __cfa_lane_mask_size ];215 } used;216 217 // Data tracking the actual lanes218 // On a seperate cacheline from the used struct since219 // used can change on each push/pop but this data220 // only changes on shrink/grow221 struct __attribute__((aligned(64))) {222 // Arary of lanes223 __intrusive_lane_t * volatile data;224 225 // Number of lanes (empty or not)226 volatile size_t count;227 } lanes;228 229 // Statistics230 #if !defined(__CFA_NO_STATISTICS__)231 __attribute__((aligned(64))) struct {232 struct {233 // Push statistic234 struct {235 // number of attemps at pushing something236 volatile size_t attempt;237 238 // number of successes at pushing239 volatile size_t success;240 } push;241 242 // Pop statistic243 struct {244 // number of reads of the mask245 // picking an empty __cfa_readyQ_mask_t counts here246 // but not as an attempt247 volatile size_t maskrds;248 249 // number of attemps at poping something250 volatile size_t attempt;251 252 // number of successes at poping253 volatile size_t success;254 } pop;255 } pick;256 257 // stats on the "used" struct of the queue258 // tracks average number of queues that are not empty259 // when pushing / poping260 struct {261 volatile size_t value;262 volatile size_t count;263 } used;264 } global_stats;265 266 #endif267 };268 269 void ?{}(__ready_queue_t & this);270 void ^?{}(__ready_queue_t & this);271 272 121 //----------------------------------------------------------------------------- 273 122 // Cluster 274 123 struct cluster { 275 124 // Ready queue locks 276 __ clusterRWLock_t ready_lock;125 __spinlock_t ready_queue_lock; 277 126 278 127 // Ready queue for threads 279 __ ready_queue_tready_queue;128 __queue_t($thread) ready_queue; 280 129 281 130 // Name of the cluster -
libcfa/src/concurrency/kernel_private.hfa
r4fa44e7 r730f4f1 84 84 //----------------------------------------------------------------------------- 85 85 // 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)] 87 87 88 88 static inline uint32_t __tls_rand() { … … 103 103 void unregister( struct cluster * cltr, struct processor * proc ); 104 104 105 //=======================================================================106 // Cluster lock API107 //=======================================================================108 struct __attribute__((aligned(64))) __processor_id {109 processor * volatile handle;110 volatile bool lock;111 };112 113 // Lock-Free registering/unregistering of threads114 // Register a processor to a given cluster and get its unique id in return115 unsigned doregister2( struct cluster * cltr, struct processor * proc );116 117 // Unregister a processor from a given cluster using its id, getting back the original pointer118 void unregister2( struct cluster * cltr, struct processor * proc );119 120 //=======================================================================121 // Reader-writer lock implementation122 // Concurrent with doregister/unregister,123 // i.e., threads can be added at any point during or between the entry/exit124 125 //-----------------------------------------------------------------------126 // simple spinlock underlying the RWLock127 // Blocking acquire128 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 acquire137 static inline bool __atomic_try_acquire(volatile bool * ll) {138 return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);139 }140 141 // Release142 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 not149 // creating/destroying queues150 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 section156 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 lock160 // before we read a false.161 // Not needed on x86162 // std::atomic_thread_fence(std::memory_order_seq_cst);163 164 // Step 2 : acquire our local lock165 __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 more179 // 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 API186 //-----------------------------------------------------------------------187 // push thread onto a ready queue for a cluster188 // returns true if the list was previously empty, false otherwise189 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);190 191 //-----------------------------------------------------------------------192 // pop thread from the ready queue of a cluster193 // returns 0p if empty194 __attribute__((hot)) struct $thread * pop(struct cluster * cltr);195 196 //-----------------------------------------------------------------------197 // Increase the width of the ready queue (number of lanes) by 4198 void ready_queue_grow (struct cluster * cltr);199 200 //-----------------------------------------------------------------------201 // Decrease the width of the ready queue (number of lanes) by 4202 void ready_queue_shrink(struct cluster * cltr);203 204 //-----------------------------------------------------------------------205 // Statics call at the end of each thread to register statistics206 #if !defined(__CFA_NO_STATISTICS__)207 void stats_tls_tally(struct cluster * cltr);208 #else209 static inline void stats_tls_tally(struct cluster * cltr) {}210 #endif211 212 105 // Local Variables: // 213 106 // mode: c // -
libcfa/src/concurrency/monitor.cfa
r4fa44e7 r730f4f1 114 114 115 115 // Some one else has the monitor, wait in line for it 116 /* paranoid */ verify( thrd-> link.next == 0p );116 /* paranoid */ verify( thrd->next == 0p ); 117 117 append( this->entry_queue, thrd ); 118 /* paranoid */ verify( thrd-> link.next == 1p );118 /* paranoid */ verify( thrd->next == 1p ); 119 119 120 120 unlock( this->lock ); … … 199 199 200 200 // Some one else has the monitor, wait in line for it 201 /* paranoid */ verify( thrd-> link.next == 0p );201 /* paranoid */ verify( thrd->next == 0p ); 202 202 append( this->entry_queue, thrd ); 203 /* paranoid */ verify( thrd-> link.next == 1p );203 /* paranoid */ verify( thrd->next == 1p ); 204 204 unlock( this->lock ); 205 205 … … 761 761 $thread * new_owner = pop_head( this->entry_queue ); 762 762 /* 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 ); 764 764 __set_owner( this, new_owner ); 765 765 … … 883 883 } 884 884 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 ); 886 886 return ready2run ? node->waiting_thread : 0p; 887 887 } … … 907 907 // For each thread in the entry-queue 908 908 for( $thread ** thrd_it = &entry_queue.head; 909 *thrd_it ;910 thrd_it = &(*thrd_it)-> link.next909 *thrd_it != 1p; 910 thrd_it = &(*thrd_it)->next 911 911 ) { 912 912 // For each acceptable check if it matches -
libcfa/src/concurrency/preemption.cfa
r4fa44e7 r730f4f1 121 121 // If there are still alarms pending, reset the timer 122 122 if( & (*alarms)`first ) { 123 __cfa dbg_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); 124 124 Duration delta = (*alarms)`first.alarm - currtime; 125 125 Duration capped = max(delta, 50`us); -
libcfa/src/concurrency/thread.cfa
r4fa44e7 r730f4f1 35 35 self_mon_p = &self_mon; 36 36 curr_cluster = &cl; 37 link.next = 0p; 38 link.prev = 0p; 37 next = 0p; 39 38 40 39 node.next = 0p; -
libcfa/src/stdhdr/assert.h
r4fa44e7 r730f4f1 33 33 #define verify(x) assert(x) 34 34 #define verifyf(x, ...) assertf(x, __VA_ARGS__) 35 #define verifyfail(...)36 35 #define __CFA_WITH_VERIFY__ 37 36 #else 38 37 #define verify(x) 39 38 #define verifyf(x, ...) 40 #define verifyfail(...)41 39 #endif 42 40 -
tests/concurrent/examples/datingService.cfa
r4fa44e7 r730f4f1 35 35 signal_block( Boys[ccode] ); // restart boy to set phone number 36 36 } // 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; 38 38 return BoyPhoneNo; 39 39 } // DatingService girl … … 47 47 signal_block( Girls[ccode] ); // restart girl to set phone number 48 48 } // if 49 // sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;49 //sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode; 50 50 return GirlPhoneNo; 51 51 } // DatingService boy -
tests/concurrent/waitfor/when.cfa
r4fa44e7 r730f4f1 57 57 58 58 void 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 on61 this.last_call = 6;62 63 59 for( int i = 0; i < N; i++ ) { 64 60 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.