diff options
author | hsu <hsu@FreeBSD.org> | 2003-01-21 04:05:49 +0000 |
---|---|---|
committer | hsu <hsu@FreeBSD.org> | 2003-01-21 04:05:49 +0000 |
commit | 34eb753e798204e15fdd328a23e44ad5b887931e (patch) | |
tree | e46a1f607600f691d08be4af4c686c8063e61b38 /sys/kern | |
parent | 38a289515c2a7fd6073cfac40606014fa4ee7a2c (diff) | |
download | FreeBSD-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.c | 34 |
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); |