Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/time/timeout.c

    r583c2a3 reda43238  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
     3 * Copyright (c) 2022 Jiří Zárevúcky
    34 * All rights reserved.
    45 *
     
    5758}
    5859
    59 /** Reinitialize timeout
    60  *
    61  * Initialize all members except the lock.
    62  *
    63  * @param timeout Timeout to be initialized.
    64  *
    65  */
    66 void timeout_reinitialize(timeout_t *timeout)
    67 {
    68         timeout->cpu = NULL;
    69         timeout->ticks = 0;
    70         timeout->handler = NULL;
    71         timeout->arg = NULL;
    72         link_initialize(&timeout->link);
    73 }
    74 
    7560/** Initialize timeout
    7661 *
     
    8267void timeout_initialize(timeout_t *timeout)
    8368{
    84         irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
    85         timeout_reinitialize(timeout);
     69        link_initialize(&timeout->link);
     70        timeout->cpu = NULL;
    8671}
    8772
     
    10287{
    10388        irq_spinlock_lock(&CPU->timeoutlock, true);
    104         irq_spinlock_lock(&timeout->lock, false);
    10589
    106         if (timeout->cpu)
    107                 panic("Unexpected: timeout->cpu != 0.");
     90        assert(!link_in_use(&timeout->link));
    10891
    10992        timeout->cpu = CPU;
    110         timeout->ticks = us2ticks(time);
    111 
     93        timeout->deadline = CPU->current_clock_tick + us2ticks(time);
    11294        timeout->handler = handler;
    11395        timeout->arg = arg;
    11496
    115         /*
    116          * Insert timeout into the active timeouts list according to timeout->ticks.
    117          */
    118         uint64_t sum = 0;
    119         timeout_t *target = NULL;
    120         link_t *cur, *prev;
    121         prev = NULL;
    122         for (cur = list_first(&CPU->timeout_active_list);
    123             cur != NULL; cur = list_next(cur, &CPU->timeout_active_list)) {
    124                 target = list_get_instance(cur, timeout_t, link);
    125                 irq_spinlock_lock(&target->lock, false);
     97        /* Insert timeout into the active timeouts list according to timeout->deadline. */
    12698
    127                 if (timeout->ticks < sum + target->ticks) {
    128                         irq_spinlock_unlock(&target->lock, false);
    129                         break;
     99        link_t *last = list_last(&CPU->timeout_active_list);
     100        if (last == NULL || timeout->deadline >= list_get_instance(last, timeout_t, link)->deadline) {
     101                list_append(&timeout->link, &CPU->timeout_active_list);
     102        } else {
     103                for (link_t *cur = list_first(&CPU->timeout_active_list); cur != NULL;
     104                    cur = list_next(cur, &CPU->timeout_active_list)) {
     105
     106                        if (timeout->deadline < list_get_instance(cur, timeout_t, link)->deadline) {
     107                                list_insert_before(&timeout->link, cur);
     108                                break;
     109                        }
    130110                }
    131 
    132                 sum += target->ticks;
    133                 irq_spinlock_unlock(&target->lock, false);
    134                 prev = cur;
    135111        }
    136112
    137         if (prev == NULL)
    138                 list_prepend(&timeout->link, &CPU->timeout_active_list);
    139         else
    140                 list_insert_after(&timeout->link, prev);
    141 
    142         /*
    143          * Adjust timeout->ticks according to ticks
    144          * accumulated in target's predecessors.
    145          */
    146         timeout->ticks -= sum;
    147 
    148         /*
    149          * Decrease ticks of timeout's immediate succesor by timeout->ticks.
    150          */
    151         if (cur != NULL) {
    152                 irq_spinlock_lock(&target->lock, false);
    153                 target->ticks -= timeout->ticks;
    154                 irq_spinlock_unlock(&target->lock, false);
    155         }
    156 
    157         irq_spinlock_unlock(&timeout->lock, false);
    158113        irq_spinlock_unlock(&CPU->timeoutlock, true);
    159114}
     
    170125bool timeout_unregister(timeout_t *timeout)
    171126{
    172         DEADLOCK_PROBE_INIT(p_tolock);
     127        assert(timeout->cpu);
    173128
    174 grab_locks:
    175         irq_spinlock_lock(&timeout->lock, true);
    176         if (!timeout->cpu) {
    177                 irq_spinlock_unlock(&timeout->lock, true);
    178                 return false;
     129        irq_spinlock_lock(&timeout->cpu->timeoutlock, true);
     130
     131        bool success = link_in_use(&timeout->link);
     132        if (success) {
     133                list_remove(&timeout->link);
    179134        }
    180135
    181         if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
    182                 irq_spinlock_unlock(&timeout->lock, true);
    183                 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
    184                 goto grab_locks;
    185         }
    186 
    187         /*
    188          * Now we know for sure that timeout hasn't been activated yet
    189          * and is lurking in timeout->cpu->timeout_active_list.
    190          */
    191 
    192         link_t *cur = list_next(&timeout->link,
    193             &timeout->cpu->timeout_active_list);
    194         if (cur != NULL) {
    195                 timeout_t *tmp = list_get_instance(cur, timeout_t, link);
    196                 irq_spinlock_lock(&tmp->lock, false);
    197                 tmp->ticks += timeout->ticks;
    198                 irq_spinlock_unlock(&tmp->lock, false);
    199         }
    200 
    201         list_remove(&timeout->link);
    202         irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
    203 
    204         timeout_reinitialize(timeout);
    205         irq_spinlock_unlock(&timeout->lock, true);
    206 
    207         return true;
     136        irq_spinlock_unlock(&timeout->cpu->timeoutlock, true);
     137        return success;
    208138}
    209139
Note: See TracChangeset for help on using the changeset viewer.