Changeset c457dc41


Ignore:
Timestamp:
May 14, 2021, 5:23:49 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
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
Message:

Fix sequential handling of timers

Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/alarm.cfa

    re2f601f rc457dc41  
    3838
    3939void __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        }
    4247}
    4348
     
    4651//=============================================================================================
    4752
    48 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period) with( this ) {
     53void ?{}( alarm_node_t & this, $thread * thrd, Duration alarm, Duration period) with( this ) {
     54        this.initial = alarm;
     55        this.period  = period;
    4956        this.thrd = thrd;
    50         this.alarm = alarm;
    51         this.period = period;
    5257        set = false;
    5358        type = User;
    5459}
    5560
    56 void ?{}( alarm_node_t & this, processor * proc, Time alarm, Duration period ) with( this ) {
     61void ?{}( alarm_node_t & this, processor * proc, Duration alarm, Duration period ) with( this ) {
     62        this.initial = alarm;
     63        this.period  = period;
    5764        this.proc = proc;
    58         this.alarm = alarm;
    59         this.period = period;
    6065        set = false;
    6166        type = Kernel;
    6267}
    63 void ?{}( alarm_node_t & this, Alarm_Callback callback, Time alarm, Duration period ) with( this ) {
    64         this.alarm = alarm;
    65         this.period = period;
     68void ?{}( alarm_node_t & this, Alarm_Callback callback, Duration alarm, Duration period ) with( this ) {
     69        this.initial = alarm;
     70        this.period  = period;
    6671        this.callback = callback;
    6772        set = false;
     
    7782void insert( alarm_list_t * this, alarm_node_t * n ) {
    7883        alarm_node_t * it = & (*this)`first;
    79         while( it && (n->alarm > it->alarm) ) {
     84        while( it && (n->timeval > it->timeval) ) {
    8085                it = & (*it)`next;
    8186        }
     
    105110        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    106111        {
    107                 verify( validate( alarms ) );
    108                 bool first = ! & alarms`first;
     112                Time curr = __kernel_get_time();
     113                this->timeval = curr + this->initial;
    109114
    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 );
    111118                insert( &alarms, this );
    112                 if( first ) {
    113                         __kernel_set_timer( alarms`first.alarm - __kernel_get_time() );
    114                 }
     119                __kernel_set_timer( this->initial );
    115120        }
    116121        unlock( event_kernel->lock );
     
    136141
    137142void 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 };
    139144
    140145        register_self( &node );
  • libcfa/src/concurrency/alarm.hfa

    re2f601f rc457dc41  
    4646
    4747struct alarm_node_t {
    48         Time alarm;                             // time when alarm goes off
    49         Duration period;                        // if > 0 => period of alarm
     48        Duration initial;       // time when alarm goes off
     49        Duration period;        // if > 0 => period of alarm
    5050
    5151        inline dlink(alarm_node_t);
    5252
    5353        union {
    54                 $thread * thrd;                                 // thrd who created event
    55                 processor * proc;                               // proc who created event
    56                 Alarm_Callback callback;                // callback to handle event
     54                $thread * thrd;                 // thrd who created event
     55                processor * proc;                       // proc who created event
     56                Alarm_Callback callback;        // callback to handle event
    5757        };
    5858
    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
    6162};
    6263P9_EMBEDDED( alarm_node_t, dlink(alarm_node_t) )
    6364
    64 void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period );
    65 void ?{}( alarm_node_t & this, processor   * proc, Time alarm, Duration period );
    66 void ?{}( alarm_node_t & this, Alarm_Callback callback, Time alarm, Duration period );
     65void ?{}( alarm_node_t & this, $thread * thrd, Duration alarm, Duration period );
     66void ?{}( alarm_node_t & this, processor * proc, Duration alarm, Duration period );
     67void ?{}( alarm_node_t & this, Alarm_Callback callback, Duration alarm, Duration period );
    6768void ^?{}( alarm_node_t & this );
    6869
  • libcfa/src/concurrency/clib/cfathread.cfa

    re2f601f rc457dc41  
    2727      extern void __cfactx_invoke_thread(void (*main)(void *), void * this);
    2828}
     29
     30extern Time __kernel_get_time();
    2931
    3032//================================================================================
     
    265267        int cfathread_cond_timedwait(cfathread_cond_t *restrict cond, cfathread_mutex_t *restrict mut, const struct timespec *restrict abstime) __attribute__((nonnull (1,2,3))) {
    266268                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 ) ) {
    268273                        return 0;
    269274                }
  • libcfa/src/concurrency/clib/cfathread.h

    re2f601f rc457dc41  
    8080
    8181        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
    8284        } cfathread_condattr_t;
    8385        typedef struct cfathread_condition * cfathread_cond_t;
  • libcfa/src/concurrency/locks.cfa

    re2f601f rc457dc41  
    191191        };
    192192
    193         void ?{}( alarm_node_wrap(L) & this, Time alarm, 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 ) {
    194194                this.alarm_node{ callback, alarm, period };
    195195                this.cond = c;
     
    313313
    314314        // helper for wait()'s' with a timeout
    315         void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) {
     315        void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t ) with(this) {
    316316                lock( lock __cfaabi_dbg_ctx2 );
    317317                size_t recursion_count = queue_and_get_recursion(this, &info);
     
    340340        void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) { WAIT( info, &l ) }
    341341
    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 ) }
    350346}
    351347
  • libcfa/src/concurrency/locks.hfa

    re2f601f rc457dc41  
    290290        bool wait( condition_variable(L) & this, Duration duration );
    291291        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 );
    294292
    295293        void wait( condition_variable(L) & this, L & l );
     
    297295        bool wait( condition_variable(L) & this, L & l, Duration duration );
    298296        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}
  • libcfa/src/concurrency/preemption.cfa

    re2f601f rc457dc41  
    1818
    1919#include "preemption.hfa"
     20
    2021#include <assert.h>
    2122
     
    2627#include <limits.h>                                                                             // PTHREAD_STACK_MIN
    2728
     29#include "bits/debug.hfa"
    2830#include "bits/signal.hfa"
    2931#include "kernel_private.hfa"
     
    105107static inline alarm_node_t * get_expired( alarm_list_t * alarms, Time currtime ) {
    106108        if( ! & (*alarms)`first ) return 0p;                                            // If no alarms return null
    107         if( (*alarms)`first.alarm >= currtime ) return 0p;      // If alarms head not expired return null
     109        if( (*alarms)`first.timeval >= currtime ) return 0p;    // If alarms head not expired return null
    108110        return pop(alarms);                                                                     // Otherwise just pop head
    109111}
     
    141143                if( period > 0 ) {
    142144                        __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)
    144146                        insert( alarms, node );             // Reinsert the node for the next time it triggers
    145147                }
     
    148150        // If there are still alarms pending, reset the timer
    149151        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 );
    153154        }
    154155}
     
    160161        // Alarms need to be enabled
    161162        if ( duration > 0 && ! alarm->set ) {
    162                 alarm->alarm = __kernel_get_time() + duration;
    163                 alarm->period = duration;
     163                alarm->initial = duration;
     164                alarm->period  = duration;
    164165                register_self( alarm );
    165166        }
     
    167168        else if ( duration == 0 && alarm->set ) {
    168169                unregister_self( alarm );
    169                 alarm->alarm = 0;
    170                 alarm->period = 0;
     170                alarm->initial = 0;
     171                alarm->period  = 0;
    171172        }
    172173        // If alarm is different from previous, change it
    173174        else if ( duration > 0 && alarm->period != duration ) {
    174175                unregister_self( alarm );
    175                 alarm->alarm = __kernel_get_time() + duration;
    176                 alarm->period = duration;
     176                alarm->initial = duration;
     177                alarm->period  = duration;
    177178                register_self( alarm );
    178179        }
     
    599600
    600601        // Notify the alarm thread of the shutdown
    601         sigval val = { 1 };
     602        sigval val;
     603        val.sival_int = 0;
    602604        pthread_sigqueue( alarm_thread, SIGALRM, val );
    603605
     
    619621// Used by thread to control when they want to receive preemption signals
    620622void ?{}( preemption_scope & this, processor * proc ) {
    621         (this.alarm){ proc, (Time){ 0 }, 0`s };
     623        (this.alarm){ proc, 0`s, 0`s };
    622624        this.proc = proc;
    623625        this.proc->preemption_alarm = &this.alarm;
     
    705707                int sig = sigwaitinfo( &mask, &info );
    706708
     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
    707712                if( sig < 0 ) {
    708713                        //Error!
     
    711716                                case EAGAIN :
    712717                                case EINTR :
    713                                         {__cfaabi_dbg_print_buffer_decl( " KERNEL: Spurious wakeup %d.\n", err );}
     718                                        {__cfadbg_print_buffer_local( preemption, " KERNEL: Spurious wakeup %d.\n", err );}
    714719                                        continue;
    715720                                case EINVAL :
     
    723728                assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int);
    724729
    725                 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
    726730                // Switch on the code (a.k.a. the sender) to
    727731                switch( info.si_code )
    728732                {
     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
    729745                // Timers can apparently be marked as sent for the kernel
    730746                // In either case, tick preemption
     
    736752                        unlock( event_kernel->lock );
    737753                        break;
    738                 // Signal was not sent by the kernel but by an other thread
    739                 case SI_QUEUE:
    740                         // For now, other thread only signal the alarm thread to shut it down
    741                         // If this needs to change use info.si_value and handle the case here
    742                         goto EXIT;
    743754                }
    744755        }
Note: See TracChangeset for help on using the changeset viewer.