Changeset c457dc41
- Timestamp:
- May 14, 2021, 5:23:49 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 353aaba
- Parents:
- e2f601f
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified libcfa/src/concurrency/alarm.cfa ¶
re2f601f rc457dc41 38 38 39 39 void __kernel_set_timer( Duration alarm ) { 40 verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (%jins)", alarm`ns); 41 setitimer( ITIMER_REAL, &(itimerval){ alarm }, 0p ); 40 alarm = max(alarm, 1`us); 41 itimerval otv @= { 0 }; 42 getitimer( ITIMER_REAL, &otv ); 43 Duration od = { otv.it_value }; 44 if(od == 0 || od > alarm) { 45 setitimer( ITIMER_REAL, &(itimerval){ alarm }, 0p ); 46 } 42 47 } 43 48 … … 46 51 //============================================================================================= 47 52 48 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period) with( this ) { 53 void ?{}( alarm_node_t & this, $thread * thrd, Duration alarm, Duration period) with( this ) { 54 this.initial = alarm; 55 this.period = period; 49 56 this.thrd = thrd; 50 this.alarm = alarm;51 this.period = period;52 57 set = false; 53 58 type = User; 54 59 } 55 60 56 void ?{}( alarm_node_t & this, processor * proc, Time alarm, Duration period ) with( this ) { 61 void ?{}( alarm_node_t & this, processor * proc, Duration alarm, Duration period ) with( this ) { 62 this.initial = alarm; 63 this.period = period; 57 64 this.proc = proc; 58 this.alarm = alarm;59 this.period = period;60 65 set = false; 61 66 type = Kernel; 62 67 } 63 void ?{}( alarm_node_t & this, Alarm_Callback callback, Timealarm, Duration period ) with( this ) {64 this. alarm= alarm;65 this.period = period;68 void ?{}( alarm_node_t & this, Alarm_Callback callback, Duration alarm, Duration period ) with( this ) { 69 this.initial = alarm; 70 this.period = period; 66 71 this.callback = callback; 67 72 set = false; … … 77 82 void insert( alarm_list_t * this, alarm_node_t * n ) { 78 83 alarm_node_t * it = & (*this)`first; 79 while( it && (n-> alarm > it->alarm) ) {84 while( it && (n->timeval > it->timeval) ) { 80 85 it = & (*it)`next; 81 86 } … … 105 110 lock( event_kernel->lock __cfaabi_dbg_ctx2 ); 106 111 { 107 verify( validate( alarms ));108 bool first = ! & alarms`first;112 Time curr = __kernel_get_time(); 113 this->timeval = curr + this->initial; 109 114 110 __cfadbg_print_safe( preemption, " KERNEL: alarm inserting %p (%lu).\n", this, this->alarm.tn ); 115 /* paranoid */ verify( validate( alarms ) ); 116 117 __cfadbg_print_safe( preemption, " KERNEL: alarm inserting %p (%lu -> %lu).\n", this, curr.tn, this->timeval.tn ); 111 118 insert( &alarms, this ); 112 if( first ) { 113 __kernel_set_timer( alarms`first.alarm - __kernel_get_time() ); 114 } 119 __kernel_set_timer( this->initial ); 115 120 } 116 121 unlock( event_kernel->lock ); … … 136 141 137 142 void sleep( Duration duration ) { 138 alarm_node_t node = { active_thread(), __kernel_get_time() +duration, 0`s };143 alarm_node_t node = { active_thread(), duration, 0`s }; 139 144 140 145 register_self( &node ); -
TabularUnified libcfa/src/concurrency/alarm.hfa ¶
re2f601f rc457dc41 46 46 47 47 struct alarm_node_t { 48 Time alarm;// time when alarm goes off49 Duration period; 48 Duration initial; // time when alarm goes off 49 Duration period; // if > 0 => period of alarm 50 50 51 51 inline dlink(alarm_node_t); 52 52 53 53 union { 54 $thread * thrd; 55 processor * proc; 56 Alarm_Callback callback; 54 $thread * thrd; // thrd who created event 55 processor * proc; // proc who created event 56 Alarm_Callback callback; // callback to handle event 57 57 }; 58 58 59 bool set :1; // whether or not the alarm has be registered 60 enum alarm_type type; // true if this is not a user defined alarm 59 Time timeval; // actual time at which the alarm goes off 60 enum alarm_type type; // true if this is not a user defined alarm 61 bool set :1; // whether or not the alarm has be registered 61 62 }; 62 63 P9_EMBEDDED( alarm_node_t, dlink(alarm_node_t) ) 63 64 64 void ?{}( alarm_node_t & this, $thread * thrd, Timealarm, Duration period );65 void ?{}( alarm_node_t & this, processor * proc, Timealarm, Duration period );66 void ?{}( alarm_node_t & this, Alarm_Callback callback, Timealarm, Duration period );65 void ?{}( alarm_node_t & this, $thread * thrd, Duration alarm, Duration period ); 66 void ?{}( alarm_node_t & this, processor * proc, Duration alarm, Duration period ); 67 void ?{}( alarm_node_t & this, Alarm_Callback callback, Duration alarm, Duration period ); 67 68 void ^?{}( alarm_node_t & this ); 68 69 -
TabularUnified libcfa/src/concurrency/clib/cfathread.cfa ¶
re2f601f rc457dc41 27 27 extern void __cfactx_invoke_thread(void (*main)(void *), void * this); 28 28 } 29 30 extern Time __kernel_get_time(); 29 31 30 32 //================================================================================ … … 265 267 int cfathread_cond_timedwait(cfathread_cond_t *restrict cond, cfathread_mutex_t *restrict mut, const struct timespec *restrict abstime) __attribute__((nonnull (1,2,3))) { 266 268 Time t = { *abstime }; 267 if( wait( (*cond)->impl, (*mut)->impl, t ) ) { 269 timespec curr; 270 clock_gettime( CLOCK_REALTIME, &curr ); 271 Time c = { curr }; 272 if( wait( (*cond)->impl, (*mut)->impl, t - c ) ) { 268 273 return 0; 269 274 } -
TabularUnified libcfa/src/concurrency/clib/cfathread.h ¶
re2f601f rc457dc41 80 80 81 81 typedef struct cfathread_cond_attr { 82 // WARNING: adding support for pthread_condattr_setclock would require keeping track of the clock 83 // and reading it in cond_timedwait 82 84 } cfathread_condattr_t; 83 85 typedef struct cfathread_condition * cfathread_cond_t; -
TabularUnified libcfa/src/concurrency/locks.cfa ¶
re2f601f rc457dc41 191 191 }; 192 192 193 void ?{}( alarm_node_wrap(L) & this, Timealarm, Duration period, Alarm_Callback callback, condition_variable(L) * c, info_thread(L) * i ) {193 void ?{}( alarm_node_wrap(L) & this, Duration alarm, Duration period, Alarm_Callback callback, condition_variable(L) * c, info_thread(L) * i ) { 194 194 this.alarm_node{ callback, alarm, period }; 195 195 this.cond = c; … … 313 313 314 314 // helper for wait()'s' with a timeout 315 void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Timet ) with(this) {315 void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t ) with(this) { 316 316 lock( lock __cfaabi_dbg_ctx2 ); 317 317 size_t recursion_count = queue_and_get_recursion(this, &info); … … 340 340 void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) { WAIT( info, &l ) } 341 341 342 bool wait( condition_variable(L) & this, Duration duration ) with(this) { WAIT_TIME( 0 , 0p , __kernel_get_time() + duration ) } 343 bool wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, 0p , __kernel_get_time() + duration ) } 344 bool wait( condition_variable(L) & this, Time time ) with(this) { WAIT_TIME( 0 , 0p , time ) } 345 bool wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) { WAIT_TIME( info, 0p , time ) } 346 bool wait( condition_variable(L) & this, L & l, Duration duration ) with(this) { WAIT_TIME( 0 , &l , __kernel_get_time() + duration ) } 347 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , __kernel_get_time() + duration ) } 348 bool wait( condition_variable(L) & this, L & l, Time time ) with(this) { WAIT_TIME( 0 , &l , time ) } 349 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) { WAIT_TIME( info, &l , time ) } 342 bool wait( condition_variable(L) & this, Duration duration ) with(this) { WAIT_TIME( 0 , 0p , duration ) } 343 bool wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, 0p , duration ) } 344 bool wait( condition_variable(L) & this, L & l, Duration duration ) with(this) { WAIT_TIME( 0 , &l , duration ) } 345 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , duration ) } 350 346 } 351 347 -
TabularUnified libcfa/src/concurrency/locks.hfa ¶
re2f601f rc457dc41 290 290 bool wait( condition_variable(L) & this, Duration duration ); 291 291 bool wait( condition_variable(L) & this, uintptr_t info, Duration duration ); 292 bool wait( condition_variable(L) & this, Time time );293 bool wait( condition_variable(L) & this, uintptr_t info, Time time );294 292 295 293 void wait( condition_variable(L) & this, L & l ); … … 297 295 bool wait( condition_variable(L) & this, L & l, Duration duration ); 298 296 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ); 299 bool wait( condition_variable(L) & this, L & l, Time time ); 300 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ); 301 } 297 } -
TabularUnified libcfa/src/concurrency/preemption.cfa ¶
re2f601f rc457dc41 18 18 19 19 #include "preemption.hfa" 20 20 21 #include <assert.h> 21 22 … … 26 27 #include <limits.h> // PTHREAD_STACK_MIN 27 28 29 #include "bits/debug.hfa" 28 30 #include "bits/signal.hfa" 29 31 #include "kernel_private.hfa" … … 105 107 static inline alarm_node_t * get_expired( alarm_list_t * alarms, Time currtime ) { 106 108 if( ! & (*alarms)`first ) return 0p; // If no alarms return null 107 if( (*alarms)`first. alarm>= currtime ) return 0p; // If alarms head not expired return null109 if( (*alarms)`first.timeval >= currtime ) return 0p; // If alarms head not expired return null 108 110 return pop(alarms); // Otherwise just pop head 109 111 } … … 141 143 if( period > 0 ) { 142 144 __cfadbg_print_buffer_local( preemption, " KERNEL: alarm period is %lu.\n", period`ns ); 143 node-> alarm = currtime + period;// Alarm is periodic, add currtime to it (used cached current time)145 node->timeval = currtime + period; // Alarm is periodic, add currtime to it (used cached current time) 144 146 insert( alarms, node ); // Reinsert the node for the next time it triggers 145 147 } … … 148 150 // If there are still alarms pending, reset the timer 149 151 if( & (*alarms)`first ) { 150 Duration delta = (*alarms)`first.alarm - currtime; 151 Duration capped = max(delta, 50`us); 152 __kernel_set_timer( capped ); 152 Duration delta = (*alarms)`first.timeval - currtime; 153 __kernel_set_timer( delta ); 153 154 } 154 155 } … … 160 161 // Alarms need to be enabled 161 162 if ( duration > 0 && ! alarm->set ) { 162 alarm-> alarm = __kernel_get_time() +duration;163 alarm->period = duration;163 alarm->initial = duration; 164 alarm->period = duration; 164 165 register_self( alarm ); 165 166 } … … 167 168 else if ( duration == 0 && alarm->set ) { 168 169 unregister_self( alarm ); 169 alarm-> alarm= 0;170 alarm->period = 0;170 alarm->initial = 0; 171 alarm->period = 0; 171 172 } 172 173 // If alarm is different from previous, change it 173 174 else if ( duration > 0 && alarm->period != duration ) { 174 175 unregister_self( alarm ); 175 alarm-> alarm = __kernel_get_time() +duration;176 alarm->period = duration;176 alarm->initial = duration; 177 alarm->period = duration; 177 178 register_self( alarm ); 178 179 } … … 599 600 600 601 // Notify the alarm thread of the shutdown 601 sigval val = { 1 }; 602 sigval val; 603 val.sival_int = 0; 602 604 pthread_sigqueue( alarm_thread, SIGALRM, val ); 603 605 … … 619 621 // Used by thread to control when they want to receive preemption signals 620 622 void ?{}( preemption_scope & this, processor * proc ) { 621 (this.alarm){ proc, (Time){ 0 }, 0`s };623 (this.alarm){ proc, 0`s, 0`s }; 622 624 this.proc = proc; 623 625 this.proc->preemption_alarm = &this.alarm; … … 705 707 int sig = sigwaitinfo( &mask, &info ); 706 708 709 __cfadbg_print_buffer_decl ( preemption, " KERNEL: sigwaitinfo returned %d, c: %d, v: %d\n", sig, info.si_code, info.si_value.sival_int ); 710 __cfadbg_print_buffer_local( preemption, " KERNEL: SI_QUEUE %d, SI_TIMER %d, SI_KERNEL %d\n", SI_QUEUE, SI_TIMER, SI_KERNEL ); 711 707 712 if( sig < 0 ) { 708 713 //Error! … … 711 716 case EAGAIN : 712 717 case EINTR : 713 {__cfa abi_dbg_print_buffer_decl(" KERNEL: Spurious wakeup %d.\n", err );}718 {__cfadbg_print_buffer_local( preemption, " KERNEL: Spurious wakeup %d.\n", err );} 714 719 continue; 715 720 case EINVAL : … … 723 728 assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int); 724 729 725 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );726 730 // Switch on the code (a.k.a. the sender) to 727 731 switch( info.si_code ) 728 732 { 733 // Signal was not sent by the kernel but by an other thread 734 case SI_QUEUE: 735 // other threads may signal the alarm thread to shut it down 736 // or to manual cause the preemption tick 737 // use info.si_value and handle the case here 738 switch( info.si_value.sival_int ) { 739 case 0: 740 goto EXIT; 741 default: 742 abort( "SI_QUEUE with val %d", info.si_value.sival_int); 743 } 744 // fallthrough 729 745 // Timers can apparently be marked as sent for the kernel 730 746 // In either case, tick preemption … … 736 752 unlock( event_kernel->lock ); 737 753 break; 738 // Signal was not sent by the kernel but by an other thread739 case SI_QUEUE:740 // For now, other thread only signal the alarm thread to shut it down741 // If this needs to change use info.si_value and handle the case here742 goto EXIT;743 754 } 744 755 }
Note: See TracChangeset
for help on using the changeset viewer.