Index: kern_event.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_event.c,v retrieving revision 1.95 diff -u -r1.95 kern_event.c --- kern_event.c 12 Oct 2005 17:51:31 -0000 1.95 +++ kern_event.c 13 Apr 2006 20:19:12 -0000 @@ -754,15 +754,12 @@ int kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int waitok) { - struct filedesc *fdp; struct filterops *fops; struct file *fp; struct knote *kn, *tkn; int error, filt, event; int haskqglobal; - int fd; - fdp = NULL; fp = NULL; kn = NULL; error = 0; @@ -778,22 +775,13 @@ findkn: if (fops->f_isfd) { KASSERT(td != NULL, ("td is NULL")); - fdp = td->td_proc->p_fd; - FILEDESC_LOCK(fdp); - /* validate descriptor */ - fd = kev->ident; - if (fd < 0 || fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[fd]) == NULL) { - FILEDESC_UNLOCK(fdp); - error = EBADF; + error = fget(td, kev->ident, &fp); + if (error) goto done; - } - fhold(fp); if ((kev->flags & EV_ADD) == EV_ADD && kqueue_expand(kq, fops, kev->ident, 0) != 0) { - /* unlock and try again */ - FILEDESC_UNLOCK(fdp); + /* try again */ fdrop(fp, td); fp = NULL; error = kqueue_expand(kq, fops, kev->ident, waitok); @@ -811,7 +799,6 @@ * they are the same thing. */ if (fp->f_data == kq) { - FILEDESC_UNLOCK(fdp); error = EINVAL; goto done_noglobal; } @@ -819,7 +806,6 @@ KQ_GLOBAL_LOCK(&kq_global, haskqglobal); } - FILEDESC_UNLOCK(fdp); KQ_LOCK(kq); if (kev->ident < kq->kq_knlistsize) { SLIST_FOREACH(kn, &kq->kq_knlist[kev->ident], kn_link) @@ -849,7 +835,20 @@ fdrop(fp, td); fp = NULL; } + if (!waitok) { + error = ENOMEM; /* XXX */ + goto done; + } + /* + * XXX: haskqglobal should be 0 I think since we + * should be holding a kq lock and thus waitok should + * be 0? + */ +#if 1 + MPASS(haskqglobal == 0); +#else KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); +#endif kq->kq_state |= KQ_FLUXWAIT; msleep(kq, &kq->kq_lock, PSOCK | PDROP, "kqflxwt", 0); goto findkn; @@ -1179,7 +1178,6 @@ if (timeout < 0) { error = EWOULDBLOCK; } else { - KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); kq->kq_state |= KQ_SLEEP; error = msleep(kq, &kq->kq_lock, PSOCK | PCATCH, "kqread", timeout); @@ -1201,7 +1199,6 @@ if ((kn->kn_status == KN_MARKER && kn != marker) || (kn->kn_status & KN_INFLUX) == KN_INFLUX) { - KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); kq->kq_state |= KQ_FLUXWAIT; error = msleep(kq, &kq->kq_lock, PSOCK, "kqflxwt", 0); @@ -1246,6 +1243,7 @@ KN_LIST_LOCK(kn); if (kn->kn_fop->f_event(kn, 0) == 0) { KQ_LOCK(kq); + KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE | KN_INFLUX); kq->kq_count--; @@ -1254,6 +1252,7 @@ } *kevp = kn->kn_kevent; KQ_LOCK(kq); + KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); if (kn->kn_flags & EV_CLEAR) { kn->kn_data = 0; kn->kn_fflags = 0; @@ -1264,7 +1263,6 @@ kn->kn_status &= ~(KN_INFLUX); KN_LIST_UNLOCK(kn); - } /* we are returning a copy to the user */ @@ -1286,7 +1284,6 @@ done: KQ_OWNED(kq); KQ_UNLOCK_FLUX(kq); - KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); knote_free(marker); done_nl: KQ_NOTOWNED(kq);