Changes in / [e9a3b20b:1a18423]
- Location:
- src
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/alarm.c
re9a3b20b r1a18423 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 … … 71 89 } 72 90 91 LIB_DEBUG_DO( bool validate( alarm_list_t * this ) { 92 alarm_node_t ** it = &this->head; 93 while( (*it) ) { 94 it = &(*it)->next; 95 } 96 97 return it == this->tail; 98 }) 99 73 100 static inline void insert_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t p ) { 74 assert( !n->next );101 verify( !n->next ); 75 102 if( p == this->tail ) { 76 103 this->tail = &n->next; … … 80 107 } 81 108 *p = n; 109 110 verify( validate( this ) ); 82 111 } 83 112 … … 89 118 90 119 insert_at( this, n, it ); 120 121 verify( validate( this ) ); 91 122 } 92 123 … … 100 131 head->next = NULL; 101 132 } 133 verify( validate( this ) ); 102 134 return head; 103 135 } … … 105 137 static inline void remove_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t it ) { 106 138 verify( it ); 107 verify( (*it) ->next== n );108 109 (*it) ->next= n->next;139 verify( (*it) == n ); 140 141 (*it) = n->next; 110 142 if( !n-> next ) { 111 143 this->tail = it; 112 144 } 113 145 n->next = NULL; 146 147 verify( validate( this ) ); 114 148 } 115 149 116 150 static inline void remove( alarm_list_t * this, alarm_node_t * n ) { 117 151 alarm_node_t ** it = &this->head; 118 while( (*it) && (*it) ->next!= n ) {152 while( (*it) && (*it) != n ) { 119 153 it = &(*it)->next; 120 154 } 121 155 156 verify( validate( this ) ); 157 122 158 if( *it ) { remove_at( this, n, it ); } 159 160 verify( validate( this ) ); 123 161 } 124 162 125 163 void register_self( alarm_node_t * this ) { 126 164 disable_interrupts(); 127 assert( !systemProcessor->pending_alarm );165 verify( !systemProcessor->pending_alarm ); 128 166 lock( &systemProcessor->alarm_lock ); 129 167 { 168 verify( validate( &systemProcessor->alarms ) ); 169 bool first = !systemProcessor->alarms.head; 170 130 171 insert( &systemProcessor->alarms, this ); 131 172 if( systemProcessor->pending_alarm ) { 132 173 tick_preemption(); 133 174 } 175 if( first ) { 176 __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() ); 177 } 134 178 } 135 179 unlock( &systemProcessor->alarm_lock ); 136 180 this->set = true; 137 enable_interrupts( );181 enable_interrupts( __PRETTY_FUNCTION__ ); 138 182 } 139 183 140 184 void unregister_self( alarm_node_t * this ) { 185 LIB_DEBUG_DO( 186 char text[256]; 187 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : unregister %p start\n", this ); 188 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 189 ); 141 190 disable_interrupts(); 142 191 lock( &systemProcessor->alarm_lock ); 143 remove( &systemProcessor->alarms, this ); 192 { 193 verify( validate( &systemProcessor->alarms ) ); 194 remove( &systemProcessor->alarms, this ); 195 } 144 196 unlock( &systemProcessor->alarm_lock ); 145 197 disable_interrupts(); 146 198 this->set = false; 147 } 199 LIB_DEBUG_DO( 200 len = snprintf( text, 256, "Kernel : unregister %p end\n", this ); 201 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 202 ); 203 } -
src/libcfa/concurrency/coroutine.c
re9a3b20b r1a18423 32 32 #include "invoke.h" 33 33 34 extern thread_local processor * this_processor;34 extern volatile thread_local processor * this_processor; 35 35 36 36 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/invoke.c
re9a3b20b r1a18423 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( const char * ); 32 34 33 35 void CtxInvokeCoroutine( … … 67 69 struct monitor_desc* mon = &thrd->mon; 68 70 cor->state = Active; 71 enable_interrupts( __PRETTY_FUNCTION__ ); 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 -
src/libcfa/concurrency/kernel
re9a3b20b r1a18423 90 90 unsigned int preemption; 91 91 92 unsigned short disable_preempt_count;92 bool pending_preemption; 93 93 94 bool pending_preemption;94 char * last_enable; 95 95 }; 96 96 -
src/libcfa/concurrency/kernel.c
re9a3b20b r1a18423 59 59 // Global state 60 60 61 thread_local processor * this_processor; 61 volatile thread_local processor * this_processor; 62 volatile thread_local unsigned short disable_preempt_count; 62 63 63 64 coroutine_desc * this_coroutine(void) { … … 142 143 this->preemption_alarm = NULL; 143 144 this->preemption = default_preemption(); 144 this->disable_preempt_count = 1; //Start with interrupts disabled145 145 this->pending_preemption = false; 146 146 … … 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(); 157 158 this->pending_preemption = false; 159 this->kernel_thread = pthread_self(); 158 160 159 161 this->runner = runner; 160 LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);162 LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner); 161 163 runner{ this }; 162 164 } 165 166 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 163 167 164 168 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) { … … 168 172 169 173 (&this->proc){ cltr, runner }; 174 175 verify( validate( &this->alarms ) ); 170 176 } 171 177 … … 209 215 if(readyThread) 210 216 { 217 verify( disable_preempt_count > 0 ); 218 211 219 runThread(this, readyThread); 220 221 verify( disable_preempt_count > 0 ); 212 222 213 223 //Some actions need to be taken from the kernel … … 289 299 processor * proc = (processor *) arg; 290 300 this_processor = proc; 301 disable_preempt_count = 1; 291 302 // SKULLDUGGERY: We want to create a context for the processor coroutine 292 303 // which is needed for the 2-step context switch. However, there is no reason … … 322 333 void start(processor * this) { 323 334 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 324 335 336 // SIGALRM must only be caught by the system processor 337 sigset_t old_mask; 338 bool is_system_proc = this_processor == &systemProcessor->proc; 339 if ( is_system_proc ) { 340 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the 341 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user 342 // processor, and toggle back (below) previous signal mask of the system processor. 343 344 sigset_t new_mask; 345 sigemptyset( &new_mask ); 346 sigemptyset( &old_mask ); 347 sigaddset( &new_mask, SIGALRM ); 348 349 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) { 350 abortf( "internal error, sigprocmask" ); 351 } 352 353 assert( ! sigismember( &old_mask, SIGALRM ) ); 354 } 355 325 356 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 357 358 // Toggle back previous signal mask of system processor. 359 if ( is_system_proc ) { 360 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) { 361 abortf( "internal error, sigprocmask" ); 362 } // if 363 } // if 326 364 327 365 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); … … 347 385 } 348 386 349 void ScheduleInternal() { 387 void BlockInternal() { 388 disable_interrupts(); 389 verify( disable_preempt_count > 0 ); 350 390 suspend(); 351 } 352 353 void ScheduleInternal( spinlock * lock ) { 391 verify( disable_preempt_count > 0 ); 392 enable_interrupts( __PRETTY_FUNCTION__ ); 393 } 394 395 void BlockInternal( spinlock * lock ) { 396 disable_interrupts(); 354 397 this_processor->finish.action_code = Release; 355 398 this_processor->finish.lock = lock; 399 400 verify( disable_preempt_count > 0 ); 356 401 suspend(); 357 } 358 359 void ScheduleInternal( thread_desc * thrd ) { 402 verify( disable_preempt_count > 0 ); 403 404 enable_interrupts( __PRETTY_FUNCTION__ ); 405 } 406 407 void BlockInternal( thread_desc * thrd ) { 408 disable_interrupts(); 360 409 this_processor->finish.action_code = Schedule; 361 410 this_processor->finish.thrd = thrd; 411 412 verify( disable_preempt_count > 0 ); 362 413 suspend(); 363 } 364 365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) { 414 verify( disable_preempt_count > 0 ); 415 416 enable_interrupts( __PRETTY_FUNCTION__ ); 417 } 418 419 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 420 disable_interrupts(); 366 421 this_processor->finish.action_code = Release_Schedule; 367 422 this_processor->finish.lock = lock; 368 423 this_processor->finish.thrd = thrd; 424 425 verify( disable_preempt_count > 0 ); 369 426 suspend(); 370 } 371 372 void ScheduleInternal(spinlock ** locks, unsigned short count) { 427 verify( disable_preempt_count > 0 ); 428 429 enable_interrupts( __PRETTY_FUNCTION__ ); 430 } 431 432 void BlockInternal(spinlock ** locks, unsigned short count) { 433 disable_interrupts(); 373 434 this_processor->finish.action_code = Release_Multi; 374 435 this_processor->finish.locks = locks; 375 436 this_processor->finish.lock_count = count; 437 438 verify( disable_preempt_count > 0 ); 376 439 suspend(); 377 } 378 379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 440 verify( disable_preempt_count > 0 ); 441 442 enable_interrupts( __PRETTY_FUNCTION__ ); 443 } 444 445 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 446 disable_interrupts(); 380 447 this_processor->finish.action_code = Release_Multi_Schedule; 381 448 this_processor->finish.locks = locks; … … 383 450 this_processor->finish.thrds = thrds; 384 451 this_processor->finish.thrd_count = thrd_count; 452 453 verify( disable_preempt_count > 0 ); 385 454 suspend(); 455 verify( disable_preempt_count > 0 ); 456 457 enable_interrupts( __PRETTY_FUNCTION__ ); 386 458 } 387 459 … … 403 475 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 404 476 405 // Enable preemption406 kernel_start_preemption();407 408 477 // Initialize the system cluster 409 478 systemCluster = (cluster *)&systemCluster_storage; … … 425 494 this_processor->current_thread = mainThread; 426 495 this_processor->current_coroutine = &mainThread->cor; 496 disable_preempt_count = 1; 497 498 // Enable preemption 499 kernel_start_preemption(); 427 500 428 501 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX … … 435 508 // THE SYSTEM IS NOW COMPLETELY RUNNING 436 509 LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n"); 510 511 enable_interrupts( __PRETTY_FUNCTION__ ); 437 512 } 438 513 439 514 void kernel_shutdown(void) { 440 515 LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n"); 516 517 disable_interrupts(); 441 518 442 519 // SKULLDUGGERY: Notify the systemProcessor it needs to terminates. … … 447 524 448 525 // THE SYSTEM IS NOW COMPLETELY STOPPED 526 527 // Disable preemption 528 kernel_stop_preemption(); 449 529 450 530 // Destroy the system processor and its context in reverse order of construction … … 550 630 if( !this->cond ) { 551 631 append( &this->blocked, this_thread() ); 552 ScheduleInternal( &this->lock ); 553 lock( &this->lock ); 554 } 555 unlock( &this->lock ); 632 BlockInternal( &this->lock ); 633 } 634 else { 635 unlock( &this->lock ); 636 } 556 637 } 557 638 … … 561 642 this->cond = true; 562 643 644 disable_interrupts(); 563 645 thread_desc * it; 564 646 while( it = pop_head( &this->blocked) ) { 565 647 ScheduleThread( it ); 566 648 } 649 enable_interrupts( __PRETTY_FUNCTION__ ); 567 650 } 568 651 unlock( &this->lock ); -
src/libcfa/concurrency/kernel_private.h
re9a3b20b r1a18423 30 30 thread_desc * nextThread(cluster * this); 31 31 32 void ScheduleInternal(void);33 void ScheduleInternal(spinlock * lock);34 void ScheduleInternal(thread_desc * thrd);35 void ScheduleInternal(spinlock * lock, thread_desc * thrd);36 void ScheduleInternal(spinlock ** locks, unsigned short count);37 void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);32 void BlockInternal(void); 33 void BlockInternal(spinlock * lock); 34 void BlockInternal(thread_desc * thrd); 35 void BlockInternal(spinlock * lock, thread_desc * thrd); 36 void BlockInternal(spinlock ** locks, unsigned short count); 37 void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count); 38 38 39 39 //----------------------------------------------------------------------------- … … 60 60 extern cluster * systemCluster; 61 61 extern system_proc_t * systemProcessor; 62 extern thread_local processor * this_processor; 62 extern volatile thread_local processor * this_processor; 63 extern volatile thread_local unsigned short disable_preempt_count; 63 64 64 static inline void disable_interrupts() { 65 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 66 assert( prev != (unsigned short) -1 ); 67 } 68 69 static inline void enable_interrupts_noRF() { 70 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 71 verify( prev != (unsigned short) 0 ); 72 } 73 74 static inline void enable_interrupts() { 75 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 76 verify( prev != (unsigned short) 0 ); 77 if( prev == 1 && this_processor->pending_preemption ) { 78 ScheduleInternal( this_processor->current_thread ); 79 this_processor->pending_preemption = false; 80 } 65 extern "C" { 66 void disable_interrupts(); 67 void enable_interrupts_noRF(); 68 void enable_interrupts( const char * ); 81 69 } 82 70 -
src/libcfa/concurrency/monitor.c
re9a3b20b r1a18423 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 } … … 170 170 unsigned short count = this->monitor_count; 171 171 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 172 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal172 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 173 173 174 174 LIB_DEBUG_PRINT_SAFE("count %i\n", count); … … 208 208 209 209 // Everything is ready to go to sleep 210 ScheduleInternal( locks, count, threads, thread_count );210 BlockInternal( locks, count, threads, thread_count ); 211 211 212 212 … … 281 281 unsigned short count = this->monitor_count; 282 282 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 283 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal283 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 284 284 285 285 lock_all( this->monitors, locks, count ); … … 309 309 310 310 //Everything is ready to go to sleep 311 ScheduleInternal( locks, count, &signallee, 1 );311 BlockInternal( locks, count, &signallee, 1 ); 312 312 313 313 … … 339 339 // unsigned short count = this->current_monitor_count; 340 340 // unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 341 // spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal341 // spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 342 342 343 343 // lock_all( this->current_monitors, locks, count ); … … 348 348 349 349 // // // Everything is ready to go to sleep 350 // // ScheduleInternal( locks, count, threads, thread_count );350 // // BlockInternal( locks, count, threads, thread_count ); 351 351 352 352 -
src/libcfa/concurrency/preemption.c
re9a3b20b r1a18423 17 17 #include "preemption.h" 18 18 19 19 20 extern "C" { 21 #include <errno.h> 22 #define __USE_GNU 20 23 #include <signal.h> 21 } 22 23 #define __CFA_DEFAULT_PREEMPTION__ 10 24 #undef __USE_GNU 25 #include <stdio.h> 26 #include <string.h> 27 #include <unistd.h> 28 } 29 30 #include "libhdr.h" 31 32 #define __CFA_DEFAULT_PREEMPTION__ 10000 24 33 25 34 __attribute__((weak)) unsigned int default_preemption() { … … 27 36 } 28 37 38 #define __CFA_SIGCXT__ ucontext_t * 39 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt 40 29 41 static void preempt( processor * this ); 30 42 static void timeout( thread_desc * this ); 43 44 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ); 45 void sigHandler_alarm ( __CFA_SIGPARMS__ ); 46 47 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); 31 48 32 49 //============================================================================================= … … 35 52 36 53 void kernel_start_preemption() { 37 38 } 54 LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n"); 55 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); 56 __kernel_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); 57 } 58 59 void kernel_stop_preemption() { 60 //Block all signals, we are no longer in a position to handle them 61 sigset_t mask; 62 sigfillset( &mask ); 63 sigprocmask( SIG_BLOCK, &mask, NULL ); 64 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n"); 65 66 assert( !systemProcessor->alarms.head ); 67 assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head ); 68 } 69 70 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 39 71 40 72 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 ); 78 41 79 alarm_list_t * alarms = &systemProcessor->alarms; 42 80 __cfa_time_t currtime = __kernel_get_time(); 43 81 while( alarms->head && alarms->head->alarm < currtime ) { 44 82 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 ); 45 87 if( node->kernel_alarm ) { 46 88 preempt( node->proc ); … … 50 92 } 51 93 94 LIB_DEBUG_DO( assert( validate( alarms ) ) ); 95 52 96 if( node->period > 0 ) { 53 node->alarm +=node->period;97 node->alarm = currtime + node->period; 54 98 insert( alarms, node ); 55 99 } … … 62 106 __kernel_set_timer( alarms->head->alarm - currtime ); 63 107 } 108 109 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 ); 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_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 ); 122 68 123 alarm_node_t * alarm = this->preemption_alarm; 124 duration *= 1000; 69 125 70 126 // Alarms need to be enabled … … 97 153 98 154 void ^?{}( preemption_scope * this ) { 155 disable_interrupts(); 156 99 157 update_preemption( this->proc, 0 ); 100 158 } … … 104 162 //============================================================================================= 105 163 164 extern "C" { 165 void disable_interrupts() { 166 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 167 verify( new_val < (unsigned short)65_000 ); 168 verify( new_val != (unsigned short) 0 ); 169 } 170 171 void enable_interrupts_noRF() { 172 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 173 verify( prev != (unsigned short) 0 ); 174 } 175 176 void enable_interrupts( const char * func ) { 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 && 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 ) { 194 sigset_t mask; 195 sigemptyset( &mask ); 196 sigaddset( &mask, SIGUSR1 ); 197 198 if( alarm ) sigaddset( &mask, SIGALRM ); 199 200 if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 201 abortf( "internal error, sigprocmask" ); 202 } // if 203 } 204 106 205 static inline bool preemption_ready() { 107 return this_processor->disable_preempt_count == 0;206 return disable_preempt_count == 0; 108 207 } 109 208 … … 116 215 } 117 216 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 217 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 ); 119 226 if( preemption_ready() ) { 120 ScheduleInternal( this_processor->current_thread ); 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 ); 121 232 } 122 233 else { 234 LIB_DEBUG_DO( 235 len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" ); 236 LIB_DEBUG_WRITE( STDERR_FILENO, text, len ); 237 ); 123 238 defer_ctxSwitch(); 124 239 } 125 240 } 126 241 127 void sigHandler_alarm( __attribute__((unused)) int sig ) { 242 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 ); 128 251 if( try_lock( &systemProcessor->alarm_lock ) ) { 129 252 tick_preemption(); … … 133 256 defer_alarm(); 134 257 } 258 259 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 ); 264 this_processor->pending_preemption = false; 265 BlockInternal( this_processor->current_thread ); 266 } 135 267 } 136 268 137 269 static void preempt( processor * this ) { 138 pthread_kill( this->kernel_thread, SIGUSR1 ); 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 ); 275 276 if( this != systemProcessor ) { 277 pthread_kill( this->kernel_thread, SIGUSR1 ); 278 } 279 else { 280 defer_ctxSwitch(); 281 } 139 282 } 140 283 … … 142 285 //TODO : implement waking threads 143 286 } 287 288 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) { 289 struct sigaction act; 290 291 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 292 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; 297 298 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 ); 304 _exit( EXIT_FAILURE ); 305 } // if 306 } -
src/libcfa/concurrency/thread.c
re9a3b20b r1a18423 28 28 } 29 29 30 extern thread_local processor * this_processor;30 extern volatile thread_local processor * this_processor; 31 31 32 32 //----------------------------------------------------------------------------- … … 84 84 85 85 void yield( void ) { 86 ScheduleInternal( this_processor->current_thread );86 BlockInternal( this_processor->current_thread ); 87 87 } 88 88 -
src/libcfa/libhdr/libdebug.h
re9a3b20b r1a18423 19 19 #ifdef __CFA_DEBUG__ 20 20 #define LIB_DEBUG_DO(x) x 21 #define LIB_NO_DEBUG_DO(x) ((void)0)21 #define LIB_NO_DEBUG_DO(x) 22 22 #else 23 #define LIB_DEBUG_DO(x) ((void)0)24 #define LIB_NO_DEBUG_DO(x) x 23 #define LIB_DEBUG_DO(x) 24 #define LIB_NO_DEBUG_DO(x) x 25 25 #endif 26 26
Note: See TracChangeset
for help on using the changeset viewer.