On Mon, Oct 07, 2002 at 03:48:45AM -0700, Terry Lambert wrote:
> 
> *** OK, it's very hard to believe you didn't break into the
> *** debugger and manually call "pnaic" to get this to happen.

You're right, this is exactly what I did.

> I can't personally repeat the problem, so you're elected to do
> the legwork on this one.  8-(.

Following the advice from the spl* man page I turned the spl* calls to a
mutex and was surprised to see it working. My SMP -current survived a 'make
-j16 buildworld' with make using kqueue() (which it did not a single
time out of >30 times before). Further testings will follow tomorrow.

However, WITNESS complains (only once) about this:
lock order reversal
 1st 0xc662140c kqueue mutex (kqueue mutex) @ 
/freebsd/current/src/sys/kern/kern_event.c:714
 2nd 0xc6727d00 pipe mutex (pipe mutex) @ /freebsd/current/src/sys/kern/sys_pipe.c:1478

Regards,
Stefan Farfeleder
Index: sys/eventvar.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/eventvar.h,v
retrieving revision 1.4
diff -u -r1.4 eventvar.h
--- sys/eventvar.h      18 Jul 2000 19:31:48 -0000      1.4
+++ sys/eventvar.h      8 Oct 2002 16:06:46 -0000
@@ -35,6 +35,7 @@
 struct kqueue {
        TAILQ_HEAD(kqlist, knote) kq_head;      /* list of pending event */
        int             kq_count;               /* number of pending events */
+       struct          mtx kq_mtx;             /* protect kq_head */
        struct          selinfo kq_sel; 
        struct          filedesc *kq_fdp;
        int             kq_state;
Index: kern/kern_event.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_event.c,v
retrieving revision 1.46
diff -u -r1.46 kern_event.c
--- kern/kern_event.c   3 Oct 2002 06:03:26 -0000       1.46
+++ kern/kern_event.c   8 Oct 2002 19:22:27 -0000
@@ -375,7 +375,7 @@
        if (error)
                goto done2;
        kq = malloc(sizeof(struct kqueue), M_KQUEUE, M_WAITOK | M_ZERO);
-       TAILQ_INIT(&kq->kq_head);
+       mtx_init(&kq->kq_mtx, "kqueue mutex", NULL, MTX_DEF);
        FILE_LOCK(fp);
        fp->f_flag = FREAD | FWRITE;
        fp->f_type = DTYPE_KQUEUE;
@@ -709,13 +709,15 @@
                        error = 0;
                goto done;
        }
+       splx(s);
 
+       mtx_lock(&kq->kq_mtx);
        TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe); 
        while (count) {
                kn = TAILQ_FIRST(&kq->kq_head);
                TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 
                if (kn == &marker) {
-                       splx(s);
+                       mtx_unlock(&kq->kq_mtx);
                        if (count == maxevents)
                                goto retry;
                        goto done;
@@ -737,10 +739,10 @@
                if (kn->kn_flags & EV_ONESHOT) {
                        kn->kn_status &= ~KN_QUEUED;
                        kq->kq_count--;
-                       splx(s);
+                       mtx_unlock(&kq->kq_mtx);
                        kn->kn_fop->f_detach(kn);
                        knote_drop(kn, td);
-                       s = splhigh();
+                       mtx_lock(&kq->kq_mtx);
                } else if (kn->kn_flags & EV_CLEAR) {
                        kn->kn_data = 0;
                        kn->kn_fflags = 0;
@@ -751,19 +753,19 @@
                }
                count--;
                if (nkev == KQ_NEVENTS) {
-                       splx(s);
+                       mtx_unlock(&kq->kq_mtx);
                        error = copyout(&kq->kq_kev, ulistp,
                            sizeof(struct kevent) * nkev);
                        ulistp += nkev;
                        nkev = 0;
                        kevp = kq->kq_kev;
-                       s = splhigh();
+                       mtx_lock(&kq->kq_mtx);
                        if (error)
                                break;
                }
        }
        TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe); 
-       splx(s);
+       mtx_unlock(&kq->kq_mtx);
 done:
        if (nkev != 0)
                error = copyout(&kq->kq_kev, ulistp,
@@ -887,6 +889,7 @@
                }
        }
        FILEDESC_UNLOCK(fdp);
+       mtx_destroy(&kq->kq_mtx);
        free(kq, M_KQUEUE);
        fp->f_data = NULL;
 
@@ -1051,14 +1054,14 @@
 knote_enqueue(struct knote *kn)
 {
        struct kqueue *kq = kn->kn_kq;
-       int s = splhigh();
 
        KASSERT((kn->kn_status & KN_QUEUED) == 0, ("knote already queued"));
 
+       mtx_lock(&kq->kq_mtx);
        TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 
        kn->kn_status |= KN_QUEUED;
        kq->kq_count++;
-       splx(s);
+       mtx_unlock(&kq->kq_mtx);
        kqueue_wakeup(kq);
 }
 
@@ -1066,14 +1069,14 @@
 knote_dequeue(struct knote *kn)
 {
        struct kqueue *kq = kn->kn_kq;
-       int s = splhigh();
 
        KASSERT(kn->kn_status & KN_QUEUED, ("knote not queued"));
 
+       mtx_lock(&kq->kq_mtx);
        TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 
        kn->kn_status &= ~KN_QUEUED;
        kq->kq_count--;
-       splx(s);
+       mtx_unlock(&kq->kq_mtx);
 }
 
 static void

Reply via email to