Changeset 1c273d0 for src/libcfa/concurrency/preemption.c
- Timestamp:
- Jun 23, 2017, 10:12:04 AM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- d43cd01
- Parents:
- aa3d77b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
raa3d77b r1c273d0 20 20 extern "C" { 21 21 #include <errno.h> 22 #include <execinfo.h> 22 23 #define __USE_GNU 23 24 #include <signal.h> … … 28 29 } 29 30 31 32 #ifdef __USE_STREAM__ 33 #include "fstream" 34 #endif 30 35 #include "libhdr.h" 31 36 … … 44 49 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ); 45 50 void sigHandler_alarm ( __CFA_SIGPARMS__ ); 51 void sigHandler_segv ( __CFA_SIGPARMS__ ); 52 void sigHandler_abort ( __CFA_SIGPARMS__ ); 46 53 47 54 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); … … 55 62 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); 56 63 __kernel_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); 64 __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); 65 __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); 66 // __kernel_sigaction( SIGABRT, sigHandler_abort , SA_SIGINFO ); 57 67 } 58 68 … … 64 74 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n"); 65 75 66 assert( !systemProcessor->alarms.head );67 assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );76 // assert( !systemProcessor->alarms.head ); 77 // assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head ); 68 78 } 69 79 … … 71 81 72 82 void tick_preemption() { 73 LIB_DEBUG_DO( 74 char text[256]; 75 __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" ); 76 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 77 ); 83 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" ); 78 84 79 85 alarm_list_t * alarms = &systemProcessor->alarms; … … 81 87 while( alarms->head && alarms->head->alarm < currtime ) { 82 88 alarm_node_t * node = pop(alarms); 83 LIB_DEBUG_DO( 84 len = snprintf( text, 256, "Ticking %p\n", node ); 85 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 86 ); 89 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node ); 90 87 91 if( node->kernel_alarm ) { 88 92 preempt( node->proc ); … … 92 96 } 93 97 94 LIB_DEBUG_DO( assert( validate( alarms )) );98 verify( validate( alarms ) ); 95 99 96 100 if( node->period > 0 ) { … … 108 112 109 113 verify( validate( alarms ) ); 110 LIB_DEBUG_DO( 111 len = snprintf( text, 256, "Ticking preemption done\n" ); 112 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 113 ); 114 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" ); 114 115 } 115 116 116 117 void update_preemption( processor * this, __cfa_time_t duration ) { 117 LIB_DEBUG_DO( 118 char text[256]; 119 __attribute__((unused)) int len = snprintf( text, 256, "Processor : %p updating preemption to %lu\n", this, duration ); 120 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 121 ); 118 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration ); 122 119 123 120 alarm_node_t * alarm = this->preemption_alarm; … … 175 172 176 173 void enable_interrupts( const char * func ) { 174 processor * proc = this_processor; 175 thread_desc * thrd = this_thread; 177 176 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 178 177 verify( prev != (unsigned short) 0 ); 179 if( prev == 1 && this_processor->pending_preemption ) { 180 this_processor->pending_preemption = false; 181 LIB_DEBUG_DO( 182 char text[256]; 183 __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch on %p\n", this_processor ); 184 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 185 ); 186 BlockInternal( this_processor->current_thread ); 187 } 188 189 this_processor->last_enable = func; 190 } 191 } 192 193 static inline void signal_unblock( bool alarm ) { 178 if( prev == 1 && proc->pending_preemption ) { 179 proc->pending_preemption = false; 180 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Executing deferred CtxSwitch on %p\n", this_processor ); 181 BlockInternal( thrd ); 182 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Executing deferred back\n" ); 183 } 184 185 proc->last_enable = func; 186 } 187 } 188 189 static inline void signal_unblock( int sig ) { 190 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p unblocking sig %i\n", this_processor, sig ); 191 194 192 sigset_t mask; 195 193 sigemptyset( &mask ); 196 sigaddset( &mask, SIGUSR1 ); 197 198 if( alarm ) sigaddset( &mask, SIGALRM ); 194 sigaddset( &mask, sig ); 199 195 200 196 if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { … … 215 211 } 216 212 213 extern "C" { 214 __attribute__((noinline)) void __debug_break() { 215 pthread_kill( pthread_self(), SIGTRAP ); 216 } 217 } 218 217 219 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 218 219 LIB_DEBUG_DO( 220 char text[256]; 221 __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP])); 222 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 223 ); 224 225 signal_unblock( false ); 220 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ctx Switch IRH %p running %p @ %p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 221 226 222 if( preemption_ready() ) { 227 LIB_DEBUG_DO( 228 len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread %p on %p\n", this_processor->current_thread, this_processor ); 229 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 230 ); 231 BlockInternal( this_processor->current_thread ); 223 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 224 signal_unblock( SIGUSR1 ); 225 BlockInternal( (thread_desc*)this_thread ); 226 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Back\n\n"); 232 227 } 233 228 else { 234 LIB_DEBUG_DO( 235 len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" ); 236 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 237 ); 229 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Defering\n" ); 238 230 defer_ctxSwitch(); 231 signal_unblock( SIGUSR1 ); 239 232 } 240 233 } 241 234 242 235 void sigHandler_alarm( __CFA_SIGPARMS__ ) { 243 244 LIB_DEBUG_DO( 245 char text[256]; 246 __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 247 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 248 ); 249 250 signal_unblock( true ); 251 if( try_lock( &systemProcessor->alarm_lock ) ) { 236 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "\nAlarm IRH %p running %p @ %p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 237 238 // if( ((intptr_t)cxt->uc_mcontext.gregs[REG_RIP]) > 0xFFFFFF ) __debug_break(); 239 240 if( try_lock( &systemProcessor->alarm_lock, __PRETTY_FUNCTION__ ) ) { 252 241 tick_preemption(); 253 242 unlock( &systemProcessor->alarm_lock ); … … 257 246 } 258 247 248 signal_unblock( SIGALRM ); 249 259 250 if( preemption_ready() && this_processor->pending_preemption ) { 260 LIB_DEBUG_DO( 261 len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" ); 262 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 263 ); 251 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 264 252 this_processor->pending_preemption = false; 265 BlockInternal( this_processor->current_thread ); 253 BlockInternal( (thread_desc*)this_thread ); 254 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm Switch IRH : Back\n\n"); 266 255 } 267 256 } 268 257 269 258 static void preempt( processor * this ) { 270 LIB_DEBUG_DO( 271 char text[256]; 272 __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this ); 273 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 274 ); 259 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : signalling %p\n", this ); 275 260 276 261 if( this != systemProcessor ) { … … 290 275 291 276 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 277 act.sa_flags = flags; 278 279 // disabled during signal handler 292 280 sigemptyset( &act.sa_mask ); 293 sigaddset( &act.sa_mask, SIGALRM ); // disabled during signal handler 294 sigaddset( &act.sa_mask, SIGUSR1 ); 295 296 act.sa_flags = flags; 281 sigaddset( &act.sa_mask, sig ); 297 282 298 283 if ( sigaction( sig, &act, NULL ) == -1 ) { 299 // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES! 300 char helpText[256]; 301 __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 302 sig, handler, flags, errno, strerror( errno ) ); 303 LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len ); 284 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 285 " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 286 sig, handler, flags, errno, strerror( errno ) 287 ); 304 288 _exit( EXIT_FAILURE ); 305 } // if 306 } 289 } 290 } 291 292 typedef void (*sa_handler_t)(int); 293 294 static void __kernel_sigdefault( int sig ) { 295 struct sigaction act; 296 297 // act.sa_handler = SIG_DFL; 298 act.sa_flags = 0; 299 sigemptyset( &act.sa_mask ); 300 301 if ( sigaction( sig, &act, NULL ) == -1 ) { 302 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 303 " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n", 304 sig, errno, strerror( errno ) 305 ); 306 _exit( EXIT_FAILURE ); 307 } 308 } 309 310 //============================================================================================= 311 // Terminating Signals logic 312 //============================================================================================= 313 314 LIB_DEBUG_DO( 315 static void __kernel_backtrace( int start ) { 316 // skip first N stack frames 317 318 enum { Frames = 50 }; 319 void * array[Frames]; 320 int size = backtrace( array, Frames ); 321 char ** messages = backtrace_symbols( array, size ); 322 323 // find executable name 324 *index( messages[0], '(' ) = '\0'; 325 #ifdef __USE_STREAM__ 326 serr | "Stack back trace for:" | messages[0] | endl; 327 #else 328 fprintf( stderr, "Stack back trace for: %s\n", messages[0]); 329 #endif 330 331 // skip last 2 stack frames after main 332 for ( int i = start; i < size && messages != NULL; i += 1 ) { 333 char * name = NULL; 334 char * offset_begin = NULL; 335 char * offset_end = NULL; 336 337 for ( char *p = messages[i]; *p; ++p ) { 338 // find parantheses and +offset 339 if ( *p == '(' ) { 340 name = p; 341 } 342 else if ( *p == '+' ) { 343 offset_begin = p; 344 } 345 else if ( *p == ')' ) { 346 offset_end = p; 347 break; 348 } 349 } 350 351 // if line contains symbol print it 352 int frameNo = i - start; 353 if ( name && offset_begin && offset_end && name < offset_begin ) { 354 // delimit strings 355 *name++ = '\0'; 356 *offset_begin++ = '\0'; 357 *offset_end++ = '\0'; 358 359 #ifdef __USE_STREAM__ 360 serr | "(" | frameNo | ")" | messages[i] | ":" 361 | name | "+" | offset_begin | offset_end | endl; 362 #else 363 fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end); 364 #endif 365 } 366 // otherwise, print the whole line 367 else { 368 #ifdef __USE_STREAM__ 369 serr | "(" | frameNo | ")" | messages[i] | endl; 370 #else 371 fprintf( stderr, "(%i) %s\n", frameNo, messages[i] ); 372 #endif 373 } 374 } 375 376 free( messages ); 377 } 378 ) 379 380 void sigHandler_segv( __CFA_SIGPARMS__ ) { 381 LIB_DEBUG_DO( 382 #ifdef __USE_STREAM__ 383 serr | "*CFA runtime error* program cfa-cpp terminated with" 384 | (sig == SIGSEGV ? "segment fault." : "bus error.") 385 | endl; 386 #else 387 fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." ); 388 #endif 389 390 // skip first 2 stack frames 391 __kernel_backtrace( 1 ); 392 ) 393 exit( EXIT_FAILURE ); 394 } 395 396 // void sigHandler_abort( __CFA_SIGPARMS__ ) { 397 // // skip first 6 stack frames 398 // LIB_DEBUG_DO( __kernel_backtrace( 6 ); ) 399 400 // // reset default signal handler 401 // __kernel_sigdefault( SIGABRT ); 402 403 // raise( SIGABRT ); 404 // }
Note: See TracChangeset
for help on using the changeset viewer.