- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
rc5ac6d5 r0b33412 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 }
Note: See TracChangeset
for help on using the changeset viewer.