- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/preemption.cfa
r428adbc rb443db0 238 238 //---------- 239 239 // special case for preemption since used often 240 __attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_ public {240 __attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_nopreempt libcfa_public { 241 241 // create a assembler label before 242 242 // marked as clobber all to avoid movement … … 272 272 } 273 273 274 extern "C" { 275 __attribute__((visibility("hidden"))) extern void * const __start_cfatext_nopreempt; 276 __attribute__((visibility("hidden"))) extern void * const __stop_cfatext_nopreempt; 277 278 extern const __cfa_nopreempt_region __libcfa_nopreempt; 279 __attribute__((visibility("protected"))) const __cfa_nopreempt_region __libcfathrd_nopreempt @= { 280 (void * const)&__start_cfatext_nopreempt, 281 (void * const)&__stop_cfatext_nopreempt 282 }; 283 } 284 285 static inline bool __cfaabi_in( void * const ip, const struct __cfa_nopreempt_region & const region ) { 286 return ip >= region.start && ip <= region.stop; 287 } 288 274 289 275 290 //---------- 276 291 // Get data from the TLS block 277 292 // struct asm_region __cfaasm_get; 278 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__, visibility("default"))); //no inline to avoid problems293 uintptr_t __cfatls_get( unsigned long int offset ) libcfa_nopreempt libcfa_public; //no inline to avoid problems 279 294 uintptr_t __cfatls_get( unsigned long int offset ) { 280 295 // create a assembler label before … … 295 310 extern "C" { 296 311 // Disable interrupts by incrementing the counter 297 __attribute__((__noinline__, visibility("default"))) void disable_interrupts()libcfa_public {312 void disable_interrupts() libcfa_nopreempt libcfa_public { 298 313 // create a assembler label before 299 314 // marked as clobber all to avoid movement … … 326 341 // Enable interrupts by decrementing the counter 327 342 // If counter reaches 0, execute any pending __cfactx_switch 328 void enable_interrupts( bool poll ) libcfa_ public {343 void enable_interrupts( bool poll ) libcfa_nopreempt libcfa_public { 329 344 // Cache the processor now since interrupts can start happening after the atomic store 330 345 processor * proc = __cfaabi_tls.this_processor; … … 358 373 } 359 374 } 375 376 // Check whether or not there is pending preemption 377 // force_yield( __POLL_PREEMPTION ) if appropriate 378 // return true if the thread was in an interruptable state 379 // i.e. on a real processor and not in the kernel 380 // (can return true even if no preemption was pending) 381 bool poll_interrupts() libcfa_public { 382 // Cache the processor now since interrupts can start happening after the atomic store 383 processor * proc = publicTLS_get( this_processor ); 384 if ( ! proc ) return false; 385 if ( ! __preemption_enabled() ) return false; 386 387 with( __cfaabi_tls.preemption_state ){ 388 // Signal the compiler that a fence is needed but only for signal handlers 389 __atomic_signal_fence(__ATOMIC_RELEASE); 390 if( proc->pending_preemption ) { 391 proc->pending_preemption = false; 392 force_yield( __POLL_PREEMPTION ); 393 } 394 } 395 396 return true; 397 } 360 398 } 361 399 … … 368 406 sigset_t oldset; 369 407 int ret; 370 ret = real_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary408 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 371 409 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 372 410 … … 401 439 sigaddset( &mask, sig ); 402 440 403 if ( real_pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {441 if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) { 404 442 abort( "internal error, pthread_sigmask" ); 405 443 } … … 412 450 sigaddset( &mask, sig ); 413 451 414 if ( real_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {452 if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) { 415 453 abort( "internal error, pthread_sigmask" ); 416 454 } … … 420 458 static void preempt( processor * this ) { 421 459 sigval_t value = { PREEMPT_NORMAL }; 422 real_pthread_sigqueue( this->kernel_thread, SIGUSR1, value );460 pthread_sigqueue( this->kernel_thread, SIGUSR1, value ); 423 461 } 424 462 … … 431 469 sigset_t oldset; 432 470 int ret; 433 ret = real_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary471 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 434 472 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 435 473 … … 450 488 sigset_t oldset; 451 489 int ret; 452 ret = real_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary490 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 453 491 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 454 492 … … 463 501 464 502 //----------------------------------------------------------------------------- 465 // Some assembly required466 #if defined( __i386 )467 #ifdef __PIC__468 #define RELOC_PRELUDE( label ) \469 "calll .Lcfaasm_prelude_" #label "$pb\n\t" \470 ".Lcfaasm_prelude_" #label "$pb:\n\t" \471 "popl %%eax\n\t" \472 ".Lcfaasm_prelude_" #label "_end:\n\t" \473 "addl $_GLOBAL_OFFSET_TABLE_+(.Lcfaasm_prelude_" #label "_end-.Lcfaasm_prelude_" #label "$pb), %%eax\n\t"474 #define RELOC_PREFIX ""475 #define RELOC_SUFFIX "@GOT(%%eax)"476 #else477 #define RELOC_PREFIX "$"478 #define RELOC_SUFFIX ""479 #endif480 #define __cfaasm_label( label ) struct asm_region label = \481 ({ \482 struct asm_region region; \483 asm( \484 RELOC_PRELUDE( label ) \485 "movl " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \486 "movl " RELOC_PREFIX "__cfaasm_" #label "_after" RELOC_SUFFIX ", %[va]\n\t" \487 : [vb]"=r"(region.before), [va]"=r"(region.after) \488 ); \489 region; \490 });491 #elif defined( __x86_64 )492 #ifdef __PIC__493 #define RELOC_PREFIX ""494 #define RELOC_SUFFIX "@GOTPCREL(%%rip)"495 #else496 #define RELOC_PREFIX "$"497 #define RELOC_SUFFIX ""498 #endif499 #define __cfaasm_label( label ) struct asm_region label = \500 ({ \501 struct asm_region region; \502 asm( \503 "movq " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \504 "movq " RELOC_PREFIX "__cfaasm_" #label "_after" RELOC_SUFFIX ", %[va]\n\t" \505 : [vb]"=r"(region.before), [va]"=r"(region.after) \506 ); \507 region; \508 });509 #elif defined( __aarch64__ )510 #ifdef __PIC__511 // Note that this works only for gcc512 #define __cfaasm_label( label ) struct asm_region label = \513 ({ \514 struct asm_region region; \515 asm( \516 "adrp %[vb], _GLOBAL_OFFSET_TABLE_" "\n\t" \517 "ldr %[vb], [%[vb], #:gotpage_lo15:__cfaasm_" #label "_before]" "\n\t" \518 "adrp %[va], _GLOBAL_OFFSET_TABLE_" "\n\t" \519 "ldr %[va], [%[va], #:gotpage_lo15:__cfaasm_" #label "_after]" "\n\t" \520 : [vb]"=r"(region.before), [va]"=r"(region.after) \521 ); \522 region; \523 });524 #else525 #error this is not the right thing to do526 /*527 #define __cfaasm_label( label ) struct asm_region label = \528 ({ \529 struct asm_region region; \530 asm( \531 "adrp %[vb], __cfaasm_" #label "_before" "\n\t" \532 "add %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \533 "adrp %[va], :got:__cfaasm_" #label "_after" "\n\t" \534 "add %[va], %[va], :lo12:__cfaasm_" #label "_after" "\n\t" \535 : [vb]"=r"(region.before), [va]"=r"(region.after) \536 ); \537 region; \538 });539 */540 #endif541 #else542 #error unknown hardware architecture543 #endif544 545 503 // KERNEL ONLY 546 504 // Check if a __cfactx_switch signal handler shoud defer … … 548 506 // If false : preemption is unsafe and marked as pending 549 507 static inline bool preemption_ready( void * ip ) { 550 // Get all the region for which it is not safe to preempt551 __cfaasm_label( get );552 __cfaasm_label( check );553 __cfaasm_label( dsable );554 // __cfaasm_label( debug );555 556 508 // Check if preemption is safe 557 509 bool ready = true; 558 if( __cfaasm_in( ip, get ) ) { ready = false; goto EXIT; }; 559 if( __cfaasm_in( ip, check ) ) { ready = false; goto EXIT; }; 560 if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; }; 561 // if( __cfaasm_in( ip, debug ) ) { ready = false; goto EXIT; }; 510 if( __cfaabi_in( ip, __libcfa_nopreempt ) ) { ready = false; goto EXIT; }; 511 if( __cfaabi_in( ip, __libcfathrd_nopreempt ) ) { ready = false; goto EXIT; }; 512 562 513 if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; }; 563 514 if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; }; … … 608 559 sigval val; 609 560 val.sival_int = 0; 610 real_pthread_sigqueue( alarm_thread, SIGALRM, val );561 pthread_sigqueue( alarm_thread, SIGALRM, val ); 611 562 612 563 // Wait for the preemption thread to finish … … 643 594 // Kernel Signal Handlers 644 595 //============================================================================================= 645 __cfaabi_dbg_debug_do( static thread_localvoid * last_interrupt = 0; )596 __cfaabi_dbg_debug_do( static __thread void * last_interrupt = 0; ) 646 597 647 598 // Context switch signal handler … … 682 633 static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" ); 683 634 #endif 684 if ( real_pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {635 if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) { 685 636 abort( "internal error, sigprocmask" ); 686 637 } … … 710 661 sigset_t mask; 711 662 sigfillset(&mask); 712 if ( real_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {663 if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) { 713 664 abort( "internal error, pthread_sigmask" ); 714 665 }
Note:
See TracChangeset
for help on using the changeset viewer.