- File:
-
- 1 edited
-
src/libcfa/concurrency/preemption.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
r0b33412 rc5ac6d5 17 17 #include "preemption.h" 18 18 19 20 19 extern "C" { 21 #include <errno.h>22 #define __USE_GNU23 20 #include <signal.h> 24 #undef __USE_GNU25 #include <stdio.h>26 #include <string.h>27 #include <unistd.h>28 21 } 29 22 30 #include "libhdr.h" 31 32 #define __CFA_DEFAULT_PREEMPTION__ 10000 23 #define __CFA_DEFAULT_PREEMPTION__ 10 33 24 34 25 __attribute__((weak)) unsigned int default_preemption() { … … 36 27 } 37 28 38 #define __CFA_SIGCXT__ ucontext_t *39 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt40 41 29 static void preempt( processor * this ); 42 30 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 );48 31 49 32 //============================================================================================= … … 52 35 53 36 void kernel_start_preemption() { 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 ); 37 57 38 } 58 39 59 void kernel_stop_preemption() {60 //Block all signals, we are no longer in a position to handle them61 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 ); )71 72 40 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 79 41 alarm_list_t * alarms = &systemProcessor->alarms; 80 42 __cfa_time_t currtime = __kernel_get_time(); 81 43 while( alarms->head && alarms->head->alarm < currtime ) { 82 44 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 );87 45 if( node->kernel_alarm ) { 88 46 preempt( node->proc ); … … 92 50 } 93 51 94 LIB_DEBUG_DO( assert( validate( alarms ) ) );95 96 52 if( node->period > 0 ) { 97 node->alarm = currtime +node->period;53 node->alarm += node->period; 98 54 insert( alarms, node ); 99 55 } … … 106 62 __kernel_set_timer( alarms->head->alarm - currtime ); 107 63 } 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 );114 64 } 115 65 116 66 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 ); 122 67 // assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 ); 123 68 alarm_node_t * alarm = this->preemption_alarm; 124 duration *= 1000;125 69 126 70 // Alarms need to be enabled … … 153 97 154 98 void ^?{}( preemption_scope * this ) { 155 disable_interrupts();156 157 99 update_preemption( this->proc, 0 ); 158 100 } … … 162 104 //============================================================================================= 163 105 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 } // if203 }204 205 106 static inline bool preemption_ready() { 206 return disable_preempt_count == 0;107 return this_processor->disable_preempt_count == 0; 207 108 } 208 109 … … 215 116 } 216 117 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 ); 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 226 119 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 ); 120 ScheduleInternal( this_processor->current_thread ); 232 121 } 233 122 else { 234 LIB_DEBUG_DO(235 len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );236 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );237 );238 123 defer_ctxSwitch(); 239 124 } 240 125 } 241 126 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 ); 127 void sigHandler_alarm( __attribute__((unused)) int sig ) { 251 128 if( try_lock( &systemProcessor->alarm_lock ) ) { 252 129 tick_preemption(); … … 256 133 defer_alarm(); 257 134 } 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 }267 135 } 268 136 269 137 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 ); 275 276 if( this != systemProcessor ) { 277 pthread_kill( this->kernel_thread, SIGUSR1 ); 278 } 279 else { 280 defer_ctxSwitch(); 281 } 138 pthread_kill( this->kernel_thread, SIGUSR1 ); 282 139 } 283 140 … … 285 142 //TODO : implement waking threads 286 143 } 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 handler294 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 } // if306 }
Note:
See TracChangeset
for help on using the changeset viewer.