On Thu, Nov 18, 2021 at 07:50:01PM -0600, Scott Cheloha wrote:
> On Thu, Nov 18, 2021 at 12:30:30PM +0100, Martin Pieuchot wrote:
> > On 17/11/21(Wed) 09:51, Scott Cheloha wrote:
> > > > On Nov 17, 2021, at 03:22, Martin Pieuchot <m...@openbsd.org> wrote:
> > > > 
> > > > ???On 16/11/21(Tue) 13:55, Visa Hankala wrote:
> > > >> Currently, dopselect() and doppoll() call tsleep_nsec() without retry.
> > > >> cheloha@ asked if the functions should handle spurious wakeups. I guess
> > > >> such wakeups are unlikely with the nowake wait channel, but I am not
> > > >> sure if that is a safe guess.
> > > > 
> > > > I'm not sure to understand, are we afraid a thread sleeping on `nowake'
> > > > can be awaken?  Is it the assumption here?
> > > 
> > > Yes, but I don't know how.
> > 
> > Then I'd suggest we start with understanding how this can happen otherwise
> > I fear we are adding more complexity for reasons we don't understands.
> > 
> > > kettenis@ said spurious wakeups were
> > > possible on a similar loop in sigsuspend(2)
> > > so I mentioned this to visa@ off-list.
> > 
> > I don't understand how this can happen.
> > 
> > > If we added an assert to panic in wakeup(9)
> > > if the channel is &nowake, would that be
> > > sufficient?
> > 
> > I guess so.
> 
> So, something like the attached patch?  All variants of wakeup(9) end
> up in wakeup_proc(), right?
> 
> Wondering if it'd be better (and cheaper) to do the assert at the top
> of wakeup_n(9)...
> 
> kettenis: Can you explain how a spurious wakeup would actually happen
> here or in sigsuspend(2)?
> 
> Index: kern_synch.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_synch.c,v
> retrieving revision 1.180
> diff -u -p -r1.180 kern_synch.c
> --- kern_synch.c      7 Oct 2021 08:51:00 -0000       1.180
> +++ kern_synch.c      19 Nov 2021 01:41:21 -0000
> @@ -493,6 +493,8 @@ wakeup_proc(struct proc *p, const volati
>  {
>       int s, awakened = 0;
>  
> +     KASSERT(chan != &nowake);
> +
>       SCHED_LOCK(s);
>       if (p->p_wchan != NULL &&
>          ((chan == NULL) || (p->p_wchan == chan))) {
> 

To cover all wakeup point, KASSERT() should be done at:
- unsleep()
- wakeup_n()

note: wakeup_proc() will ends in calling unsleep() (setrunnable() will
call unsleep() too)

Thanks.
-- 
Sebastien Marie

diff a5dfec8fdaf0b4c0fdc18ec79317f74db550548a /home/semarie/repos/openbsd/src
blob - f0190261fe60789beb42bd76509517c604a487a3
file + sys/kern/kern_synch.c
--- sys/kern/kern_synch.c
+++ sys/kern/kern_synch.c
@@ -534,6 +534,8 @@ unsleep(struct proc *p)
 {
        SCHED_ASSERT_LOCKED();
 
+       KASSERT(p->p_wchan != &nowake);
+       
        if (p->p_wchan != NULL) {
                TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_runq);
                p->p_wchan = NULL;
@@ -553,6 +555,8 @@ wakeup_n(const volatile void *ident, int n)
        struct proc *pnext;
        int s;
 
+       KASSERT(ident != &nowake);
+       
        SCHED_LOCK(s);
        qp = &slpque[LOOKUP(ident)];
        for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) {

Reply via email to