Changes in / [730f4f1:4fa44e7]
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
r730f4f1 r4fa44e7 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 ${thread_headers:.hfa=.cfa}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} 51 51 else 52 52 headers = -
libcfa/src/Makefile.in
r730f4f1 r4fa44e7 166 166 concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \ 167 167 concurrency/invoke.c concurrency/io.cfa \ 168 concurrency/preemption.cfa concurrency/coroutine.cfa \ 169 concurrency/thread.cfa concurrency/kernel.cfa \ 170 concurrency/monitor.cfa concurrency/mutex.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 171 172 @BUILDLIB_TRUE@am__objects_3 = concurrency/coroutine.lo \ 172 173 @BUILDLIB_TRUE@ concurrency/thread.lo concurrency/kernel.lo \ … … 176 177 @BUILDLIB_TRUE@ concurrency/alarm.lo concurrency/invoke.lo \ 177 178 @BUILDLIB_TRUE@ concurrency/io.lo concurrency/preemption.lo \ 178 @BUILDLIB_TRUE@ $(am__objects_3)179 @BUILDLIB_TRUE@ concurrency/ready_queue.lo $(am__objects_3) 179 180 am_libcfathread_la_OBJECTS = $(am__objects_4) 180 181 libcfathread_la_OBJECTS = $(am_libcfathread_la_OBJECTS) … … 477 478 @BUILDLIB_FALSE@thread_headers = 478 479 @BUILDLIB_TRUE@thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa concurrency/monitor.hfa concurrency/mutex.hfa 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}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} 480 481 481 482 #---------------------------------------------------------------------------------------------------------------- … … 615 616 concurrency/$(DEPDIR)/$(am__dirstamp) 616 617 concurrency/preemption.lo: concurrency/$(am__dirstamp) \ 618 concurrency/$(DEPDIR)/$(am__dirstamp) 619 concurrency/ready_queue.lo: concurrency/$(am__dirstamp) \ 617 620 concurrency/$(DEPDIR)/$(am__dirstamp) 618 621 concurrency/coroutine.lo: concurrency/$(am__dirstamp) \ -
libcfa/src/bits/debug.hfa
r730f4f1 r4fa44e7 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__) 54 || defined(__CFA_DEBUG_PRINT_RUNTIME_CORE__) || defined(__CFA_DEBUG_PRINT_EXCEPTION__) \ 55 || defined(__CFA_DEBUG_PRINT_READY_QUEUE__) 55 56 #include <stdio.h> 56 57 #include <unistd.h> -
libcfa/src/bits/defs.hfa
r730f4f1 r4fa44e7 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 #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
r730f4f1 r4fa44e7 161 161 }; 162 162 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 163 171 struct $thread { 164 172 // Core threading fields … … 192 200 // Link lists fields 193 201 // instrusive link field for threads 194 struct $thread * next;202 struct __thread_desc_link link; 195 203 196 204 struct { … … 218 226 #ifdef __cforall 219 227 extern "Cforall" { 228 220 229 static inline $thread *& get_next( $thread & this ) __attribute__((const)) { 221 return this. next;230 return this.link.next; 222 231 } 223 232 -
libcfa/src/concurrency/kernel.cfa
r730f4f1 r4fa44e7 120 120 static void __run_thread(processor * this, $thread * dst); 121 121 static $thread * __halt(processor * this); 122 static bool __wake_one(cluster * cltr , bool was_empty);122 static bool __wake_one(cluster * cltr); 123 123 static bool __wake_proc(processor *); 124 124 … … 197 197 self_mon.recursion = 1; 198 198 self_mon_p = &self_mon; 199 next = 0p; 199 link.next = 0p; 200 link.prev = 0p; 200 201 201 202 node.next = 0p; … … 223 224 this.name = name; 224 225 this.cltr = &cltr; 226 id = -1u; 225 227 terminated{ 0 }; 226 228 destroyer = 0p; … … 260 262 this.preemption_rate = preemption_rate; 261 263 ready_queue{}; 262 ready_ queue_lock{};264 ready_lock{}; 263 265 264 266 #if !defined(__CFA_NO_STATISTICS__) … … 295 297 __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this); 296 298 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 297 305 doregister(this->cltr, this); 298 306 … … 318 326 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 319 327 /* paranoid */ verifyf( readyThread->state == Ready || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted); 320 /* paranoid */ verifyf( readyThread-> next == 0p, "Expected null got %p", readyThread->next );328 /* paranoid */ verifyf( readyThread->link.next == 0p, "Expected null got %p", readyThread->link.next ); 321 329 322 330 // We found a thread run it … … 334 342 V( this->terminated ); 335 343 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 336 356 __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this); 337 357 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; 358 stats_tls_tally(this->cltr); 342 359 } 343 360 … … 591 608 // Scheduler routines 592 609 // KERNEL ONLY 593 void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) { 610 void __schedule_thread( $thread * thrd ) { 611 /* paranoid */ verify( thrd ); 612 /* paranoid */ verify( thrd->state != Halted ); 594 613 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 595 614 /* paranoid */ #if defined( __CFA_WITH_VERIFY__ ) 596 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,597 598 /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,599 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 ); 600 619 /* paranoid */ #endif 601 /* paranoid */ verifyf( thrd-> next == 0p, "Expected null got %p", thrd->next );620 /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next ); 602 621 603 622 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 604 623 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); 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); 611 629 612 630 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 617 635 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 618 636 619 lock( ready_queue_lock __cfaabi_dbg_ctx2);620 $thread * head = pop_head( ready_queue);621 unlock( ready_queue_lock);637 ready_schedule_lock(this, kernelTLS.this_processor); 638 $thread * head = pop( this ); 639 ready_schedule_unlock(this, kernelTLS.this_processor); 622 640 623 641 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 703 721 // If that is the case, abandon the preemption. 704 722 bool preempted = false; 705 if(thrd-> next == 0p) {723 if(thrd->link.next == 0p) { 706 724 preempted = true; 707 725 thrd->preempted = reason; … … 763 781 pending_preemption = false; 764 782 kernel_thread = pthread_self(); 783 id = -1u; 765 784 766 785 runner{ &this }; … … 772 791 mainProcessor = (processor *)&storage_mainProcessor; 773 792 (*mainProcessor){}; 793 794 mainProcessor->id = doregister2(mainCluster, mainProcessor); 774 795 775 796 //initialize the global state variables … … 826 847 kernel_stop_preemption(); 827 848 849 unregister2(mainCluster, mainProcessor); 850 828 851 // Destroy the main processor and its context in reverse order of construction 829 852 // These were manually constructed so we need manually destroy them 830 853 void ^?{}(processor & this) with( this ){ 831 854 /* paranoid */ verify( this.do_terminate == true ); 855 __cfaabi_dbg_print_safe("Kernel : destroyed main processor context %p\n", &runner); 832 856 } 833 857 … … 835 859 836 860 // Final step, destroy the main thread since it is no longer needed 861 837 862 // Since we provided a stack to this taxk it will not destroy anything 838 863 /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1)); … … 887 912 888 913 // Wake a thread from the front if there are any 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 914 static bool __wake_one(cluster * this) { 893 915 // First, lock the cluster idle 894 916 lock( this->idle_lock __cfaabi_dbg_ctx2 ); -
libcfa/src/concurrency/kernel.hfa
r730f4f1 r4fa44e7 60 60 // Cluster from which to get threads 61 61 struct cluster * cltr; 62 unsigned int id; 62 63 63 64 // Name of the processor … … 92 93 93 94 // Link lists fields 94 struct __dbg_node_ proc{95 structprocessor * next;96 structprocessor * prev;95 struct __dbg_node_cltr { 96 processor * next; 97 processor * prev; 97 98 } node; 98 99 … … 119 120 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 120 121 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 121 272 //----------------------------------------------------------------------------- 122 273 // Cluster 123 274 struct cluster { 124 275 // Ready queue locks 125 __ spinlock_t ready_queue_lock;276 __clusterRWLock_t ready_lock; 126 277 127 278 // Ready queue for threads 128 __ queue_t($thread)ready_queue;279 __ready_queue_t ready_queue; 129 280 130 281 // Name of the cluster -
libcfa/src/concurrency/kernel_private.hfa
r730f4f1 r4fa44e7 84 84 //----------------------------------------------------------------------------- 85 85 // 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)] 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 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 105 212 // Local Variables: // 106 213 // mode: c // -
libcfa/src/concurrency/monitor.cfa
r730f4f1 r4fa44e7 114 114 115 115 // Some one else has the monitor, wait in line for it 116 /* paranoid */ verify( thrd-> next == 0p );116 /* paranoid */ verify( thrd->link.next == 0p ); 117 117 append( this->entry_queue, thrd ); 118 /* paranoid */ verify( thrd-> next == 1p );118 /* paranoid */ verify( thrd->link.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-> next == 0p );201 /* paranoid */ verify( thrd->link.next == 0p ); 202 202 append( this->entry_queue, thrd ); 203 /* paranoid */ verify( thrd-> next == 1p );203 /* paranoid */ verify( thrd->link.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-> next == 0p );763 /* paranoid */ verify( !new_owner || new_owner->link.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 ? node->waiting_thread :0p );885 __cfaabi_dbg_print_safe( "Kernel : Runing %i (%p)\n", ready2run, ready2run ? (thread*)node->waiting_thread : (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 != 1p;910 thrd_it = &(*thrd_it)-> next909 *thrd_it; 910 thrd_it = &(*thrd_it)->link.next 911 911 ) { 912 912 // For each acceptable check if it matches -
libcfa/src/concurrency/preemption.cfa
r730f4f1 r4fa44e7 121 121 // If there are still alarms pending, reset the timer 122 122 if( & (*alarms)`first ) { 123 __cfa abi_dbg_print_buffer_decl(" KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);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); 124 124 Duration delta = (*alarms)`first.alarm - currtime; 125 125 Duration capped = max(delta, 50`us); -
libcfa/src/concurrency/thread.cfa
r730f4f1 r4fa44e7 35 35 self_mon_p = &self_mon; 36 36 curr_cluster = &cl; 37 next = 0p; 37 link.next = 0p; 38 link.prev = 0p; 38 39 39 40 node.next = 0p; -
libcfa/src/stdhdr/assert.h
r730f4f1 r4fa44e7 33 33 #define verify(x) assert(x) 34 34 #define verifyf(x, ...) assertf(x, __VA_ARGS__) 35 #define verifyfail(...) 35 36 #define __CFA_WITH_VERIFY__ 36 37 #else 37 38 #define verify(x) 38 39 #define verifyf(x, ...) 40 #define verifyfail(...) 39 41 #endif 40 42 -
tests/concurrent/examples/datingService.cfa
r730f4f1 r4fa44e7 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
r730f4f1 r4fa44e7 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 on 61 this.last_call = 6; 62 59 63 for( int i = 0; i < N; i++ ) { 60 64 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.