Changes in / [bb2e05e:2bb2efa9]
- Location:
- libcfa/src
- Files:
-
- 5 edited
-
bits/containers.hfa (modified) (1 diff)
-
bits/locks.hfa (modified) (2 diffs)
-
concurrency/kernel.cfa (modified) (13 diffs)
-
concurrency/kernel.hfa (modified) (3 diffs)
-
concurrency/kernel_private.hfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/bits/containers.hfa
rbb2e05e r2bb2efa9 274 274 return this.head != 0; 275 275 } 276 277 void move_to_front( __dllist(T) & src, __dllist(T) & dst, T & node ) {278 remove (src, node);279 push_front(dst, node);280 }281 276 } 282 277 #undef next -
libcfa/src/bits/locks.hfa
rbb2e05e r2bb2efa9 139 139 } 140 140 141 static inline bool post(__bin_sem_t & this) with( this ) { 141 static inline void post(__bin_sem_t & this) with( this ) { 142 verify(__cfaabi_dbg_in_kernel()); 143 142 144 pthread_mutex_lock(&lock); 143 145 bool needs_signal = !signaled; … … 145 147 pthread_mutex_unlock(&lock); 146 148 147 if (needs_signal) pthread_cond_signal(&cond); 148 149 return needs_signal; 149 if (needs_signal) 150 pthread_cond_signal(&cond); 150 151 } 151 152 #endif -
libcfa/src/concurrency/kernel.cfa
rbb2e05e r2bb2efa9 114 114 115 115 //----------------------------------------------------------------------------- 116 // Kernel Scheduling logic117 static $thread * __next_thread(cluster * this);118 static void __run_thread(processor * this, $thread * dst);119 static $thread * __halt(processor * this);120 static bool __wake_one(cluster * cltr, bool was_empty);121 static bool __wake_proc(processor *);122 123 //-----------------------------------------------------------------------------124 116 // Kernel storage 125 117 KERNEL_STORAGE(cluster, mainCluster); … … 228 220 runner.proc = &this; 229 221 230 idle {};222 idleLock{}; 231 223 232 224 __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", &this); … … 242 234 243 235 __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED); 244 __wake_proc( &this );236 wake( &this ); 245 237 246 238 P( terminated ); … … 272 264 // Kernel Scheduling logic 273 265 //============================================================================================= 266 static $thread * __next_thread(cluster * this); 267 static void __run_thread(processor * this, $thread * dst); 268 static void __halt(processor * this); 269 274 270 //Main of the processor contexts 275 271 void main(processorCtx_t & runner) { … … 293 289 $thread * readyThread = 0p; 294 290 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) { 295 // Try to get the next thread296 291 readyThread = __next_thread( this->cltr ); 297 292 298 // If no ready thread 299 if( readyThread == 0p ) { 300 // Block until a thread is ready 301 readyThread = __halt(this); 302 } 303 304 // Check if we actually found a thread 305 if( readyThread ) { 293 if(readyThread) { 306 294 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 307 /* paranoid */ verifyf( readyThread->state == Ready|| readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);295 /* paranoid */ verifyf( readyThread->state == Blocked || readyThread->state == Start || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted); 308 296 /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next ); 309 297 310 // We found a thread run it311 298 __run_thread(this, readyThread); 312 299 313 300 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 301 302 spin_count = 0; 303 } else { 304 // spin(this, &spin_count); 305 __halt(this); 314 306 } 315 307 } … … 320 312 unregister(this->cltr, this); 321 313 322 V( this->terminated ); 314 bool signalled = V( this->terminated ); 315 if(signalled) 323 316 324 317 __cfaabi_dbg_print_safe("Kernel : core %p terminated\n", this); 325 326 // HACK : the coroutine context switch expects this_thread to be set327 // and it make sense for it to be set in all other cases except here328 // fake it329 if( this == mainProcessor ) kernelTLS.this_thread = mainThread;330 318 } 331 319 … … 350 338 if(unlikely(thrd_dst->preempted)) { 351 339 thrd_dst->preempted = __NO_PREEMPTION; 352 verify(thrd_dst->state == Active || thrd_dst->state == Rerun);340 verify(thrd_dst->state == Active || thrd_dst->state == Rerun); 353 341 } else { 354 verify(thrd_dst->state == Blocked || thrd_dst->state == Ready); // Ready means scheduled normally, blocked means rerun342 verify(thrd_dst->state == Start || thrd_dst->state == Primed || thrd_dst->state == Blocked); 355 343 thrd_dst->state = Active; 356 344 } … … 533 521 dst->starter = dst->starter ? dst->starter : &src->self_cor; 534 522 535 // make sure the current state is still correct536 /* paranoid */ verify(src->state == Ready);523 // set state of current coroutine to inactive 524 src->state = src->state == Halted ? Halted : Blocked; 537 525 538 526 // context switch to specified coroutine … … 543 531 mainThread->curr_cor = &mainThread->self_cor; 544 532 545 // make sure the current state has been update546 /* paranoid */ verify(src->state == Active);533 // set state of new coroutine to active 534 src->state = Active; 547 535 548 536 verify( ! kernelTLS.preemption_state.enabled ); … … 582 570 unlock( ready_queue_lock ); 583 571 584 __wake_one(thrd->curr_cluster, was_empty); 572 if(was_empty) { 573 lock (proc_list_lock __cfaabi_dbg_ctx2); 574 if(idles) { 575 wake_fast(idles.head); 576 } 577 unlock (proc_list_lock); 578 } 579 else if( struct processor * idle = idles.head ) { 580 wake_fast(idle); 581 } 585 582 586 583 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 771 768 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 772 769 773 /* paranoid */verify( TL_GET( preemption_state.enabled ) );770 verify( TL_GET( preemption_state.enabled ) ); 774 771 disable_interrupts(); 775 /* paranoid */verify( ! kernelTLS.preemption_state.enabled );772 verify( ! kernelTLS.preemption_state.enabled ); 776 773 777 774 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 803 800 804 801 //============================================================================================= 805 // Kernel Idle Sleep802 // Kernel Quiescing 806 803 //============================================================================================= 807 static $thread * __halt(processor * this) with( *this ) { 808 if( do_terminate ) return 0p; 809 810 // First, lock the cluster idle 811 lock( cltr->idle_lock __cfaabi_dbg_ctx2 ); 812 813 // Check if we can find a thread 814 if( $thread * found = __next_thread( cltr ) ) { 815 unlock( cltr->idle_lock ); 816 return found; 817 } 818 819 // Move this processor from the active list to the idle list 820 move_to_front(cltr->procs, cltr->idles, *this); 821 822 // Unlock the idle lock so we don't go to sleep with a lock 823 unlock (cltr->idle_lock); 824 825 // We are ready to sleep 804 static void __halt(processor * this) with( *this ) { 805 // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) ); 806 807 with( *cltr ) { 808 lock (proc_list_lock __cfaabi_dbg_ctx2); 809 remove (procs, *this); 810 push_front(idles, *this); 811 unlock (proc_list_lock); 812 } 813 826 814 __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this); 827 wait( idle ); 828 829 // We have woken up 815 816 wait( idleLock ); 817 830 818 __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this); 831 819 832 // Get ourself off the idle list833 820 with( *cltr ) { 834 lock (idle_lock __cfaabi_dbg_ctx2); 835 move_to_front(idles, procs, *this); 836 unlock(idle_lock); 837 } 838 839 // Don't check the ready queue again, we may not be in a position to run a thread 840 return 0p; 841 } 842 843 // Wake a thread from the front if there are any 844 static bool __wake_one(cluster * this, __attribute__((unused)) bool force) { 845 // if we don't want to force check if we know it's false 846 if( !this->idles.head && !force ) return false; 847 848 // First, lock the cluster idle 849 lock( this->idle_lock __cfaabi_dbg_ctx2 ); 850 851 // Check if there is someone to wake up 852 if( !this->idles.head ) { 853 // Nope unlock and return false 854 unlock( this->idle_lock ); 855 return false; 856 } 857 858 // Wake them up 859 post( this->idles.head->idle ); 860 861 // Unlock and return true 862 unlock( this->idle_lock ); 863 return true; 864 } 865 866 // Unconditionnaly wake a thread 867 static bool __wake_proc(processor * this) { 868 return post( this->idle ); 821 lock (proc_list_lock __cfaabi_dbg_ctx2); 822 remove (idles, *this); 823 push_front(procs, *this); 824 unlock (proc_list_lock); 825 } 869 826 } 870 827 … … 1010 967 1011 968 void doregister( cluster * cltr, processor * proc ) { 1012 lock (cltr-> idle_lock __cfaabi_dbg_ctx2);969 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 1013 970 cltr->nprocessors += 1; 1014 971 push_front(cltr->procs, *proc); 1015 unlock (cltr-> idle_lock);972 unlock (cltr->proc_list_lock); 1016 973 } 1017 974 1018 975 void unregister( cluster * cltr, processor * proc ) { 1019 lock (cltr-> idle_lock __cfaabi_dbg_ctx2);976 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 1020 977 remove(cltr->procs, *proc ); 1021 978 cltr->nprocessors -= 1; 1022 unlock(cltr-> idle_lock);979 unlock(cltr->proc_list_lock); 1023 980 } 1024 981 -
libcfa/src/concurrency/kernel.hfa
rbb2e05e r2bb2efa9 76 76 bool pending_preemption; 77 77 78 // Idle lock (kernel semaphore)79 __bin_sem_t idle ;78 // Idle lock 79 __bin_sem_t idleLock; 80 80 81 81 // Termination … … 83 83 volatile bool do_terminate; 84 84 85 // Termination synchronisation (user semaphore)85 // Termination synchronisation 86 86 semaphore terminated; 87 87 … … 126 126 127 127 // List of processors 128 __spinlock_t idle_lock;128 __spinlock_t proc_list_lock; 129 129 __dllist_t(struct processor) procs; 130 130 __dllist_t(struct processor) idles; -
libcfa/src/concurrency/kernel_private.hfa
rbb2e05e r2bb2efa9 42 42 void * __create_pthread( pthread_t *, void * (*)(void *), void * ); 43 43 44 static inline void wake_fast(processor * this) { 45 __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this); 46 post( this->idleLock ); 47 } 44 48 49 static inline void wake(processor * this) { 50 disable_interrupts(); 51 wake_fast(this); 52 enable_interrupts( __cfaabi_dbg_ctx ); 53 } 45 54 46 55 struct event_kernel_t {
Note:
See TracChangeset
for help on using the changeset viewer.