Changeset ead174a
- Timestamp:
- Nov 11, 2020, 5:43:27 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- ad4832f1
- Parents:
- b0b1e15
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/preemption.cfa
rb0b1e15 read174a 215 215 // available. 216 216 217 //----------------------------------------------------------------------------- 218 // Some assembly required 219 #define __cfaasm_label(label, when) when: asm volatile goto(".global __cfaasm_" #label "_" #when "\n" "__cfaasm_" #label "_" #when ":":::"memory":when) 220 217 221 //---------- 218 222 // special case for preemption since used often … … 220 224 // create a assembler label before 221 225 // marked as clobber all to avoid movement 222 asm volatile("__cfaasm_check_before:":::"memory");226 __cfaasm_label(check, before); 223 227 224 228 // access tls as normal … … 227 231 // create a assembler label after 228 232 // marked as clobber all to avoid movement 229 asm volatile("__cfaasm_check_after:":::"memory");233 __cfaasm_label(check, after); 230 234 return enabled; 231 235 } … … 246 250 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems 247 251 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; });250 252 // create a assembler label before 251 253 // marked as clobber all to avoid movement 252 asm volatile("__cfaasm_get_before:":::"memory");254 __cfaasm_label(get, before); 253 255 254 256 // access tls as normal (except for pointer arithmetic) … … 257 259 // create a assembler label after 258 260 // marked as clobber all to avoid movement 259 asm volatile("__cfaasm_get_after:":::"memory");261 __cfaasm_label(get, after); 260 262 return val; 261 263 } … … 266 268 // create a assembler label before 267 269 // marked as clobber all to avoid movement 268 asm volatile("__cfaasm_dsable_before:":::"memory");270 __cfaasm_label(dsable, before); 269 271 270 272 with( __cfaabi_tls.preemption_state ) { … … 288 290 // create a assembler label after 289 291 // marked as clobber all to avoid movement 290 asm volatile("__cfaasm_dsable_after:":::"memory"); 292 __cfaasm_label(dsable, after); 293 291 294 } 292 295 … … 294 297 // If counter reaches 0, execute any pending __cfactx_switch 295 298 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 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 299 // Cache the processor now since interrupts can start happening after the atomic store 300 processor * proc = __cfaabi_tls.this_processor; 301 301 /* paranoid */ verify( proc ); 302 302 … … 304 304 unsigned short prev = disable_count; 305 305 disable_count -= 1; 306 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 306 307 // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 308 /* paranoid */ verify( prev != 0u ); 307 309 308 310 // Check if we need to prempt the thread because an interrupt was missed 309 311 if( prev == 1 ) { 310 312 #if GCC_VERSION > 50000 311 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");313 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free"); 312 314 #endif 313 315 … … 328 330 // For debugging purposes : keep track of the last person to enable the interrupts 329 331 __cfaabi_dbg_debug_do( proc->last_enable = caller; ) 330 331 // create a assembler label after332 // marked as clobber all to avoid movement333 asm volatile("__cfaasm_enble_after:":::"memory");334 332 } 335 333 … … 337 335 // Don't execute any pending __cfactx_switch even if counter reaches 0 338 336 void enable_interrupts_noPoll() { 339 // create a assembler label before340 // marked as clobber all to avoid movement341 asm volatile("__cfaasm_nopoll_before:":::"memory");342 343 337 unsigned short prev = __cfaabi_tls.preemption_state.disable_count; 344 338 __cfaabi_tls.preemption_state.disable_count -= 1; 345 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 339 // If this triggers someone is enabled already enabled interrupts 340 /* paranoid */ verifyf( prev != 0u, "Incremented from %u\n", prev ); 346 341 if( prev == 1 ) { 347 342 #if GCC_VERSION > 50000 348 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");343 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free"); 349 344 #endif 350 345 // Set enabled flag to true … … 356 351 __atomic_signal_fence(__ATOMIC_RELEASE); 357 352 } 358 359 // create a assembler label after 360 // marked as clobber all to avoid movement 361 asm volatile("__cfaasm_nopoll_after:":::"memory"); 362 } 363 } 353 } 354 } 355 356 #undef __cfaasm_label 364 357 365 358 // sigprocmask wrapper : unblock a single signal … … 446 439 #elif defined( __aarch64__ ) 447 440 #ifdef __PIC__ 448 #define RELOC_TAG "@PLT" 449 #else 450 #define RELOC_TAG "" 451 #endif 452 #define __cfaasm_label( label ) \ 441 // Note that this works only for gcc 442 #define __cfaasm_label( label ) static struct asm_region label = \ 453 443 ({ \ 454 444 struct asm_region region; \ 455 445 asm( \ 456 "mov %[vb], __cfaasm_" #label "_before@GOTPCREL(%%rip)" "\n\t" \ 457 "mov %[va], __cfaasm_" #label "_after@GOTPCREL(%%rip)" "\n\t" \ 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" \ 458 450 : [vb]"=r"(region.before), [va]"=r"(region.after) \ 459 451 ); \ 460 452 region; \ 461 453 }); 454 #else 455 #error this is not the right thing to do 456 // #define __cfaasm_label( label ) static struct asm_region label = \ 457 // ({ \ 458 // struct asm_region region; \ 459 // asm( \ 460 // "adrp %[vb], __cfaasm_" #label "_before" "\n\t" \ 461 // "add %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \ 462 // "adrp %[va], :got:__cfaasm_" #label "_after" "\n\t" \ 463 // "add %[va], %[va], :lo12:__cfaasm_" #label "_after" "\n\t" \ 464 // : [vb]"=r"(region.before), [va]"=r"(region.after) \ 465 // ); \ 466 // region; \ 467 // }); 468 #endif 462 469 #else 463 470 #error unknown hardware architecture … … 473 480 __cfaasm_label( check ); 474 481 __cfaasm_label( dsable ); 475 __cfaasm_label( enble );476 __cfaasm_label( nopoll );477 482 478 483 // Check if preemption is safe … … 481 486 if( __cfaasm_in( ip, check ) ) { ready = false; goto EXIT; }; 482 487 if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; }; 483 if( __cfaasm_in( ip, enble ) ) { ready = false; goto EXIT; };484 if( __cfaasm_in( ip, nopoll ) ) { ready = false; goto EXIT; };485 488 if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; }; 486 489 if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
Note: See TracChangeset
for help on using the changeset viewer.