Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Protect the event queue with a simple mutex; this only p...



details:   https://anonhg.NetBSD.org/src/rev/f563f0f5a114
branches:  trunk
changeset: 543358:f563f0f5a114
user:      pk <pk%NetBSD.org@localhost>
date:      Sun Feb 23 22:05:35 2003 +0000

description:
Protect the event queue with a simple mutex; this only partially addresses
MP-safety issues in the event handling system.

diffstat:

 sys/kern/kern_event.c |  38 +++++++++++++++++++++++++++++---------
 sys/sys/eventvar.h    |   3 ++-
 2 files changed, 31 insertions(+), 10 deletions(-)

diffs (171 lines):

diff -r 61da40a63f80 -r f563f0f5a114 sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Sun Feb 23 22:03:11 2003 +0000
+++ b/sys/kern/kern_event.c     Sun Feb 23 22:05:35 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_event.c,v 1.11 2003/02/23 21:44:26 pk Exp $       */
+/*     $NetBSD: kern_event.c,v 1.12 2003/02/23 22:05:35 pk Exp $       */
 /*-
  * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon%FreeBSD.org@localhost>
  * All rights reserved.
@@ -626,6 +626,7 @@
        fp->f_ops = &kqueueops;
        kq = pool_get(&kqueue_pool, PR_WAITOK);
        memset((char *)kq, 0, sizeof(struct kqueue));
+       simple_lock_init(&kq->kq_lock);
        TAILQ_INIT(&kq->kq_head);
        fp->f_data = (caddr_t)kq;       /* store the kqueue with the fp */
        *retval = fd;
@@ -923,12 +924,14 @@
  start:
        kevp = kq->kq_kev;
        s = splsched();
+       simple_lock(&kq->kq_lock);
        if (kq->kq_count == 0) {
                if (timeout < 0) { 
                        error = EWOULDBLOCK;
                } else {
                        kq->kq_state |= KQ_SLEEP;
-                       error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout);
+                       error = ltsleep(kq, PSOCK | PCATCH | PNORELOCK,
+                                       "kqread", timeout, &kq->kq_lock);
                }
                splx(s);
                if (error == 0)
@@ -943,20 +946,26 @@
 
        /* mark end of knote list */
        TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe); 
+       simple_unlock(&kq->kq_lock);
 
        while (count) {                         /* while user wants data ... */
+               simple_lock(&kq->kq_lock);
                kn = TAILQ_FIRST(&kq->kq_head); /* get next knote */
                TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 
                if (kn == &marker) {            /* if it's our marker, stop */
+                       /* What if it's some else's marker? */
+                       simple_unlock(&kq->kq_lock);
                        splx(s);
                        if (count == maxevents)
                                goto retry;
                        goto done;
                }
+               kq->kq_count--;
+               simple_unlock(&kq->kq_lock);
+
                if (kn->kn_status & KN_DISABLED) {
                        /* don't want disabled events */
                        kn->kn_status &= ~KN_QUEUED;
-                       kq->kq_count--;
                        continue;
                }
                if ((kn->kn_flags & EV_ONESHOT) == 0 &&
@@ -966,7 +975,6 @@
                         * triggered again, so de-queue.
                         */
                        kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
-                       kq->kq_count--;
                        continue;
                }
                *kevp = kn->kn_kevent;
@@ -975,7 +983,6 @@
                if (kn->kn_flags & EV_ONESHOT) {
                        /* delete ONESHOT events after retrieval */
                        kn->kn_status &= ~KN_QUEUED;
-                       kq->kq_count--;
                        splx(s);
                        kn->kn_fop->f_detach(kn);
                        knote_drop(kn, p, p->p_fd);
@@ -985,10 +992,12 @@
                        kn->kn_data = 0;
                        kn->kn_fflags = 0;
                        kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
-                       kq->kq_count--;
                } else {
                        /* add event back on list */
+                       simple_lock(&kq->kq_lock);
                        TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 
+                       kq->kq_count++;
+                       simple_unlock(&kq->kq_lock);
                }
                count--;
                if (nkev == KQ_NEVENTS) {
@@ -1006,7 +1015,9 @@
        }
 
        /* remove marker */
+       simple_lock(&kq->kq_lock);
        TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe); 
+       simple_unlock(&kq->kq_lock);
        splx(s);
  done:
        if (nkev != 0) {
@@ -1209,7 +1220,10 @@
 static void
 kqueue_wakeup(struct kqueue *kq)
 {
+       int s;
 
+       s = splsched();
+       simple_lock(&kq->kq_lock);
        if (kq->kq_state & KQ_SLEEP) {          /* if currently sleeping ...  */
                kq->kq_state &= ~KQ_SLEEP;
                wakeup(kq);                     /* ... wakeup */
@@ -1217,6 +1231,8 @@
 
        /* Notify select/poll and kevent. */
        selnotify(&kq->kq_sel, 0);
+       simple_unlock(&kq->kq_lock);
+       splx(s);
 }
 
 /*
@@ -1371,12 +1387,14 @@
        int             s;
 
        kq = kn->kn_kq;
-       s = splsched();
        KASSERT((kn->kn_status & KN_QUEUED) == 0);
 
+       s = splsched();
+       simple_lock(&kq->kq_lock);
        TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 
        kn->kn_status |= KN_QUEUED;
        kq->kq_count++;
+       simple_unlock(&kq->kq_lock);
        splx(s);
        kqueue_wakeup(kq);
 }
@@ -1390,12 +1408,14 @@
        struct kqueue   *kq;
        int             s;
 
+       KASSERT(kn->kn_status & KN_QUEUED);
        kq = kn->kn_kq;
+
        s = splsched();
-       KASSERT(kn->kn_status & KN_QUEUED);
-
+       simple_lock(&kq->kq_lock);
        TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 
        kn->kn_status &= ~KN_QUEUED;
        kq->kq_count--;
+       simple_unlock(&kq->kq_lock);
        splx(s);
 }
diff -r 61da40a63f80 -r f563f0f5a114 sys/sys/eventvar.h
--- a/sys/sys/eventvar.h        Sun Feb 23 22:03:11 2003 +0000
+++ b/sys/sys/eventvar.h        Sun Feb 23 22:05:35 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: eventvar.h,v 1.3 2002/10/23 09:14:56 jdolecek Exp $    */
+/*     $NetBSD: eventvar.h,v 1.4 2003/02/23 22:05:35 pk Exp $  */
 /*-
  * Copyright (c) 1999,2000 Jonathan Lemon <jlemon%FreeBSD.org@localhost>
  * All rights reserved.
@@ -38,6 +38,7 @@
 struct kqueue {
        TAILQ_HEAD(kqlist, knote) kq_head;      /* list of pending event */
        int             kq_count;               /* number of pending events */
+       struct simplelock kq_lock;              /* mutex for queue access */
        struct selinfo  kq_sel; 
        struct filedesc *kq_fdp;
        int             kq_state;



Home | Main Index | Thread Index | Old Index