summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authortruckman <truckman@FreeBSD.org>2002-10-03 06:03:26 +0000
committertruckman <truckman@FreeBSD.org>2002-10-03 06:03:26 +0000
commit8ad27d99229f14a15d5975b533483bb4b6c065a8 (patch)
tree6447bcd1f2efaba7ac0961f75fbf3bc6900c4e2a /sys/kern/kern_event.c
parentcea0ea5b91ba3c35928089c6b4b279f60ab99c94 (diff)
downloadFreeBSD-src-8ad27d99229f14a15d5975b533483bb4b6c065a8.zip
FreeBSD-src-8ad27d99229f14a15d5975b533483bb4b6c065a8.tar.gz
hashinit() calls MALLOC(), so release the filedesc lock in knote_attach()
before calling hashinit() and relock afterwards, taking care to see that we don't lose a race.
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index d8bc894..02402f9 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -953,15 +953,27 @@ knote_fdclose(struct thread *td, int fd)
static void
knote_attach(struct knote *kn, struct filedesc *fdp)
{
- struct klist *list, *oldlist;
+ struct klist *list, *oldlist, *tmp_knhash;
+ u_long tmp_knhashmask;
int size, newsize;
FILEDESC_LOCK(fdp);
if (! kn->kn_fop->f_isfd) {
- if (fdp->fd_knhashmask == 0)
- fdp->fd_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
- &fdp->fd_knhashmask);
+ if (fdp->fd_knhashmask == 0) {
+ FILEDESC_UNLOCK(fdp);
+ tmp_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
+ &tmp_knhashmask);
+ FILEDESC_LOCK(fdp);
+ if (fdp->fd_knhashmask == 0) {
+ fdp->fd_knhash = tmp_knhash;
+ fdp->fd_knhashmask = tmp_knhashmask;
+ } else {
+ FILEDESC_UNLOCK(fdp);
+ free(tmp_knhash, M_KQUEUE);
+ FILEDESC_LOCK(fdp);
+ }
+ }
list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
goto done;
}
OpenPOWER on IntegriCloud