Changeset ad58fd2 in mainline


Ignore:
Timestamp:
2022-08-15T16:31:58Z (2 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
46b305a
Parents:
742f95ec
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2022-08-15 16:26:16)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2022-08-15 16:31:58)
Message:

Make timeout→cpu immutable

We ensure timeout→cpu is only changed in timeout_register(),
which by its nature is externally synchronized with timeout_unregister(),
and internally synchronized with clock(). Thus in both those contexts,
timeout→cpu is always a valid constant pointing to the CPU of last
call to timeout_register().

Doing so removes the need for synchronization using timeout→lock.
Instead, timeout→link is synchronized by timeout→cpu→timeoutlock,
and all other fields of timeout_t are also immutable outside
timeout_register(), which means they are safely synchronized by
a combination of timeout→cpu→timoutlock and external sychronization
of timeout_register/unregister.

Location:
kernel/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/time/timeout.h

    r742f95ec rad58fd2  
    4545        IRQ_SPINLOCK_DECLARE(lock);
    4646
    47         /** Link to the list of active timeouts on CURRENT->cpu */
     47        /** Link to the list of active timeouts on timeout->cpu */
    4848        link_t link;
    4949        /** Timeout will be activated when current clock tick reaches this value. */
     
    6161extern void timeout_init(void);
    6262extern void timeout_initialize(timeout_t *);
    63 extern void timeout_reinitialize(timeout_t *);
    6463extern void timeout_register(timeout_t *, uint64_t, timeout_handler_t, void *);
    6564extern bool timeout_unregister(timeout_t *);
  • kernel/generic/src/time/clock.c

    r742f95ec rad58fd2  
    172172                        timeout_handler_t handler = timeout->handler;
    173173                        void *arg = timeout->arg;
    174                         timeout_reinitialize(timeout);
    175174
    176175                        irq_spinlock_unlock(&timeout->lock, false);
  • kernel/generic/src/time/timeout.c

    r742f95ec rad58fd2  
    5757}
    5858
    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->deadline = 0;
    70         timeout->handler = NULL;
    71         timeout->arg = NULL;
    72         link_initialize(&timeout->link);
    73 }
    74 
    7559/** Initialize timeout
    7660 *
     
    8367{
    8468        irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
    85         timeout_reinitialize(timeout);
     69        link_initialize(&timeout->link);
     70        timeout->cpu = NULL;
    8671}
    8772
     
    10388        irq_spinlock_lock(&CPU->timeoutlock, true);
    10489        irq_spinlock_lock(&timeout->lock, false);
    105 
    106         if (timeout->cpu)
    107                 panic("Unexpected: timeout->cpu != 0.");
    10890
    10991        timeout->cpu = CPU;
     
    152134bool timeout_unregister(timeout_t *timeout)
    153135{
    154         DEADLOCK_PROBE_INIT(p_tolock);
     136        assert(timeout->cpu);
    155137
    156 grab_locks:
    157         irq_spinlock_lock(&timeout->lock, true);
    158         if (!timeout->cpu) {
    159                 irq_spinlock_unlock(&timeout->lock, true);
    160                 return false;
     138        irq_spinlock_lock(&timeout->cpu->timeoutlock, true);
     139
     140        bool success = link_in_use(&timeout->link);
     141        if (success) {
     142                list_remove(&timeout->link);
    161143        }
    162144
    163         if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
    164                 irq_spinlock_unlock(&timeout->lock, true);
    165                 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
    166                 goto grab_locks;
    167         }
    168 
    169         /*
    170          * Now we know for sure that timeout hasn't been activated yet
    171          * and is lurking in timeout->cpu->timeout_active_list.
    172          */
    173 
    174         link_t *cur = list_next(&timeout->link,
    175             &timeout->cpu->timeout_active_list);
    176         if (cur != NULL) {
    177                 timeout_t *tmp = list_get_instance(cur, timeout_t, link);
    178                 irq_spinlock_lock(&tmp->lock, false);
    179                 irq_spinlock_unlock(&tmp->lock, false);
    180         }
    181 
    182         list_remove(&timeout->link);
    183         irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
    184 
    185         timeout_reinitialize(timeout);
    186         irq_spinlock_unlock(&timeout->lock, true);
    187 
    188         return true;
     145        irq_spinlock_unlock(&timeout->cpu->timeoutlock, true);
     146        return success;
    189147}
    190148
Note: See TracChangeset for help on using the changeset viewer.