Hi,

from a customer's system I got this panic:

kernel diagnostic assertion "(kn->kn_status & KN_QUEUED) == 0" failed: file ".. 
/../../../kern/kern_event.c", line 1071                                         

panic() at panic+0xfe                                                           
__assert() at __assert+0x25                                                     
knote_enqueue() at knote_enqueue+0x8c                                           
knote() at knote+0x47                                                           
selwakeup() at selwakeup+0x1b                                                   
logwakeup() at logwakeup+0x20                                                   
log() at log+0xfc                                                               
...
softclock() at softclock+0x315                                                  
softintr_dispatch() at softintr_dispatch+0x7f                                   

When looking at the condition in KNOTE_ACTIVATE()
        if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0)
                knote_enqueue(kn);
and the assertion in knote_enqueue()
        KASSERT((kn->kn_status & KN_QUEUED) == 0);
it is quite obvious that interrupts must be blocked between those.

So put the splhigh() around KNOTE_ACTIVATE() and use a splassert()
within knote_enqueue().  This is more or less where FreeBSD puts
its KQ_LOCK().

ok?

bluhm

Index: kern/kern_event.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.71
diff -u -p -r1.71 kern_event.c
--- kern/kern_event.c   6 Jan 2016 17:58:46 -0000       1.71
+++ kern/kern_event.c   29 Mar 2016 19:15:40 -0000
@@ -338,9 +338,12 @@ void
 filt_timerexpire(void *knx)
 {
        struct knote *kn = knx;
+       int s;
 
        kn->kn_data++;
+       s = splhigh();
        KNOTE_ACTIVATE(kn);
+       splx(s);
 
        if ((kn->kn_flags & EV_ONESHOT) == 0)
                filt_timer_timeout_add(kn);
@@ -954,7 +957,11 @@ kqueue_wakeup(struct kqueue *kq)
 void
 knote_activate(struct knote *kn)
 {
+       int s;
+
+       s = splhigh();
        KNOTE_ACTIVATE(kn);
+       splx(s);
 }
 
 /*
@@ -964,10 +971,14 @@ void
 knote(struct klist *list, long hint)
 {
        struct knote *kn, *kn0;
+       int s;
 
-       SLIST_FOREACH_SAFE(kn, list, kn_selnext, kn0)
+       SLIST_FOREACH_SAFE(kn, list, kn_selnext, kn0) {
+               s = splhigh();
                if (kn->kn_fop->f_event(kn, hint))
                        KNOTE_ACTIVATE(kn);
+               splx(s);
+       }
 }
 
 /*
@@ -1073,14 +1084,13 @@ void
 knote_enqueue(struct knote *kn)
 {
        struct kqueue *kq = kn->kn_kq;
-       int s = splhigh();
 
+       splassert(IPL_HIGH);
        KASSERT((kn->kn_status & KN_QUEUED) == 0);
 
        TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
        kn->kn_status |= KN_QUEUED;
        kq->kq_count++;
-       splx(s);
        kqueue_wakeup(kq);
 }
 

Reply via email to