Changeset 82ff5845
- Timestamp:
- Jun 8, 2017, 1:48:12 PM (8 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:
- a724ac1
- Parents:
- 8b8152e
- Location:
- src/libcfa/concurrency
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/libcfa/concurrency/alarm.c ¶
r8b8152e r82ff5845 16 16 17 17 extern "C" { 18 #include <errno.h> 19 #include <stdio.h> 20 #include <string.h> 18 21 #include <time.h> 22 #include <unistd.h> 19 23 #include <sys/time.h> 20 24 } … … 22 26 #include "alarm.h" 23 27 #include "kernel_private.h" 28 #include "libhdr.h" 24 29 #include "preemption.h" 25 30 … … 31 36 timespec curr; 32 37 clock_gettime( CLOCK_REALTIME, &curr ); 33 return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec; 38 __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec; 39 LIB_DEBUG_DO( 40 char text[256]; 41 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : current time is %lu\n", curr_time ); 42 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 43 ); 44 return curr_time; 34 45 } 35 46 36 47 void __kernel_set_timer( __cfa_time_t alarm ) { 48 49 LIB_DEBUG_DO( 50 char text[256]; 51 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm ); 52 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 53 ); 54 37 55 itimerval val; 38 56 val.it_value.tv_sec = alarm / TIMEGRAN; // seconds … … 128 146 lock( &systemProcessor->alarm_lock ); 129 147 { 148 bool first = !systemProcessor->alarms.head; 149 130 150 insert( &systemProcessor->alarms, this ); 131 151 if( systemProcessor->pending_alarm ) { 132 152 tick_preemption(); 153 } 154 if( first ) { 155 __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() ); 133 156 } 134 157 } -
TabularUnified src/libcfa/concurrency/invoke.c ¶
r8b8152e r82ff5845 30 30 extern void __suspend_internal(void); 31 31 extern void __leave_monitor_desc( struct monitor_desc * this ); 32 extern void disable_interrupts(); 33 extern void enable_interrupts(); 32 34 33 35 void CtxInvokeCoroutine( … … 67 69 struct monitor_desc* mon = &thrd->mon; 68 70 cor->state = Active; 71 enable_interrupts(); 69 72 70 73 // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this); 71 74 main( this ); 72 75 76 disable_interrupts(); 73 77 __leave_monitor_desc( mon ); 74 78 -
TabularUnified src/libcfa/concurrency/kernel.c ¶
r8b8152e r82ff5845 154 154 (&this->terminated){}; 155 155 this->is_terminated = false; 156 this->disable_preempt_count = 0; 156 this->preemption_alarm = NULL; 157 this->preemption = default_preemption(); 158 this->disable_preempt_count = 1; 157 159 this->pending_preemption = false; 160 this->kernel_thread = pthread_self(); 158 161 159 162 this->runner = runner; 160 LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);163 LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner); 161 164 runner{ this }; 162 165 } … … 240 243 //Update global state 241 244 this->current_thread = dst; 245 246 LIB_DEBUG_PRINT_SAFE("Kernel : running %p\n", dst); 242 247 243 248 // Context Switch to the thread … … 322 327 void start(processor * this) { 323 328 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 324 329 330 // SIGALRM must only be caught by the system processor 331 sigset_t old_mask; 332 bool is_system_proc = this_processor == &systemProcessor->proc; 333 if ( is_system_proc ) { 334 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the 335 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user 336 // processor, and toggle back (below) previous signal mask of the system processor. 337 338 sigset_t new_mask; 339 sigemptyset( &new_mask ); 340 sigemptyset( &old_mask ); 341 sigaddset( &new_mask, SIGALRM ); 342 343 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) { 344 abortf( "internal error, sigprocmask" ); 345 } 346 347 assert( ! sigismember( &old_mask, SIGALRM ) ); 348 } 349 325 350 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 351 352 // Toggle back previous signal mask of system processor. 353 if ( is_system_proc ) { 354 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) { 355 abortf( "internal error, sigprocmask" ); 356 } // if 357 } // if 326 358 327 359 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); … … 347 379 } 348 380 349 void ScheduleInternal() { 381 void BlockInternal() { 382 disable_interrupts(); 350 383 suspend(); 351 } 352 353 void ScheduleInternal( spinlock * lock ) { 384 enable_interrupts(); 385 } 386 387 void BlockInternal( spinlock * lock ) { 388 disable_interrupts(); 354 389 this_processor->finish.action_code = Release; 355 390 this_processor->finish.lock = lock; 356 391 suspend(); 357 } 358 359 void ScheduleInternal( thread_desc * thrd ) { 392 enable_interrupts(); 393 } 394 395 void BlockInternal( thread_desc * thrd ) { 396 disable_interrupts(); 360 397 this_processor->finish.action_code = Schedule; 361 398 this_processor->finish.thrd = thrd; 362 399 suspend(); 363 } 364 365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) { 400 enable_interrupts(); 401 } 402 403 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 404 disable_interrupts(); 366 405 this_processor->finish.action_code = Release_Schedule; 367 406 this_processor->finish.lock = lock; 368 407 this_processor->finish.thrd = thrd; 369 408 suspend(); 370 } 371 372 void ScheduleInternal(spinlock ** locks, unsigned short count) { 409 enable_interrupts(); 410 } 411 412 void BlockInternal(spinlock ** locks, unsigned short count) { 413 disable_interrupts(); 373 414 this_processor->finish.action_code = Release_Multi; 374 415 this_processor->finish.locks = locks; 375 416 this_processor->finish.lock_count = count; 376 417 suspend(); 377 } 378 379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 418 enable_interrupts(); 419 } 420 421 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 422 disable_interrupts(); 380 423 this_processor->finish.action_code = Release_Multi_Schedule; 381 424 this_processor->finish.locks = locks; … … 384 427 this_processor->finish.thrd_count = thrd_count; 385 428 suspend(); 429 enable_interrupts(); 386 430 } 387 431 … … 403 447 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 404 448 405 // Enable preemption406 kernel_start_preemption();407 408 449 // Initialize the system cluster 409 450 systemCluster = (cluster *)&systemCluster_storage; … … 426 467 this_processor->current_coroutine = &mainThread->cor; 427 468 469 // Enable preemption 470 kernel_start_preemption(); 471 428 472 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX 429 473 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that … … 435 479 // THE SYSTEM IS NOW COMPLETELY RUNNING 436 480 LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n"); 481 482 enable_interrupts(); 437 483 } 438 484 … … 447 493 448 494 // THE SYSTEM IS NOW COMPLETELY STOPPED 495 496 // Disable preemption 497 kernel_stop_preemption(); 449 498 450 499 // Destroy the system processor and its context in reverse order of construction … … 550 599 if( !this->cond ) { 551 600 append( &this->blocked, this_thread() ); 552 ScheduleInternal( &this->lock );601 BlockInternal( &this->lock ); 553 602 lock( &this->lock ); 554 603 } -
TabularUnified src/libcfa/concurrency/kernel_private.h ¶
r8b8152e r82ff5845 28 28 thread_desc * nextThread(cluster * this); 29 29 30 void ScheduleInternal(void);31 void ScheduleInternal(spinlock * lock);32 void ScheduleInternal(thread_desc * thrd);33 void ScheduleInternal(spinlock * lock, thread_desc * thrd);34 void ScheduleInternal(spinlock ** locks, unsigned short count);35 void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);30 void BlockInternal(void); 31 void BlockInternal(spinlock * lock); 32 void BlockInternal(thread_desc * thrd); 33 void BlockInternal(spinlock * lock, thread_desc * thrd); 34 void BlockInternal(spinlock ** locks, unsigned short count); 35 void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count); 36 36 37 37 //----------------------------------------------------------------------------- … … 60 60 extern thread_local processor * this_processor; 61 61 62 static inline void disable_interrupts() { 63 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 64 assert( prev != (unsigned short) -1 ); 65 } 66 67 static inline void enable_interrupts_noRF() { 68 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 69 assert( prev != (unsigned short) 0 ); 70 } 71 72 static inline void enable_interrupts() { 73 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 74 assert( prev != (unsigned short) 0 ); 75 if( prev == 1 && this_processor->pending_preemption ) { 76 ScheduleInternal( this_processor->current_thread ); 77 this_processor->pending_preemption = false; 78 } 62 extern "C" { 63 void disable_interrupts(); 64 void enable_interrupts_noRF(); 65 void enable_interrupts(); 79 66 } 80 67 -
TabularUnified src/libcfa/concurrency/monitor.c ¶
r8b8152e r82ff5845 63 63 append( &this->entry_queue, thrd ); 64 64 LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd); 65 ScheduleInternal( &this->lock );66 67 // ScheduleInternal will unlock spinlock, no need to unlock ourselves65 BlockInternal( &this->lock ); 66 67 //BlockInternal will unlock spinlock, no need to unlock ourselves 68 68 return; 69 69 } … … 172 172 unsigned short count = this->monitor_count; 173 173 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 174 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal174 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 175 175 176 176 LIB_DEBUG_PRINT_SAFE("count %i\n", count); … … 210 210 211 211 // Everything is ready to go to sleep 212 ScheduleInternal( locks, count, threads, thread_count );212 BlockInternal( locks, count, threads, thread_count ); 213 213 214 214 … … 283 283 unsigned short count = this->monitor_count; 284 284 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 285 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal285 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 286 286 287 287 lock_all( this->monitors, locks, count ); … … 311 311 312 312 //Everything is ready to go to sleep 313 ScheduleInternal( locks, count, &signallee, 1 );313 BlockInternal( locks, count, &signallee, 1 ); 314 314 315 315 … … 343 343 // unsigned short count = this->current_monitor_count; 344 344 // unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 345 // spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal345 // spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 346 346 347 347 // lock_all( this->current_monitors, locks, count ); … … 352 352 353 353 // // // Everything is ready to go to sleep 354 // // ScheduleInternal( locks, count, threads, thread_count );354 // // BlockInternal( locks, count, threads, thread_count ); 355 355 356 356 -
TabularUnified src/libcfa/concurrency/preemption.c ¶
r8b8152e r82ff5845 18 18 19 19 extern "C" { 20 #include <errno.h> 20 21 #include <signal.h> 21 } 22 23 #define __CFA_DEFAULT_PREEMPTION__ 10 22 #include <stdio.h> 23 #include <string.h> 24 #include <unistd.h> 25 } 26 27 #include "libhdr.h" 28 29 #define __CFA_DEFAULT_PREEMPTION__ 10000 24 30 25 31 __attribute__((weak)) unsigned int default_preemption() { … … 27 33 } 28 34 35 #define __CFA_SIGCXT__ ucontext_t * 36 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt 37 29 38 static void preempt( processor * this ); 30 39 static void timeout( thread_desc * this ); 31 40 41 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ); 42 void sigHandler_alarm ( __CFA_SIGPARMS__ ); 43 44 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); 45 32 46 //============================================================================================= 33 47 // Kernel Preemption logic … … 35 49 36 50 void kernel_start_preemption() { 37 51 LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n"); 52 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); 53 __kernel_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); 54 } 55 56 void kernel_stop_preemption() { 57 //Block all signals, we are no longer in a position to handle them 58 sigset_t mask; 59 sigfillset( &mask ); 60 sigprocmask( SIG_BLOCK, &mask, NULL ); 61 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n"); 38 62 } 39 63 40 64 void tick_preemption() { 65 LIB_DEBUG_DO( 66 char text[256]; 67 __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" ); 68 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 69 ); 70 41 71 alarm_list_t * alarms = &systemProcessor->alarms; 42 72 __cfa_time_t currtime = __kernel_get_time(); 43 73 while( alarms->head && alarms->head->alarm < currtime ) { 44 74 alarm_node_t * node = pop(alarms); 75 LIB_DEBUG_DO( 76 len = snprintf( text, 256, "Ticking %p\n", node ); 77 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 78 ); 45 79 if( node->kernel_alarm ) { 46 80 preempt( node->proc ); … … 51 85 52 86 if( node->period > 0 ) { 53 node->alarm +=node->period;87 node->alarm = currtime + node->period; 54 88 insert( alarms, node ); 55 89 } … … 62 96 __kernel_set_timer( alarms->head->alarm - currtime ); 63 97 } 98 99 LIB_DEBUG_DO( 100 len = snprintf( text, 256, "Ticking preemption done\n" ); 101 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 102 ); 64 103 } 65 104 66 105 void update_preemption( processor * this, __cfa_time_t duration ) { 67 // assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 ); 106 LIB_DEBUG_DO( 107 char text[256]; 108 __attribute__((unused)) int len = snprintf( text, 256, "Processor : updating preemption to %lu\n", duration ); 109 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 110 ); 111 68 112 alarm_node_t * alarm = this->preemption_alarm; 113 duration *= 1000; 69 114 70 115 // Alarms need to be enabled … … 94 139 this->proc->preemption_alarm = &this->alarm; 95 140 update_preemption( this->proc, this->proc->preemption ); 141 142 // enable_interrupts(); 96 143 } 97 144 98 145 void ^?{}( preemption_scope * this ) { 146 disable_interrupts(); 147 99 148 update_preemption( this->proc, 0 ); 100 149 } … … 103 152 // Kernel Signal logic 104 153 //============================================================================================= 154 155 extern "C" { 156 void disable_interrupts() { 157 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 158 assert( prev != (unsigned short) -1 ); 159 } 160 161 void enable_interrupts_noRF() { 162 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 163 assert( prev != (unsigned short) 0 ); 164 } 165 166 void enable_interrupts() { 167 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 168 assert( prev != (unsigned short) 0 ); 169 if( prev == 1 && this_processor->pending_preemption ) { 170 this_processor->pending_preemption = false; 171 LIB_DEBUG_DO( 172 char text[256]; 173 __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch\n" ); 174 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 175 ); 176 BlockInternal( this_processor->current_thread ); 177 } 178 } 179 } 180 181 static inline void signal_unblock( bool alarm ) { 182 sigset_t mask; 183 sigemptyset( &mask ); 184 sigaddset( &mask, SIGUSR1 ); 185 186 if( alarm ) sigaddset( &mask, SIGALRM ); 187 188 if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 189 abortf( "internal error, sigprocmask" ); 190 } // if 191 } 105 192 106 193 static inline bool preemption_ready() { … … 116 203 } 117 204 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 205 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 206 207 LIB_DEBUG_DO( 208 char text[256]; 209 __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH\n" ); 210 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 211 ); 212 213 signal_unblock( false ); 119 214 if( preemption_ready() ) { 120 ScheduleInternal( this_processor->current_thread ); 215 LIB_DEBUG_DO( 216 len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread\n" ); 217 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 218 ); 219 BlockInternal( this_processor->current_thread ); 121 220 } 122 221 else { 222 LIB_DEBUG_DO( 223 len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" ); 224 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 225 ); 123 226 defer_ctxSwitch(); 124 227 } 125 228 } 126 229 127 void sigHandler_alarm( __attribute__((unused)) int sig ) { 230 void sigHandler_alarm( __CFA_SIGPARMS__ ) { 231 232 LIB_DEBUG_DO( 233 char text[256]; 234 __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH\n" ); 235 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 236 ); 237 238 signal_unblock( true ); 128 239 if( try_lock( &systemProcessor->alarm_lock ) ) { 129 240 tick_preemption(); … … 133 244 defer_alarm(); 134 245 } 246 247 if( preemption_ready() && this_processor->pending_preemption ) { 248 LIB_DEBUG_DO( 249 len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" ); 250 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 251 ); 252 this_processor->pending_preemption = false; 253 BlockInternal( this_processor->current_thread ); 254 } 135 255 } 136 256 137 257 static void preempt( processor * this ) { 138 pthread_kill( this->kernel_thread, SIGUSR1 ); 258 LIB_DEBUG_DO( 259 char text[256]; 260 __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this ); 261 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 262 ); 263 264 if( this != systemProcessor ) { 265 pthread_kill( this->kernel_thread, SIGUSR1 ); 266 } 267 else { 268 defer_ctxSwitch(); 269 } 139 270 } 140 271 … … 142 273 //TODO : implement waking threads 143 274 } 275 276 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) { 277 struct sigaction act; 278 279 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 280 sigemptyset( &act.sa_mask ); 281 sigaddset( &act.sa_mask, SIGALRM ); // disabled during signal handler 282 sigaddset( &act.sa_mask, SIGUSR1 ); 283 284 act.sa_flags = flags; 285 286 if ( sigaction( sig, &act, NULL ) == -1 ) { 287 // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES! 288 char helpText[256]; 289 __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 290 sig, handler, flags, errno, strerror( errno ) ); 291 LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len ); 292 _exit( EXIT_FAILURE ); 293 } // if 294 } -
TabularUnified src/libcfa/concurrency/thread.c ¶
r8b8152e r82ff5845 84 84 85 85 void yield( void ) { 86 ScheduleInternal( this_processor->current_thread );86 BlockInternal( this_processor->current_thread ); 87 87 } 88 88
Note: See TracChangeset
for help on using the changeset viewer.