- File:
-
- 1 edited
-
libcfa/src/concurrency/preemption.cfa (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/preemption.cfa
rb5344a3 r1b033b8 215 215 // available. 216 216 217 //-----------------------------------------------------------------------------218 // Some assembly required219 #define __cfaasm_label(label, when) when: asm volatile goto(".global __cfaasm_" #label "_" #when "\n" "__cfaasm_" #label "_" #when ":":::"memory":when)220 221 217 //---------- 222 218 // special case for preemption since used often … … 224 220 // create a assembler label before 225 221 // marked as clobber all to avoid movement 226 __cfaasm_label(check, before);222 asm volatile("__cfaasm_check_before:":::"memory"); 227 223 228 224 // access tls as normal … … 231 227 // create a assembler label after 232 228 // marked as clobber all to avoid movement 233 __cfaasm_label(check, after);229 asm volatile("__cfaasm_check_after:":::"memory"); 234 230 return enabled; 235 231 } … … 250 246 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems 251 247 uintptr_t __cfatls_get( unsigned long int offset ) { 248 // __cfaasm_get.before = ({ void * value; asm("movq $__cfaasm_get_before, %[v]\n\t" : [v]"=r"(value) ); value; }); 249 // __cfaasm_get.after = ({ void * value; asm("movq $__cfaasm_get_after , %[v]\n\t" : [v]"=r"(value) ); value; }); 252 250 // create a assembler label before 253 251 // marked as clobber all to avoid movement 254 __cfaasm_label(get, before);252 asm volatile("__cfaasm_get_before:":::"memory"); 255 253 256 254 // access tls as normal (except for pointer arithmetic) … … 259 257 // create a assembler label after 260 258 // marked as clobber all to avoid movement 261 __cfaasm_label(get, after);259 asm volatile("__cfaasm_get_after:":::"memory"); 262 260 return val; 263 261 } … … 268 266 // create a assembler label before 269 267 // marked as clobber all to avoid movement 270 __cfaasm_label(dsable, before);268 asm volatile("__cfaasm_dsable_before:":::"memory"); 271 269 272 270 with( __cfaabi_tls.preemption_state ) { … … 290 288 // create a assembler label after 291 289 // marked as clobber all to avoid movement 292 __cfaasm_label(dsable, after); 293 290 asm volatile("__cfaasm_dsable_after:":::"memory"); 294 291 } 295 292 … … 297 294 // If counter reaches 0, execute any pending __cfactx_switch 298 295 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 299 // Cache the processor now since interrupts can start happening after the atomic store 300 processor * proc = __cfaabi_tls.this_processor; 296 // create a assembler label before 297 // marked as clobber all to avoid movement 298 asm volatile("__cfaasm_enble_before:":::"memory"); 299 300 processor * proc = __cfaabi_tls.this_processor; // Cache the processor now since interrupts can start happening after the atomic store 301 301 /* paranoid */ verify( proc ); 302 302 … … 304 304 unsigned short prev = disable_count; 305 305 disable_count -= 1; 306 307 // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 308 /* paranoid */ verify( prev != 0u ); 306 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 309 307 310 308 // Check if we need to prempt the thread because an interrupt was missed 311 309 if( prev == 1 ) { 312 310 #if GCC_VERSION > 50000 313 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");311 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free"); 314 312 #endif 315 313 … … 330 328 // For debugging purposes : keep track of the last person to enable the interrupts 331 329 __cfaabi_dbg_debug_do( proc->last_enable = caller; ) 330 331 // create a assembler label after 332 // marked as clobber all to avoid movement 333 asm volatile("__cfaasm_enble_after:":::"memory"); 332 334 } 333 335 … … 335 337 // Don't execute any pending __cfactx_switch even if counter reaches 0 336 338 void enable_interrupts_noPoll() { 339 // create a assembler label before 340 // marked as clobber all to avoid movement 341 asm volatile("__cfaasm_nopoll_before:":::"memory"); 342 337 343 unsigned short prev = __cfaabi_tls.preemption_state.disable_count; 338 344 __cfaabi_tls.preemption_state.disable_count -= 1; 339 // If this triggers someone is enabled already enabled interrupts 340 /* paranoid */ verifyf( prev != 0u, "Incremented from %u\n", prev ); 345 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 341 346 if( prev == 1 ) { 342 347 #if GCC_VERSION > 50000 343 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");348 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free"); 344 349 #endif 345 350 // Set enabled flag to true … … 351 356 __atomic_signal_fence(__ATOMIC_RELEASE); 352 357 } 353 } 354 } 355 356 #undef __cfaasm_label 358 359 // create a assembler label after 360 // marked as clobber all to avoid movement 361 asm volatile("__cfaasm_nopoll_after:":::"memory"); 362 } 363 } 357 364 358 365 // sigprocmask wrapper : unblock a single signal … … 386 393 // reserved for future use 387 394 static void timeout( $thread * this ) { 388 #if !defined( __CFA_NO_STATISTICS__ )389 kernelTLS().this_stats = this->curr_cluster->stats;390 #endif391 395 unpark( this ); 392 396 } … … 439 443 #elif defined( __aarch64__ ) 440 444 #ifdef __PIC__ 441 // Note that this works only for gcc 442 #define __cfaasm_label( label ) static struct asm_region label = \ 445 #define RELOC_TAG "@PLT" 446 #else 447 #define RELOC_TAG "" 448 #endif 449 #define __cfaasm_label( label ) \ 443 450 ({ \ 444 451 struct asm_region region; \ 445 452 asm( \ 446 "adrp %[vb], _GLOBAL_OFFSET_TABLE_" "\n\t" \ 447 "ldr %[vb], [%[vb], #:gotpage_lo15:__cfaasm_" #label "_before]" "\n\t" \ 448 "adrp %[va], _GLOBAL_OFFSET_TABLE_" "\n\t" \ 449 "ldr %[va], [%[va], #:gotpage_lo15:__cfaasm_" #label "_after]" "\n\t" \ 453 "mov %[vb], __cfaasm_" #label "_before@GOTPCREL(%%rip)" "\n\t" \ 454 "mov %[va], __cfaasm_" #label "_after@GOTPCREL(%%rip)" "\n\t" \ 450 455 : [vb]"=r"(region.before), [va]"=r"(region.after) \ 451 456 ); \ 452 457 region; \ 453 458 }); 454 #else455 #error this is not the right thing to do456 /*457 #define __cfaasm_label( label ) static struct asm_region label = \458 ({ \459 struct asm_region region; \460 asm( \461 "adrp %[vb], __cfaasm_" #label "_before" "\n\t" \462 "add %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \463 "adrp %[va], :got:__cfaasm_" #label "_after" "\n\t" \464 "add %[va], %[va], :lo12:__cfaasm_" #label "_after" "\n\t" \465 : [vb]"=r"(region.before), [va]"=r"(region.after) \466 ); \467 region; \468 });469 */470 #endif471 459 #else 472 460 #error unknown hardware architecture … … 482 470 __cfaasm_label( check ); 483 471 __cfaasm_label( dsable ); 472 __cfaasm_label( enble ); 473 __cfaasm_label( nopoll ); 484 474 485 475 // Check if preemption is safe … … 488 478 if( __cfaasm_in( ip, check ) ) { ready = false; goto EXIT; }; 489 479 if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; }; 480 if( __cfaasm_in( ip, enble ) ) { ready = false; goto EXIT; }; 481 if( __cfaasm_in( ip, nopoll ) ) { ready = false; goto EXIT; }; 490 482 if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; }; 491 483 if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; }; … … 614 606 abort("SIGALRM should never reach the signal handler"); 615 607 } 608 609 #if !defined(__CFA_NO_STATISTICS__) 610 int __print_alarm_stats = 0; 611 #endif 616 612 617 613 // Main of the alarm thread … … 622 618 id.id = doregister(&id); 623 619 __cfaabi_tls.this_proc_id = &id; 620 621 #if !defined(__CFA_NO_STATISTICS__) 622 struct __stats_t local_stats; 623 __cfaabi_tls.this_stats = &local_stats; 624 __init_stats( &local_stats ); 625 #endif 624 626 625 627 // Block sigalrms to control when they arrive … … 681 683 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" ); 682 684 unregister(&id); 685 686 #if !defined(__CFA_NO_STATISTICS__) 687 if( 0 != __print_alarm_stats ) { 688 __print_stats( &local_stats, __print_alarm_stats, "Alarm", "Thread", 0p ); 689 } 690 #endif 683 691 return 0p; 684 692 }
Note:
See TracChangeset
for help on using the changeset viewer.