- File:
-
- 1 edited
-
src/libcfa/concurrency/preemption.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
rd0a045c7 r65deb18 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jan 23 17:59:30 201813 // Update Count : 712 // Last Modified On : Fri Jul 21 22:36:05 2017 13 // Update Count : 2 14 14 // 15 15 16 16 #include "preemption.h" 17 17 18 #define ftype `ftype`19 18 extern "C" { 20 19 #include <errno.h> 20 #include <execinfo.h> 21 #define __USE_GNU 22 #include <signal.h> 23 #undef __USE_GNU 21 24 #include <stdio.h> 22 25 #include <string.h> 23 26 #include <unistd.h> 24 27 } 25 #undef ftype 26 27 #include "bits/signal.h" 28 29 30 #ifdef __USE_STREAM__ 31 #include "fstream" 32 #endif 28 33 29 34 //TODO move to defaults … … 34 39 return __CFA_DEFAULT_PREEMPTION__; 35 40 } 41 42 // Short hands for signal context information 43 #define __CFA_SIGCXT__ ucontext_t * 44 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt 36 45 37 46 // FwdDeclarations : timeout handlers … … 44 53 void sigHandler_abort ( __CFA_SIGPARMS__ ); 45 54 55 // FwdDeclarations : sigaction wrapper 56 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); 57 46 58 // FwdDeclarations : alarm thread main 47 59 void * alarm_loop( __attribute__((unused)) void * args ); 48 60 49 61 // Machine specific register name 50 #if defined(__x86_64__) 51 #define CFA_REG_IP gregs[REG_RIP] 52 #elif defined(__i386__) 53 #define CFA_REG_IP gregs[REG_EIP] 54 #elif defined(__ARM_ARCH__) 55 #define CFA_REG_IP arm_pc 62 #ifdef __x86_64__ 63 #define CFA_REG_IP REG_RIP 64 #else 65 #define CFA_REG_IP REG_EIP 56 66 #endif 57 67 … … 142 152 // Disable interrupts by incrementing the counter 143 153 void disable_interrupts() { 144 preemption_enabled = false; 145 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1; 146 disable_preempt_count = new_val; 154 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 147 155 verify( new_val < 65_000u ); // If this triggers someone is disabling interrupts without enabling them 148 156 } … … 154 162 thread_desc * thrd = this_thread; // Cache the thread now since interrupts can start happening after the atomic add 155 163 156 unsigned short prev = disable_preempt_count; 157 disable_preempt_count -= 1; 164 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 158 165 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 159 166 160 167 // Check if we need to prempt the thread because an interrupt was missed 161 if( prev == 1 ) { 162 preemption_enabled = true; 163 if( proc->pending_preemption ) { 164 proc->pending_preemption = false; 165 BlockInternal( thrd ); 166 } 168 if( prev == 1 && proc->pending_preemption ) { 169 proc->pending_preemption = false; 170 BlockInternal( thrd ); 167 171 } 168 172 … … 174 178 // Don't execute any pending CtxSwitch even if counter reaches 0 175 179 void enable_interrupts_noPoll() { 176 unsigned short prev = disable_preempt_count; 177 disable_preempt_count -= 1; 178 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 179 if( prev == 1 ) { 180 preemption_enabled = true; 181 } 180 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 181 verify( prev != 0u ); // If this triggers someone is enabled already enabled interrupts 182 182 } 183 183 } … … 220 220 // If false : preemption is unsafe and marked as pending 221 221 static inline bool preemption_ready() { 222 bool ready = preemption_enabled&& !preemption_in_progress; // Check if preemption is safe222 bool ready = disable_preempt_count == 0 && !preemption_in_progress; // Check if preemption is safe 223 223 this_processor->pending_preemption = !ready; // Adjust the pending flag accordingly 224 224 return ready; … … 235 235 236 236 // Start with preemption disabled until ready 237 preemption_enabled = false;238 237 disable_preempt_count = 1; 239 238 … … 244 243 // Setup proper signal handlers 245 244 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART ); // CtxSwitch handler 245 // __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); // Failure handler 246 // __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); // Failure handler 246 247 247 248 signal_block( SIGALRM ); … … 295 296 // Receives SIGUSR1 signal and causes the current thread to yield 296 297 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 297 __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext. CFA_REG_IP); )298 __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); ) 298 299 299 300 // Check if it is safe to preempt here 300 301 if( !preemption_ready() ) { return; } 301 302 __cfaabi_dbg_print_buffer_decl(" KERNEL: preempting core %p (%p).\n", this_processor, this_thread);303 302 304 303 preemption_in_progress = true; // Sync flag : prevent recursive calls to the signal handler … … 372 371 } 373 372 373 // Sigaction wrapper : register an signal handler 374 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) { 375 struct sigaction act; 376 377 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 378 act.sa_flags = flags; 379 380 if ( sigaction( sig, &act, NULL ) == -1 ) { 381 __cfaabi_dbg_print_buffer_decl( 382 " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 383 sig, handler, flags, errno, strerror( errno ) 384 ); 385 _exit( EXIT_FAILURE ); 386 } 387 } 388 389 // Sigaction wrapper : restore default handler 390 static void __kernel_sigdefault( int sig ) { 391 struct sigaction act; 392 393 act.sa_handler = SIG_DFL; 394 act.sa_flags = 0; 395 sigemptyset( &act.sa_mask ); 396 397 if ( sigaction( sig, &act, NULL ) == -1 ) { 398 __cfaabi_dbg_print_buffer_decl( 399 " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n", 400 sig, errno, strerror( errno ) 401 ); 402 _exit( EXIT_FAILURE ); 403 } 404 } 405 406 //============================================================================================= 407 // Terminating Signals logic 408 //============================================================================================= 409 410 __cfaabi_dbg_debug_do( 411 static void __kernel_backtrace( int start ) { 412 // skip first N stack frames 413 414 enum { Frames = 50 }; 415 void * array[Frames]; 416 int size = backtrace( array, Frames ); 417 char ** messages = backtrace_symbols( array, size ); 418 419 // find executable name 420 *index( messages[0], '(' ) = '\0'; 421 #ifdef __USE_STREAM__ 422 serr | "Stack back trace for:" | messages[0] | endl; 423 #else 424 fprintf( stderr, "Stack back trace for: %s\n", messages[0]); 425 #endif 426 427 // skip last 2 stack frames after main 428 for ( int i = start; i < size && messages != NULL; i += 1 ) { 429 char * name = NULL; 430 char * offset_begin = NULL; 431 char * offset_end = NULL; 432 433 for ( char *p = messages[i]; *p; ++p ) { 434 // find parantheses and +offset 435 if ( *p == '(' ) { 436 name = p; 437 } 438 else if ( *p == '+' ) { 439 offset_begin = p; 440 } 441 else if ( *p == ')' ) { 442 offset_end = p; 443 break; 444 } 445 } 446 447 // if line contains symbol print it 448 int frameNo = i - start; 449 if ( name && offset_begin && offset_end && name < offset_begin ) { 450 // delimit strings 451 *name++ = '\0'; 452 *offset_begin++ = '\0'; 453 *offset_end++ = '\0'; 454 455 #ifdef __USE_STREAM__ 456 serr | "(" | frameNo | ")" | messages[i] | ":" 457 | name | "+" | offset_begin | offset_end | endl; 458 #else 459 fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end); 460 #endif 461 } 462 // otherwise, print the whole line 463 else { 464 #ifdef __USE_STREAM__ 465 serr | "(" | frameNo | ")" | messages[i] | endl; 466 #else 467 fprintf( stderr, "(%i) %s\n", frameNo, messages[i] ); 468 #endif 469 } 470 } 471 472 free( messages ); 473 } 474 ) 475 476 // void sigHandler_segv( __CFA_SIGPARMS__ ) { 477 // __cfaabi_dbg_debug_do( 478 // #ifdef __USE_STREAM__ 479 // serr | "*CFA runtime error* program cfa-cpp terminated with" 480 // | (sig == SIGSEGV ? "segment fault." : "bus error.") 481 // | endl; 482 // #else 483 // fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." ); 484 // #endif 485 486 // // skip first 2 stack frames 487 // __kernel_backtrace( 1 ); 488 // ) 489 // exit( EXIT_FAILURE ); 490 // } 491 492 // void sigHandler_abort( __CFA_SIGPARMS__ ) { 493 // // skip first 6 stack frames 494 // __cfaabi_dbg_debug_do( __kernel_backtrace( 6 ); ) 495 496 // // reset default signal handler 497 // __kernel_sigdefault( SIGABRT ); 498 499 // raise( SIGABRT ); 500 // } 501 374 502 // Local Variables: // 375 503 // mode: c //
Note:
See TracChangeset
for help on using the changeset viewer.