Changeset 83789ea2 in mainline


Ignore:
Timestamp:
2023-02-09T16:12:24Z (13 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c0b54c9
Parents:
ba25c4b
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2022-08-16 17:52:15)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2023-02-09 16:12:24)
Message:

Simplify timeout handling

Since timeout_unregister() now waits for the handler to complete,
we can get rid of some of the bookkeeping in waitq and thread code.
We can also turn timeout_t into a local variable instead of
keeping it around in thread_t.

Location:
kernel/generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/proc/thread.h

    rba25c4b r83789ea2  
    121121        /** Wait queue in which this thread sleeps. */
    122122        waitq_t *sleep_queue;
    123         /** Timeout used for timeoutable sleeping.  */
    124         timeout_t sleep_timeout;
    125         /** Flag signalling sleep timeout in progress. */
    126         volatile bool timeout_pending;
    127123
    128124        /**
  • kernel/generic/src/proc/thread.c

    rba25c4b r83789ea2  
    360360        thread->state = Entering;
    361361
    362         timeout_initialize(&thread->sleep_timeout);
    363362        thread->sleep_interruptible = false;
    364363        thread->sleep_composable = false;
    365364        thread->sleep_queue = NULL;
    366         thread->timeout_pending = false;
    367365
    368366        thread->in_copy_from_uspace = false;
     
    500498        }
    501499
    502 restart:
    503500        irq_spinlock_lock(&THREAD->lock, true);
    504         if (THREAD->timeout_pending) {
    505                 /* Busy waiting for timeouts in progress */
    506                 irq_spinlock_unlock(&THREAD->lock, true);
    507                 goto restart;
    508         }
    509 
    510501        THREAD->state = Exiting;
    511502        irq_spinlock_unlock(&THREAD->lock, true);
  • kernel/generic/src/synch/waitq.c

    rba25c4b r83789ea2  
    121121        }
    122122
    123         thread->timeout_pending = false;
    124123        irq_spinlock_unlock(&thread->lock, false);
    125124
     
    172171                        goto grab_locks;
    173172                }
    174 
    175                 if ((thread->timeout_pending) &&
    176                     (timeout_unregister(&thread->sleep_timeout)))
    177                         thread->timeout_pending = false;
    178173
    179174                list_remove(&thread->wq_link);
     
    270265ipl_t waitq_sleep_prepare(waitq_t *wq)
    271266{
    272         ipl_t ipl;
    273 
    274 restart:
    275         ipl = interrupts_disable();
    276 
    277         if (THREAD) {  /* Needed during system initiailzation */
    278                 /*
    279                  * Busy waiting for a delayed timeout.
    280                  * This is an important fix for the race condition between
    281                  * a delayed timeout and a next call to waitq_sleep_timeout().
    282                  * Simply, the thread is not allowed to go to sleep if
    283                  * there are timeouts in progress.
    284                  *
    285                  */
    286                 irq_spinlock_lock(&THREAD->lock, false);
    287 
    288                 if (THREAD->timeout_pending) {
    289                         irq_spinlock_unlock(&THREAD->lock, false);
    290                         interrupts_restore(ipl);
    291                         goto restart;
    292                 }
    293 
    294                 irq_spinlock_unlock(&THREAD->lock, false);
    295         }
    296 
     267        ipl_t ipl = interrupts_disable();
    297268        irq_spinlock_lock(&wq->lock, false);
    298269        return ipl;
     
    374345        irq_spinlock_lock(&THREAD->lock, false);
    375346
     347        timeout_t timeout;
     348        timeout_initialize(&timeout);
     349
    376350        THREAD->sleep_composable = (flags & SYNCH_FLAGS_FUTEX);
    377351
     
    395369                        THREAD->last_cycle = get_cycle();
    396370                        irq_spinlock_unlock(&THREAD->lock, false);
     371                        if (usec) {
     372                                timeout_unregister(&timeout);
     373                        }
    397374                        return EINTR;
    398375                }
     
    409386                }
    410387
    411                 THREAD->timeout_pending = true;
    412                 timeout_register(&THREAD->sleep_timeout, (uint64_t) usec,
    413                     waitq_sleep_timed_out, THREAD);
     388                timeout_register(&timeout, (uint64_t) usec, waitq_sleep_timed_out, THREAD);
    414389        }
    415390
     
    433408        /* wq->lock is released in scheduler_separated_stack() */
    434409        scheduler();
     410
     411        if (usec) {
     412                timeout_unregister(&timeout);
     413        }
    435414
    436415        return EOK;
     
    560539        list_remove(&thread->wq_link);
    561540
    562         if ((thread->timeout_pending) &&
    563             (timeout_unregister(&thread->sleep_timeout)))
    564                 thread->timeout_pending = false;
    565 
    566541        thread->sleep_queue = NULL;
    567542        irq_spinlock_unlock(&thread->lock, false);
  • kernel/generic/src/time/timeout.c

    rba25c4b r83789ea2  
    128128bool timeout_unregister(timeout_t *timeout)
    129129{
     130        if (atomic_load_explicit(&timeout->finished, memory_order_acquire))
     131                /* The timeout fired and finished already, no need to check the list. */
     132                return false;
     133
    130134        assert(timeout->cpu);
    131135
Note: See TracChangeset for help on using the changeset viewer.