- File:
-
- 1 edited
-
src/libcfa/concurrency/preemption.c (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
rc5ac6d5 rb227f68 15 15 // 16 16 17 #include "libhdr.h" 17 18 #include "preemption.h" 18 19 19 20 extern "C" { 21 #include <errno.h> 22 #include <execinfo.h> 23 #define __USE_GNU 20 24 #include <signal.h> 21 } 22 23 #define __CFA_DEFAULT_PREEMPTION__ 10 25 #undef __USE_GNU 26 #include <stdio.h> 27 #include <string.h> 28 #include <unistd.h> 29 } 30 31 32 #ifdef __USE_STREAM__ 33 #include "fstream" 34 #endif 35 36 #define __CFA_DEFAULT_PREEMPTION__ 10000 24 37 25 38 __attribute__((weak)) unsigned int default_preemption() { … … 27 40 } 28 41 42 #define __CFA_SIGCXT__ ucontext_t * 43 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt 44 29 45 static void preempt( processor * this ); 30 46 static void timeout( thread_desc * this ); 31 47 48 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ); 49 void sigHandler_alarm ( __CFA_SIGPARMS__ ); 50 void sigHandler_segv ( __CFA_SIGPARMS__ ); 51 void sigHandler_abort ( __CFA_SIGPARMS__ ); 52 53 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); 54 32 55 //============================================================================================= 33 56 // Kernel Preemption logic … … 35 58 36 59 void kernel_start_preemption() { 37 38 } 60 LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n"); 61 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); 62 __kernel_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); 63 __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); 64 __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); 65 // __kernel_sigaction( SIGABRT, sigHandler_abort , SA_SIGINFO ); 66 } 67 68 void kernel_stop_preemption() { 69 //Block all signals, we are no longer in a position to handle them 70 sigset_t mask; 71 sigfillset( &mask ); 72 sigprocmask( SIG_BLOCK, &mask, NULL ); 73 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n"); 74 75 // assert( !systemProcessor->alarms.head ); 76 // assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head ); 77 } 78 79 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 39 80 40 81 void tick_preemption() { 82 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" ); 83 41 84 alarm_list_t * alarms = &systemProcessor->alarms; 42 85 __cfa_time_t currtime = __kernel_get_time(); 43 86 while( alarms->head && alarms->head->alarm < currtime ) { 44 87 alarm_node_t * node = pop(alarms); 88 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node ); 89 45 90 if( node->kernel_alarm ) { 46 91 preempt( node->proc ); … … 50 95 } 51 96 97 verify( validate( alarms ) ); 98 52 99 if( node->period > 0 ) { 53 node->alarm +=node->period;100 node->alarm = currtime + node->period; 54 101 insert( alarms, node ); 55 102 } … … 62 109 __kernel_set_timer( alarms->head->alarm - currtime ); 63 110 } 111 112 verify( validate( alarms ) ); 113 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" ); 64 114 } 65 115 66 116 void update_preemption( processor * this, __cfa_time_t duration ) { 67 // assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 ); 117 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration ); 118 68 119 alarm_node_t * alarm = this->preemption_alarm; 120 duration *= 1000; 69 121 70 122 // Alarms need to be enabled … … 97 149 98 150 void ^?{}( preemption_scope * this ) { 151 disable_interrupts(); 152 99 153 update_preemption( this->proc, 0 ); 100 154 } … … 104 158 //============================================================================================= 105 159 160 LIB_DEBUG_DO( static thread_local void * last_interrupt = 0; ) 161 162 extern "C" { 163 void disable_interrupts() { 164 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 165 verify( new_val < (unsigned short)65_000 ); 166 verify( new_val != (unsigned short) 0 ); 167 } 168 169 void enable_interrupts_noRF() { 170 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 171 verify( prev != (unsigned short) 0 ); 172 } 173 174 void enable_interrupts( DEBUG_CTX_PARAM ) { 175 processor * proc = this_processor; 176 thread_desc * thrd = this_thread; 177 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 178 verify( prev != (unsigned short) 0 ); 179 if( prev == 1 && proc->pending_preemption ) { 180 proc->pending_preemption = false; 181 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Executing deferred CtxSwitch on %p\n", this_processor ); 182 BlockInternal( thrd ); 183 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Executing deferred back\n" ); 184 } 185 186 LIB_DEBUG_DO( proc->last_enable = caller; ) 187 } 188 } 189 190 static inline void signal_unblock( int sig ) { 191 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p unblocking sig %i\n", this_processor, sig ); 192 193 // LIB_DEBUG_DO( 194 // sigset_t waiting; 195 // sigemptyset(&waiting); 196 // sigpending(&waiting); 197 // verify( !sigismember(&waiting, sig) ); 198 // ) 199 200 sigset_t mask; 201 sigemptyset( &mask ); 202 sigaddset( &mask, sig ); 203 204 if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 205 abortf( "internal error, sigprocmask" ); 206 } // if 207 } 208 106 209 static inline bool preemption_ready() { 107 return this_processor->disable_preempt_count == 0;210 return disable_preempt_count == 0; 108 211 } 109 212 … … 116 219 } 117 220 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 221 extern "C" { 222 __attribute__((noinline)) void __debug_break() { 223 pthread_kill( pthread_self(), SIGTRAP ); 224 } 225 } 226 227 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 228 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "CtxSw IRH %10p running %10p @ %10p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 229 LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[REG_RIP]); ) 230 119 231 if( preemption_ready() ) { 120 ScheduleInternal( this_processor->current_thread ); 232 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 233 signal_unblock( SIGUSR1 ); 234 BlockInternal( (thread_desc*)this_thread ); 235 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Back\n\n"); 236 } 237 else { 238 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Defering\n" ); 239 defer_ctxSwitch(); 240 signal_unblock( SIGUSR1 ); 241 } 242 } 243 244 void sigHandler_alarm( __CFA_SIGPARMS__ ) { 245 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "\nAlarm IRH %10p running %10p @ %10p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 246 LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[REG_RIP]); ) 247 248 if( try_lock( &systemProcessor->alarm_lock DEBUG_CTX2 ) ) { 249 tick_preemption(); 250 unlock( &systemProcessor->alarm_lock ); 251 } 252 else { 253 defer_alarm(); 254 } 255 256 signal_unblock( SIGALRM ); 257 258 if( preemption_ready() && this_processor->pending_preemption ) { 259 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 260 this_processor->pending_preemption = false; 261 BlockInternal( (thread_desc*)this_thread ); 262 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm Switch IRH : Back\n\n"); 263 } 264 } 265 266 static void preempt( processor * this ) { 267 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : signalling %p\n", this ); 268 269 if( this != systemProcessor ) { 270 pthread_kill( this->kernel_thread, SIGUSR1 ); 121 271 } 122 272 else { … … 125 275 } 126 276 127 void sigHandler_alarm( __attribute__((unused)) int sig ) {128 if( try_lock( &systemProcessor->alarm_lock ) ) {129 tick_preemption();130 unlock( &systemProcessor->alarm_lock );131 }132 else {133 defer_alarm();134 }135 }136 137 static void preempt( processor * this ) {138 pthread_kill( this->kernel_thread, SIGUSR1 );139 }140 141 277 static void timeout( thread_desc * this ) { 142 278 //TODO : implement waking threads 143 279 } 280 281 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) { 282 struct sigaction act; 283 284 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 285 act.sa_flags = flags; 286 287 // disabled during signal handler 288 sigemptyset( &act.sa_mask ); 289 sigaddset( &act.sa_mask, sig ); 290 291 if ( sigaction( sig, &act, NULL ) == -1 ) { 292 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 293 " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 294 sig, handler, flags, errno, strerror( errno ) 295 ); 296 _exit( EXIT_FAILURE ); 297 } 298 } 299 300 typedef void (*sa_handler_t)(int); 301 302 static void __kernel_sigdefault( int sig ) { 303 struct sigaction act; 304 305 // act.sa_handler = SIG_DFL; 306 act.sa_flags = 0; 307 sigemptyset( &act.sa_mask ); 308 309 if ( sigaction( sig, &act, NULL ) == -1 ) { 310 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 311 " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n", 312 sig, errno, strerror( errno ) 313 ); 314 _exit( EXIT_FAILURE ); 315 } 316 } 317 318 //============================================================================================= 319 // Terminating Signals logic 320 //============================================================================================= 321 322 LIB_DEBUG_DO( 323 static void __kernel_backtrace( int start ) { 324 // skip first N stack frames 325 326 enum { Frames = 50 }; 327 void * array[Frames]; 328 int size = backtrace( array, Frames ); 329 char ** messages = backtrace_symbols( array, size ); 330 331 // find executable name 332 *index( messages[0], '(' ) = '\0'; 333 #ifdef __USE_STREAM__ 334 serr | "Stack back trace for:" | messages[0] | endl; 335 #else 336 fprintf( stderr, "Stack back trace for: %s\n", messages[0]); 337 #endif 338 339 // skip last 2 stack frames after main 340 for ( int i = start; i < size && messages != NULL; i += 1 ) { 341 char * name = NULL; 342 char * offset_begin = NULL; 343 char * offset_end = NULL; 344 345 for ( char *p = messages[i]; *p; ++p ) { 346 // find parantheses and +offset 347 if ( *p == '(' ) { 348 name = p; 349 } 350 else if ( *p == '+' ) { 351 offset_begin = p; 352 } 353 else if ( *p == ')' ) { 354 offset_end = p; 355 break; 356 } 357 } 358 359 // if line contains symbol print it 360 int frameNo = i - start; 361 if ( name && offset_begin && offset_end && name < offset_begin ) { 362 // delimit strings 363 *name++ = '\0'; 364 *offset_begin++ = '\0'; 365 *offset_end++ = '\0'; 366 367 #ifdef __USE_STREAM__ 368 serr | "(" | frameNo | ")" | messages[i] | ":" 369 | name | "+" | offset_begin | offset_end | endl; 370 #else 371 fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end); 372 #endif 373 } 374 // otherwise, print the whole line 375 else { 376 #ifdef __USE_STREAM__ 377 serr | "(" | frameNo | ")" | messages[i] | endl; 378 #else 379 fprintf( stderr, "(%i) %s\n", frameNo, messages[i] ); 380 #endif 381 } 382 } 383 384 free( messages ); 385 } 386 ) 387 388 void sigHandler_segv( __CFA_SIGPARMS__ ) { 389 LIB_DEBUG_DO( 390 #ifdef __USE_STREAM__ 391 serr | "*CFA runtime error* program cfa-cpp terminated with" 392 | (sig == SIGSEGV ? "segment fault." : "bus error.") 393 | endl; 394 #else 395 fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." ); 396 #endif 397 398 // skip first 2 stack frames 399 __kernel_backtrace( 1 ); 400 ) 401 exit( EXIT_FAILURE ); 402 } 403 404 // void sigHandler_abort( __CFA_SIGPARMS__ ) { 405 // // skip first 6 stack frames 406 // LIB_DEBUG_DO( __kernel_backtrace( 6 ); ) 407 408 // // reset default signal handler 409 // __kernel_sigdefault( SIGABRT ); 410 411 // raise( SIGABRT ); 412 // }
Note:
See TracChangeset
for help on using the changeset viewer.