summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorhsu <hsu@FreeBSD.org>2003-01-21 04:05:49 +0000
committerhsu <hsu@FreeBSD.org>2003-01-21 04:05:49 +0000
commit34eb753e798204e15fdd328a23e44ad5b887931e (patch)
treee46a1f607600f691d08be4af4c686c8063e61b38 /sys/kern
parent38a289515c2a7fd6073cfac40606014fa4ee7a2c (diff)
downloadFreeBSD-src-34eb753e798204e15fdd328a23e44ad5b887931e.zip
FreeBSD-src-34eb753e798204e15fdd328a23e44ad5b887931e.tar.gz
Rewrite the SMP filedesc locking in knote_attach() in order to
1. eliminate unnecessary loop which frees and re-allocates the just allocated array 2. eliminate the newsize recomputation 3. eliminate unnecessary unlock and relock around free 4. correctly match the free with the malloc into M_KQUEUE instead of M_TEMP 5. eliminate conditional assignment of oldlist, which is equivalent to a simple assignment 6. eliminate the oldlist temporary variable completely Reviewed by: jhb
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_event.c34
1 files changed, 11 insertions, 23 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 9ff14a6..d360c5c 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -950,9 +950,9 @@ knote_fdclose(struct thread *td, int fd)
static void
knote_attach(struct knote *kn, struct filedesc *fdp)
{
- struct klist *list, *oldlist, *tmp_knhash;
+ struct klist *list, *tmp_knhash;
u_long tmp_knhashmask;
- int size, newsize;
+ int size;
FILEDESC_LOCK(fdp);
@@ -966,9 +966,7 @@ knote_attach(struct knote *kn, struct filedesc *fdp)
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)];
@@ -976,7 +974,6 @@ knote_attach(struct knote *kn, struct filedesc *fdp)
}
if (fdp->fd_knlistsize <= kn->kn_id) {
-retry:
size = fdp->fd_knlistsize;
while (size <= kn->kn_id)
size += KQEXTENT;
@@ -984,31 +981,22 @@ retry:
MALLOC(list, struct klist *,
size * sizeof(struct klist *), M_KQUEUE, M_WAITOK);
FILEDESC_LOCK(fdp);
- newsize = fdp->fd_knlistsize;
- while (newsize <= kn->kn_id)
- newsize += KQEXTENT;
- if (newsize != size) {
- FILEDESC_UNLOCK(fdp);
- free(list, M_TEMP);
- FILEDESC_LOCK(fdp);
- goto retry;
+ if (fdp->fd_knlistsize > kn->kn_id) {
+ FREE(list, M_KQUEUE);
+ goto bigenough;
+ }
+ if (fdp->fd_knlist != NULL) {
+ bcopy(fdp->fd_knlist, list,
+ fdp->fd_knlistsize * sizeof(struct klist *));
+ FREE(fdp->fd_knlist, M_KQUEUE);
}
- bcopy(fdp->fd_knlist, list,
- fdp->fd_knlistsize * sizeof(struct klist *));
bzero((caddr_t)list +
fdp->fd_knlistsize * sizeof(struct klist *),
(size - fdp->fd_knlistsize) * sizeof(struct klist *));
- if (fdp->fd_knlist != NULL)
- oldlist = fdp->fd_knlist;
- else
- oldlist = NULL;
fdp->fd_knlistsize = size;
fdp->fd_knlist = list;
- FILEDESC_UNLOCK(fdp);
- if (oldlist != NULL)
- FREE(oldlist, M_KQUEUE);
- FILEDESC_LOCK(fdp);
}
+bigenough:
list = &fdp->fd_knlist[kn->kn_id];
done:
FILEDESC_UNLOCK(fdp);
OpenPOWER on IntegriCloud