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
This commit is contained in:
parent
4273cc51a5
commit
34c54d9f74
@ -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 @@ knote_attach(struct knote *kn, struct filedesc *fdp)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user