- File:
-
- 1 edited
-
src/libcfa/concurrency/preemption.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
r65deb18 rd0a045c7 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 21 22:36:05 201713 // Update Count : 212 // Last Modified On : Tue Jan 23 17:59:30 2018 13 // Update Count : 7 14 14 // 15 15 16 16 #include "preemption.h" 17 17 18 #define ftype `ftype` 18 19 extern "C" { 19 20 #include <errno.h> 20 #include <execinfo.h>21 #define __USE_GNU22 #include <signal.h>23 #undef __USE_GNU24 21 #include <stdio.h> 25 22 #include <string.h> 26 23 #include <unistd.h> 27 24 } 28 29 30 #ifdef __USE_STREAM__ 31 #include "fstream" 32 #endif 25 #undef ftype 26 27 #include "bits/signal.h" 33 28 34 29 //TODO move to defaults … … 39 34 return __CFA_DEFAULT_PREEMPTION__; 40 35 } 41 42 // Short hands for signal context information43 #define __CFA_SIGCXT__ ucontext_t *44 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt45 36 46 37 // FwdDeclarations : timeout handlers … … 53 44 void sigHandler_abort ( __CFA_SIGPARMS__ ); 54 45 55 // FwdDeclarations : sigaction wrapper56 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );57 58 46 // FwdDeclarations : alarm thread main 59 47 void * alarm_loop( __attribute__((unused)) void * args ); 60 48 61 49 // Machine specific register name 62 #ifdef __x86_64__ 63 #define CFA_REG_IP REG_RIP 64 #else 65 #define CFA_REG_IP REG_EIP 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 66 56 #endif 67 57 … … 152 142 // Disable interrupts by incrementing the counter 153 143 void disable_interrupts() { 154 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 144 preemption_enabled = false; 145 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1; 146 disable_preempt_count = new_val; 155 147 verify( new_val < 65_000u ); // If this triggers someone is disabling interrupts without enabling them 156 148 } … … 162 154 thread_desc * thrd = this_thread; // Cache the thread now since interrupts can start happening after the atomic add 163 155 164 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 156 unsigned short prev = disable_preempt_count; 157 disable_preempt_count -= 1; 165 158 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 166 159 167 160 // Check if we need to prempt the thread because an interrupt was missed 168 if( prev == 1 && proc->pending_preemption ) { 169 proc->pending_preemption = false; 170 BlockInternal( thrd ); 161 if( prev == 1 ) { 162 preemption_enabled = true; 163 if( proc->pending_preemption ) { 164 proc->pending_preemption = false; 165 BlockInternal( thrd ); 166 } 171 167 } 172 168 … … 178 174 // Don't execute any pending CtxSwitch even if counter reaches 0 179 175 void enable_interrupts_noPoll() { 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 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 } 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 = disable_preempt_count == 0&& !preemption_in_progress; // Check if preemption is safe222 bool ready = preemption_enabled && !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; 237 238 disable_preempt_count = 1; 238 239 … … 243 244 // Setup proper signal handlers 244 245 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART ); // CtxSwitch handler 245 // __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); // Failure handler246 // __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); // Failure handler247 246 248 247 signal_block( SIGALRM ); … … 296 295 // Receives SIGUSR1 signal and causes the current thread to yield 297 296 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 298 __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext. gregs[CFA_REG_IP]); )297 __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); ) 299 298 300 299 // Check if it is safe to preempt here 301 300 if( !preemption_ready() ) { return; } 301 302 __cfaabi_dbg_print_buffer_decl(" KERNEL: preempting core %p (%p).\n", this_processor, this_thread); 302 303 303 304 preemption_in_progress = true; // Sync flag : prevent recursive calls to the signal handler … … 371 372 } 372 373 373 // Sigaction wrapper : register an signal handler374 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 handler390 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 logic408 //=============================================================================================409 410 __cfaabi_dbg_debug_do(411 static void __kernel_backtrace( int start ) {412 // skip first N stack frames413 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 name420 *index( messages[0], '(' ) = '\0';421 #ifdef __USE_STREAM__422 serr | "Stack back trace for:" | messages[0] | endl;423 #else424 fprintf( stderr, "Stack back trace for: %s\n", messages[0]);425 #endif426 427 // skip last 2 stack frames after main428 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 +offset435 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 it448 int frameNo = i - start;449 if ( name && offset_begin && offset_end && name < offset_begin ) {450 // delimit strings451 *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 #else459 fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);460 #endif461 }462 // otherwise, print the whole line463 else {464 #ifdef __USE_STREAM__465 serr | "(" | frameNo | ")" | messages[i] | endl;466 #else467 fprintf( stderr, "(%i) %s\n", frameNo, messages[i] );468 #endif469 }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 // #else483 // fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." );484 // #endif485 486 // // skip first 2 stack frames487 // __kernel_backtrace( 1 );488 // )489 // exit( EXIT_FAILURE );490 // }491 492 // void sigHandler_abort( __CFA_SIGPARMS__ ) {493 // // skip first 6 stack frames494 // __cfaabi_dbg_debug_do( __kernel_backtrace( 6 ); )495 496 // // reset default signal handler497 // __kernel_sigdefault( SIGABRT );498 499 // raise( SIGABRT );500 // }501 502 374 // Local Variables: // 503 375 // mode: c //
Note:
See TracChangeset
for help on using the changeset viewer.