Changes in / [5fec3f6:387c9a1]
- Location:
- src
- Files:
-
- 10 edited
-
Common/Heap.cc (modified) (2 diffs)
-
libcfa/bits/containers.h (modified) (1 diff)
-
libcfa/concurrency/coroutine (modified) (5 diffs)
-
libcfa/concurrency/coroutine.c (modified) (3 diffs)
-
libcfa/concurrency/invoke.h (modified) (2 diffs)
-
libcfa/concurrency/kernel (modified) (2 diffs)
-
libcfa/concurrency/kernel.c (modified) (34 diffs)
-
libcfa/concurrency/monitor.c (modified) (11 diffs)
-
libcfa/concurrency/preemption.c (modified) (5 diffs)
-
libcfa/concurrency/thread.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Heap.cc
r5fec3f6 r387c9a1 130 130 abort(); 131 131 } 132 #endif // RTLD_NEXT132 #endif 133 133 } // if 134 134 … … 144 144 fptr = (generic_fptr_t)dlsym( library, symbol ); 145 145 #endif // _GNU_SOURCE 146 147 error = dlerror();148 if ( error ) {149 std::cerr << "interpose_symbol : internal error, " << error << std::endl;150 abort();151 }152 153 return fptr;154 }155 146 156 147 extern "C" { -
src/libcfa/bits/containers.h
r5fec3f6 r387c9a1 186 186 #endif 187 187 188 189 //-----------------------------------------------------------------------------190 // Doubly Linked List191 //-----------------------------------------------------------------------------192 #ifdef __cforall193 trait is_db_node(dtype T) {194 T*& get_next( T& );195 T*& get_prev( T& );196 };197 #endif198 199 #ifdef __cforall200 forall(dtype TYPE | is_db_node(TYPE))201 #define T TYPE202 #else203 #define T void204 #endif205 struct __dllist {206 T * head;207 };208 #undef T209 210 #ifdef __cforall211 #define __dllist_t(T) __dllist(T)212 #else213 #define __dllist_t(T) struct __dllist214 #endif215 216 #ifdef __cforall217 218 forall(dtype T | is_db_node(T))219 static inline void ?{}( __dllist(T) & this ) with( this ) {220 head{ NULL };221 }222 223 // forall(dtype T | is_db_node(T) | sized(T))224 // static inline void push_front( __dllist(T) & this, T & node ) with( this ) {225 // if ( head ) {226 // get_next( node ) = head;227 // get_prev( node ) = get_prev( *head );228 // // inserted node must be consistent before it is seen229 // // prevent code movement across barrier230 // asm( "" : : : "memory" );231 // get_prev( *head ) = node;232 // T & prev = *get_prev( node );233 // get_next( prev ) = node;234 // }235 // else {236 // get_next( node ) = &node;237 // get_prev( node ) = &node;238 // }239 240 // // prevent code movement across barrier241 // asm( "" : : : "memory" );242 // head = val;243 // }244 245 // forall(dtype T | is_db_node(T) | sized(T))246 // static inline T * remove( __dllist(T) & this, T & node ) with( this ) {247 // if ( &node == head ) {248 // if ( get_next( *head ) == head ) {249 // head = NULL;250 // }251 // else {252 // head = get_next( *head );253 // }254 // }255 // get_prev( *get_next( node ) ) = get_prev( node );256 // get_next( *get_prev( node ) ) = get_next( node );257 // get_next( node ) = NULL;258 // get_prev( node ) = NULL;259 // }260 #endif261 262 188 //----------------------------------------------------------------------------- 263 189 // Tools -
src/libcfa/concurrency/coroutine
r5fec3f6 r387c9a1 72 72 // Suspend implementation inlined for performance 73 73 static inline void suspend() { 74 // optimization : read TLS once and reuse it 75 // Safety note: this is preemption safe since if 76 // preemption occurs after this line, the pointer 77 // will also migrate which means this value will 78 // stay in syn with the TLS 79 coroutine_desc * src = TL_GET( this_coroutine ); 74 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 80 75 81 76 assertf( src->last != 0, … … 94 89 forall(dtype T | is_coroutine(T)) 95 90 static inline void resume(T & cor) { 96 // optimization : read TLS once and reuse it 97 // Safety note: this is preemption safe since if 98 // preemption occurs after this line, the pointer 99 // will also migrate which means this value will 100 // stay in syn with the TLS 101 coroutine_desc * src = TL_GET( this_coroutine ); 91 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 102 92 coroutine_desc * dst = get_coroutine(cor); 103 93 … … 117 107 dst->last = src; 118 108 dst->starter = dst->starter ? dst->starter : src; 119 } 109 } // if 120 110 121 111 // always done for performance testing … … 124 114 125 115 static inline void resume(coroutine_desc * dst) { 126 // optimization : read TLS once and reuse it 127 // Safety note: this is preemption safe since if 128 // preemption occurs after this line, the pointer 129 // will also migrate which means this value will 130 // stay in syn with the TLS 131 coroutine_desc * src = TL_GET( this_coroutine ); 116 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 132 117 133 118 // not resuming self ? … … 140 125 // set last resumer 141 126 dst->last = src; 142 } 127 } // if 143 128 144 129 // always done for performance testing -
src/libcfa/concurrency/coroutine.c
r5fec3f6 r387c9a1 84 84 // Wrapper for co 85 85 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 86 // Safety note : This could cause some false positives due to preemption87 86 verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate ); 88 87 disable_interrupts(); … … 92 91 93 92 // set new coroutine that task is executing 94 kernelTLS.this_coroutine = dst;93 TL_SET( this_coroutine, dst ); 95 94 96 95 // context switch to specified coroutine … … 103 102 104 103 enable_interrupts( __cfaabi_dbg_ctx ); 105 // Safety note : This could cause some false positives due to preemption106 104 verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate ); 107 105 } //ctxSwitchDirect -
src/libcfa/concurrency/invoke.h
r5fec3f6 r387c9a1 18 18 #include "bits/locks.h" 19 19 20 #define TL_GET( member ) kernelT LS.member21 #define TL_SET( member, value ) kernelT LS.member = value;20 #define TL_GET( member ) kernelThreadData.member 21 #define TL_SET( member, value ) kernelThreadData.member = value; 22 22 23 23 #ifdef __cforall … … 44 44 volatile bool in_progress; 45 45 } preemption_state; 46 } kernelT LS;46 } kernelThreadData; 47 47 } 48 48 49 49 static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); } 50 static inline struct thread_desc * volatile active_thread () { return TL_GET( this_thread); }51 // static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE50 static inline struct thread_desc * volatile active_thread() { return TL_GET( this_thread ); } 51 static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); } 52 52 #endif 53 53 -
src/libcfa/concurrency/kernel
r5fec3f6 r387c9a1 53 53 // Preemption rate on this cluster 54 54 Duration preemption_rate; 55 56 // List of idle processors57 // __dllist_t(struct processor) idles;58 55 }; 59 56 … … 127 124 bool pending_preemption; 128 125 129 struct {130 pthread_mutex_t lock;131 pthread_cond_t cond;132 } idle;133 134 126 #ifdef __CFA_DEBUG__ 135 127 // Last function to enable preemption on this processor -
src/libcfa/concurrency/kernel.c
r5fec3f6 r387c9a1 56 56 // volatile thread_local unsigned short disable_preempt_count = 1; 57 57 58 thread_local struct KernelThreadData kernelT LS= {58 thread_local struct KernelThreadData kernelThreadData = { 59 59 NULL, 60 60 NULL, … … 155 155 terminate(&this); 156 156 verify(this.do_terminate); 157 verify( kernelTLS.this_processor!= &this);157 verify(TL_GET( this_processor ) != &this); 158 158 P( terminated ); 159 verify( kernelTLS.this_processor!= &this);159 verify(TL_GET( this_processor ) != &this); 160 160 pthread_join( kernel_thread, NULL ); 161 161 } … … 196 196 if(readyThread) 197 197 { 198 verify( ! kernelTLS.preemption_state.enabled );198 verify( ! TL_GET( preemption_state ).enabled ); 199 199 200 200 runThread(this, readyThread); 201 201 202 verify( ! kernelTLS.preemption_state.enabled );202 verify( ! TL_GET( preemption_state ).enabled ); 203 203 204 204 //Some actions need to be taken from the kernel … … 221 221 } 222 222 223 // KERNEL ONLY224 223 // runThread runs a thread by context switching 225 224 // from the processor coroutine to the target thread … … 229 228 coroutine_desc * thrd_cor = dst->curr_cor; 230 229 231 // Reset the terminating actions here230 //Reset the terminating actions here 232 231 this->finish.action_code = No_Action; 233 232 234 // Update global state235 kernelTLS.this_thread = dst;233 //Update global state 234 TL_SET( this_thread, dst ); 236 235 237 236 // Context Switch to the thread … … 240 239 } 241 240 242 // KERNEL_ONLY243 241 void returnToKernel() { 244 coroutine_desc * proc_cor = get_coroutine( kernelTLS.this_processor->runner);245 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine;242 coroutine_desc * proc_cor = get_coroutine(TL_GET( this_processor )->runner); 243 coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine ); 246 244 ThreadCtxSwitch(thrd_cor, proc_cor); 247 245 } 248 246 249 // KERNEL_ONLY250 247 // Once a thread has finished running, some of 251 248 // its final actions must be executed from the kernel 252 249 void finishRunning(processor * this) with( this->finish ) { 253 250 if( action_code == Release ) { 254 verify( ! kernelTLS.preemption_state.enabled );251 verify( ! TL_GET( preemption_state ).enabled ); 255 252 unlock( *lock ); 256 253 } … … 259 256 } 260 257 else if( action_code == Release_Schedule ) { 261 verify( ! kernelTLS.preemption_state.enabled );258 verify( ! TL_GET( preemption_state ).enabled ); 262 259 unlock( *lock ); 263 260 ScheduleThread( thrd ); 264 261 } 265 262 else if( action_code == Release_Multi ) { 266 verify( ! kernelTLS.preemption_state.enabled );263 verify( ! TL_GET( preemption_state ).enabled ); 267 264 for(int i = 0; i < lock_count; i++) { 268 265 unlock( *locks[i] ); … … 288 285 } 289 286 290 // KERNEL_ONLY291 287 // Context invoker for processors 292 288 // This is the entry point for processors (kernel threads) … … 294 290 void * CtxInvokeProcessor(void * arg) { 295 291 processor * proc = (processor *) arg; 296 kernelTLS.this_processor = proc;297 kernelTLS.this_coroutine = NULL;298 kernelTLS.this_thread = NULL;299 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];292 TL_SET( this_processor, proc ); 293 TL_SET( this_coroutine, NULL ); 294 TL_SET( this_thread, NULL ); 295 TL_GET( preemption_state ).[enabled, disable_count] = [false, 1]; 300 296 // SKULLDUGGERY: We want to create a context for the processor coroutine 301 297 // which is needed for the 2-step context switch. However, there is no reason … … 309 305 310 306 //Set global state 311 kernelTLS.this_coroutine = get_coroutine(proc->runner);312 kernelTLS.this_thread = NULL;307 TL_SET( this_coroutine, get_coroutine(proc->runner) ); 308 TL_SET( this_thread, NULL ); 313 309 314 310 //We now have a proper context from which to schedule threads … … 337 333 } 338 334 339 // KERNEL_ONLY340 335 void kernel_first_resume(processor * this) { 341 coroutine_desc * src = kernelTLS.this_coroutine;336 coroutine_desc * src = TL_GET( this_coroutine ); 342 337 coroutine_desc * dst = get_coroutine(this->runner); 343 338 344 verify( ! kernelTLS.preemption_state.enabled );339 verify( ! TL_GET( preemption_state ).enabled ); 345 340 346 341 create_stack(&dst->stack, dst->stack.size); 347 342 CtxStart(&this->runner, CtxInvokeCoroutine); 348 343 349 verify( ! kernelTLS.preemption_state.enabled );344 verify( ! TL_GET( preemption_state ).enabled ); 350 345 351 346 dst->last = src; … … 356 351 357 352 // set new coroutine that task is executing 358 kernelTLS.this_coroutine = dst;353 TL_SET( this_coroutine, dst ); 359 354 360 355 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. … … 373 368 src->state = Active; 374 369 375 verify( ! kernelTLS.preemption_state.enabled );370 verify( ! TL_GET( preemption_state ).enabled ); 376 371 } 377 372 378 373 //----------------------------------------------------------------------------- 379 374 // Scheduler routines 380 381 // KERNEL ONLY382 375 void ScheduleThread( thread_desc * thrd ) { 376 // if( ! thrd ) return; 383 377 verify( thrd ); 384 378 verify( thrd->self_cor.state != Halted ); 385 379 386 verify( ! kernelTLS.preemption_state.enabled );380 verify( ! TL_GET( preemption_state ).enabled ); 387 381 388 382 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); … … 394 388 } 395 389 396 verify( ! kernelTLS.preemption_state.enabled ); 397 } 398 399 // KERNEL ONLY 390 verify( ! TL_GET( preemption_state ).enabled ); 391 } 392 400 393 thread_desc * nextThread(cluster * this) with( *this ) { 401 verify( ! kernelTLS.preemption_state.enabled );394 verify( ! TL_GET( preemption_state ).enabled ); 402 395 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 403 396 thread_desc * head = pop_head( ready_queue ); 404 397 unlock( ready_queue_lock ); 405 verify( ! kernelTLS.preemption_state.enabled );398 verify( ! TL_GET( preemption_state ).enabled ); 406 399 return head; 407 400 } … … 409 402 void BlockInternal() { 410 403 disable_interrupts(); 411 verify( ! kernelTLS.preemption_state.enabled );404 verify( ! TL_GET( preemption_state ).enabled ); 412 405 returnToKernel(); 413 verify( ! kernelTLS.preemption_state.enabled );406 verify( ! TL_GET( preemption_state ).enabled ); 414 407 enable_interrupts( __cfaabi_dbg_ctx ); 415 408 } … … 417 410 void BlockInternal( __spinlock_t * lock ) { 418 411 disable_interrupts(); 419 with( * kernelTLS.this_processor) {412 with( *TL_GET( this_processor ) ) { 420 413 finish.action_code = Release; 421 414 finish.lock = lock; 422 415 } 423 416 424 verify( ! preemption_state.enabled );417 verify( ! TL_GET( preemption_state ).enabled ); 425 418 returnToKernel(); 426 verify( ! preemption_state.enabled );419 verify( ! TL_GET( preemption_state ).enabled ); 427 420 428 421 enable_interrupts( __cfaabi_dbg_ctx ); … … 431 424 void BlockInternal( thread_desc * thrd ) { 432 425 disable_interrupts(); 433 with( * kernelTLS.this_processor) {426 with( *TL_GET( this_processor ) ) { 434 427 finish.action_code = Schedule; 435 428 finish.thrd = thrd; 436 429 } 437 430 438 verify( ! kernelTLS.preemption_state.enabled );431 verify( ! TL_GET( preemption_state ).enabled ); 439 432 returnToKernel(); 440 verify( ! kernelTLS.preemption_state.enabled );433 verify( ! TL_GET( preemption_state ).enabled ); 441 434 442 435 enable_interrupts( __cfaabi_dbg_ctx ); … … 446 439 assert(thrd); 447 440 disable_interrupts(); 448 with( * kernelTLS.this_processor) {441 with( *TL_GET( this_processor ) ) { 449 442 finish.action_code = Release_Schedule; 450 443 finish.lock = lock; … … 452 445 } 453 446 454 verify( ! kernelTLS.preemption_state.enabled );447 verify( ! TL_GET( preemption_state ).enabled ); 455 448 returnToKernel(); 456 verify( ! kernelTLS.preemption_state.enabled );449 verify( ! TL_GET( preemption_state ).enabled ); 457 450 458 451 enable_interrupts( __cfaabi_dbg_ctx ); … … 461 454 void BlockInternal(__spinlock_t * locks [], unsigned short count) { 462 455 disable_interrupts(); 463 with( * kernelTLS.this_processor) {456 with( *TL_GET( this_processor ) ) { 464 457 finish.action_code = Release_Multi; 465 458 finish.locks = locks; … … 467 460 } 468 461 469 verify( ! kernelTLS.preemption_state.enabled );462 verify( ! TL_GET( preemption_state ).enabled ); 470 463 returnToKernel(); 471 verify( ! kernelTLS.preemption_state.enabled );464 verify( ! TL_GET( preemption_state ).enabled ); 472 465 473 466 enable_interrupts( __cfaabi_dbg_ctx ); … … 476 469 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 477 470 disable_interrupts(); 478 with( * kernelTLS.this_processor) {471 with( *TL_GET( this_processor ) ) { 479 472 finish.action_code = Release_Multi_Schedule; 480 473 finish.locks = locks; … … 484 477 } 485 478 486 verify( ! kernelTLS.preemption_state.enabled );479 verify( ! TL_GET( preemption_state ).enabled ); 487 480 returnToKernel(); 488 verify( ! kernelTLS.preemption_state.enabled );481 verify( ! TL_GET( preemption_state ).enabled ); 489 482 490 483 enable_interrupts( __cfaabi_dbg_ctx ); 491 484 } 492 485 493 // KERNEL ONLY494 486 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 495 verify( ! kernelTLS.preemption_state.enabled );496 with( * kernelTLS.this_processor) {487 verify( ! TL_GET( preemption_state ).enabled ); 488 with( *TL_GET( this_processor ) ) { 497 489 finish.action_code = thrd ? Release_Schedule : Release; 498 490 finish.lock = lock; … … 509 501 // Kernel boot procedures 510 502 void kernel_startup(void) { 511 verify( ! kernelTLS.preemption_state.enabled );503 verify( ! TL_GET( preemption_state ).enabled ); 512 504 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 513 505 … … 555 547 556 548 //initialize the global state variables 557 kernelTLS.this_processor = mainProcessor;558 kernelTLS.this_thread = mainThread;559 kernelTLS.this_coroutine = &mainThread->self_cor;549 TL_SET( this_processor, mainProcessor ); 550 TL_SET( this_thread, mainThread ); 551 TL_SET( this_coroutine, &mainThread->self_cor ); 560 552 561 553 // Enable preemption … … 569 561 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 570 562 // mainThread is on the ready queue when this call is made. 571 kernel_first_resume( kernelTLS.this_processor);563 kernel_first_resume( TL_GET( this_processor ) ); 572 564 573 565 … … 576 568 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 577 569 578 verify( ! kernelTLS.preemption_state.enabled );570 verify( ! TL_GET( preemption_state ).enabled ); 579 571 enable_interrupts( __cfaabi_dbg_ctx ); 580 572 verify( TL_GET( preemption_state ).enabled ); … … 586 578 verify( TL_GET( preemption_state ).enabled ); 587 579 disable_interrupts(); 588 verify( ! kernelTLS.preemption_state.enabled );580 verify( ! TL_GET( preemption_state ).enabled ); 589 581 590 582 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 610 602 __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n"); 611 603 } 612 613 //=============================================================================================614 // Kernel Quiescing615 //=============================================================================================616 617 // void halt(processor * this) with( this ) {618 // pthread_mutex_lock( &idle.lock );619 620 621 622 // // SKULLDUGGERY: Even if spurious wake-up is a thing623 // // spuriously waking up a kernel thread is not a big deal624 // // if it is very rare.625 // pthread_cond_wait( &idle.cond, &idle.lock);626 // pthread_mutex_unlock( &idle.lock );627 // }628 629 // void wake(processor * this) with( this ) {630 // pthread_mutex_lock (&idle.lock);631 // pthread_cond_signal (&idle.cond);632 // pthread_mutex_unlock(&idle.lock);633 // }634 604 635 605 //============================================================================================= … … 663 633 } 664 634 665 return kernelTLS.this_thread;635 return TL_GET( this_thread ); 666 636 } 667 637 … … 672 642 __cfaabi_dbg_bits_write( abort_text, len ); 673 643 674 if ( get_coroutine(thrd) != kernelTLS.this_coroutine) {675 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine);644 if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) { 645 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) ); 676 646 __cfaabi_dbg_bits_write( abort_text, len ); 677 647 } … … 682 652 683 653 int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) { 684 return get_coroutine( kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2;654 return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2; 685 655 } 686 656 … … 712 682 if ( count < 0 ) { 713 683 // queue current task 714 append( waiting, kernelTLS.this_thread);684 append( waiting, (thread_desc *)TL_GET( this_thread ) ); 715 685 716 686 // atomically release spin lock and block … … 772 742 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) { 773 743 this.prev_name = prev_name; 774 this.prev_thrd = kernelTLS.this_thread;744 this.prev_thrd = TL_GET( this_thread ); 775 745 } 776 746 ) -
src/libcfa/concurrency/monitor.c
r5fec3f6 r387c9a1 85 85 // Lock the monitor spinlock 86 86 lock( this->lock __cfaabi_dbg_ctx2 ); 87 // Interrupts disable inside critical section 88 thread_desc * thrd = kernelTLS.this_thread; 87 thread_desc * thrd = TL_GET( this_thread ); 89 88 90 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); … … 135 134 // Lock the monitor spinlock 136 135 lock( this->lock __cfaabi_dbg_ctx2 ); 137 // Interrupts disable inside critical section 138 thread_desc * thrd = kernelTLS.this_thread; 136 thread_desc * thrd = TL_GET( this_thread ); 139 137 140 138 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); … … 170 168 171 169 // Create the node specific to this wait operation 172 wait_ctx_primed( thrd, 0 )170 wait_ctx_primed( TL_GET( this_thread ), 0 ) 173 171 174 172 // Some one else has the monitor, wait for him to finish and then run … … 181 179 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 182 180 183 wait_ctx( thrd, 0 )181 wait_ctx( TL_GET( this_thread ), 0 ) 184 182 this->dtor_node = &waiter; 185 183 … … 201 199 lock( this->lock __cfaabi_dbg_ctx2 ); 202 200 203 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);204 205 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );201 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", TL_GET( this_thread ), this, this->owner); 202 203 verifyf( TL_GET( this_thread ) == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", TL_GET( this_thread ), this->owner, this->recursion, this ); 206 204 207 205 // Leaving a recursion level, decrement the counter … … 291 289 // Sorts monitors before entering 292 290 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) { 293 thread_desc * thrd = TL_GET( this_thread );294 295 291 // Store current array 296 292 this.m = m; … … 301 297 302 298 // Save previous thread context 303 this.prev = thrd->monitors;299 this.prev = TL_GET( this_thread )->monitors; 304 300 305 301 // Update thread context (needed for conditions) 306 ( thrd->monitors){m, count, func};302 (TL_GET( this_thread )->monitors){m, count, func}; 307 303 308 304 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count); … … 332 328 // Sorts monitors before entering 333 329 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) { 334 // optimization335 thread_desc * thrd = TL_GET( this_thread );336 337 330 // Store current array 338 331 this.m = *m; 339 332 340 333 // Save previous thread context 341 this.prev = thrd->monitors;334 this.prev = TL_GET( this_thread )->monitors; 342 335 343 336 // Update thread context (needed for conditions) 344 ( thrd->monitors){m, 1, func};337 (TL_GET( this_thread )->monitors){m, 1, func}; 345 338 346 339 __enter_monitor_dtor( this.m, func ); … … 573 566 574 567 // Create the node specific to this wait operation 575 wait_ctx_primed( kernelTLS.this_thread, 0 );568 wait_ctx_primed( TL_GET( this_thread ), 0 ); 576 569 577 570 // Save monitor states … … 619 612 620 613 // Create the node specific to this wait operation 621 wait_ctx_primed( kernelTLS.this_thread, 0 );614 wait_ctx_primed( TL_GET( this_thread ), 0 ); 622 615 623 616 monitor_save; … … 625 618 626 619 for( __lock_size_t i = 0; i < count; i++) { 627 verify( monitors[i]->owner == kernelTLS.this_thread);620 verify( monitors[i]->owner == TL_GET( this_thread ) ); 628 621 } 629 622 -
src/libcfa/concurrency/preemption.c
r5fec3f6 r387c9a1 234 234 } 235 235 236 // KERNEL ONLY 236 237 237 // Check if a CtxSwitch signal handler shoud defer 238 238 // If true : preemption is safe 239 239 // If false : preemption is unsafe and marked as pending 240 240 static inline bool preemption_ready() { 241 // Check if preemption is safe 242 bool ready = kernelTLS.preemption_state.enabled && ! kernelTLS.preemption_state.in_progress; 243 244 // Adjust the pending flag accordingly 245 kernelTLS.this_processor->pending_preemption = !ready; 241 bool ready = TL_GET( preemption_state ).enabled && !TL_GET( preemption_state ).in_progress; // Check if preemption is safe 242 TL_GET( this_processor )->pending_preemption = !ready; // Adjust the pending flag accordingly 246 243 return ready; 247 244 } … … 257 254 258 255 // Start with preemption disabled until ready 259 kernelTLS.preemption_state.enabled = false;260 kernelTLS.preemption_state.disable_count = 1;256 TL_GET( preemption_state ).enabled = false; 257 TL_GET( preemption_state ).disable_count = 1; 261 258 262 259 // Initialize the event kernel … … 323 320 // before the kernel thread has even started running. When that happens an iterrupt 324 321 // we a null 'this_processor' will be caught, just ignore it. 325 if(! kernelTLS.this_processor) return;322 if(!TL_GET( this_processor )) return; 326 323 327 324 choose(sfp->si_value.sival_int) { 328 325 case PREEMPT_NORMAL : ;// Normal case, nothing to do here 329 case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate);326 case PREEMPT_TERMINATE: verify(TL_GET( this_processor )->do_terminate); 330 327 default: 331 328 abort( "internal error, signal value is %d", sfp->si_value.sival_int ); … … 335 332 if( !preemption_ready() ) { return; } 336 333 337 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", kernelTLS.this_processor, kernelTLS.this_thread ); 338 339 // Sync flag : prevent recursive calls to the signal handler 340 kernelTLS.preemption_state.in_progress = true; 341 342 // We are about to CtxSwitch out of the signal handler, let other handlers in 343 signal_unblock( SIGUSR1 ); 344 345 // TODO: this should go in finish action 346 // Clear the in progress flag 347 kernelTLS.preemption_state.in_progress = false; 334 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", TL_GET( this_processor ), TL_GET( this_thread ) ); 335 336 TL_GET( preemption_state ).in_progress = true; // Sync flag : prevent recursive calls to the signal handler 337 signal_unblock( SIGUSR1 ); // We are about to CtxSwitch out of the signal handler, let other handlers in 338 TL_GET( preemption_state ).in_progress = false; // Clear the in progress flag 348 339 349 340 // Preemption can occur here 350 341 351 BlockInternal( kernelTLS.this_thread); // Do the actual CtxSwitch342 BlockInternal( (thread_desc*)TL_GET( this_thread ) ); // Do the actual CtxSwitch 352 343 } 353 344 … … 418 409 419 410 void __cfaabi_check_preemption() { 420 bool ready = kernelTLS.preemption_state.enabled;411 bool ready = TL_GET( preemption_state ).enabled; 421 412 if(!ready) { abort("Preemption should be ready"); } 422 413 -
src/libcfa/concurrency/thread.c
r5fec3f6 r387c9a1 81 81 disable_interrupts(); 82 82 create_stack(&thrd_c->stack, thrd_c->stack.size); 83 kernelTLS.this_coroutine = thrd_c;83 TL_SET( this_coroutine, thrd_c ); 84 84 CtxStart(&this, CtxInvokeThread); 85 85 assert( thrd_c->last->stack.context ); … … 91 91 92 92 extern "C" { 93 // KERNEL ONLY94 93 void __finish_creation(void) { 95 coroutine_desc* thrd_c = kernelTLS.this_coroutine;94 coroutine_desc* thrd_c = TL_GET( this_coroutine ); 96 95 ThreadCtxSwitch( thrd_c, thrd_c->last ); 97 96 } … … 99 98 100 99 void yield( void ) { 101 // Safety note : This could cause some false positives due to preemption 102 verify( TL_GET( preemption_state ).enabled ); 100 verify( TL_GET( preemption_state ).enabled ); 103 101 BlockInternal( TL_GET( this_thread ) ); 104 // Safety note : This could cause some false positives due to preemption 105 verify( TL_GET( preemption_state ).enabled ); 102 verify( TL_GET( preemption_state ).enabled ); 106 103 } 107 104 … … 112 109 } 113 110 114 // KERNEL ONLY115 111 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 116 112 // set state of current coroutine to inactive … … 120 116 // set new coroutine that the processor is executing 121 117 // and context switch to it 122 kernelTLS.this_coroutine = dst;118 TL_SET( this_coroutine, dst ); 123 119 assert( src->stack.context ); 124 120 CtxSwitch( src->stack.context, dst->stack.context ); 125 kernelTLS.this_coroutine = src;121 TL_SET( this_coroutine, src ); 126 122 127 123 // set state of new coroutine to active
Note:
See TracChangeset
for help on using the changeset viewer.