ktrace_resize_pool() locking slightly reworked:
1) do not take a lock around the single atomic operation. 2) do not lose the invariant of lock by dropping/acquiring ktrace_mtx around free() or malloc(). MFC after: 1 Month.
This commit is contained in:
parent
2960733f48
commit
b4c20e5e37
@ -133,7 +133,7 @@ static struct sx ktrace_sx;
|
|||||||
|
|
||||||
static void ktrace_init(void *dummy);
|
static void ktrace_init(void *dummy);
|
||||||
static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
|
static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
|
||||||
static u_int ktrace_resize_pool(u_int newsize);
|
static u_int ktrace_resize_pool(u_int oldsize, u_int newsize);
|
||||||
static struct ktr_request *ktr_getrequest(int type);
|
static struct ktr_request *ktr_getrequest(int type);
|
||||||
static void ktr_submitrequest(struct thread *td, struct ktr_request *req);
|
static void ktr_submitrequest(struct thread *td, struct ktr_request *req);
|
||||||
static void ktr_freeproc(struct proc *p, struct ucred **uc,
|
static void ktr_freeproc(struct proc *p, struct ucred **uc,
|
||||||
@ -199,9 +199,7 @@ sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS)
|
|||||||
|
|
||||||
/* Handle easy read-only case first to avoid warnings from GCC. */
|
/* Handle easy read-only case first to avoid warnings from GCC. */
|
||||||
if (!req->newptr) {
|
if (!req->newptr) {
|
||||||
mtx_lock(&ktrace_mtx);
|
|
||||||
oldsize = ktr_requestpool;
|
oldsize = ktr_requestpool;
|
||||||
mtx_unlock(&ktrace_mtx);
|
|
||||||
return (SYSCTL_OUT(req, &oldsize, sizeof(u_int)));
|
return (SYSCTL_OUT(req, &oldsize, sizeof(u_int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,10 +208,8 @@ sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS)
|
|||||||
return (error);
|
return (error);
|
||||||
td = curthread;
|
td = curthread;
|
||||||
ktrace_enter(td);
|
ktrace_enter(td);
|
||||||
mtx_lock(&ktrace_mtx);
|
|
||||||
oldsize = ktr_requestpool;
|
oldsize = ktr_requestpool;
|
||||||
newsize = ktrace_resize_pool(wantsize);
|
newsize = ktrace_resize_pool(oldsize, wantsize);
|
||||||
mtx_unlock(&ktrace_mtx);
|
|
||||||
ktrace_exit(td);
|
ktrace_exit(td);
|
||||||
error = SYSCTL_OUT(req, &oldsize, sizeof(u_int));
|
error = SYSCTL_OUT(req, &oldsize, sizeof(u_int));
|
||||||
if (error)
|
if (error)
|
||||||
@ -227,38 +223,40 @@ SYSCTL_PROC(_kern_ktrace, OID_AUTO, request_pool, CTLTYPE_UINT|CTLFLAG_RW,
|
|||||||
"Pool buffer size for ktrace(1)");
|
"Pool buffer size for ktrace(1)");
|
||||||
|
|
||||||
static u_int
|
static u_int
|
||||||
ktrace_resize_pool(u_int newsize)
|
ktrace_resize_pool(u_int oldsize, u_int newsize)
|
||||||
{
|
{
|
||||||
|
STAILQ_HEAD(, ktr_request) ktr_new;
|
||||||
struct ktr_request *req;
|
struct ktr_request *req;
|
||||||
int bound;
|
int bound;
|
||||||
|
|
||||||
mtx_assert(&ktrace_mtx, MA_OWNED);
|
|
||||||
print_message = 1;
|
print_message = 1;
|
||||||
bound = newsize - ktr_requestpool;
|
bound = newsize - oldsize;
|
||||||
if (bound == 0)
|
if (bound == 0)
|
||||||
return (ktr_requestpool);
|
return (ktr_requestpool);
|
||||||
if (bound < 0)
|
if (bound < 0) {
|
||||||
|
mtx_lock(&ktrace_mtx);
|
||||||
/* Shrink pool down to newsize if possible. */
|
/* Shrink pool down to newsize if possible. */
|
||||||
while (bound++ < 0) {
|
while (bound++ < 0) {
|
||||||
req = STAILQ_FIRST(&ktr_free);
|
req = STAILQ_FIRST(&ktr_free);
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
return (ktr_requestpool);
|
break;
|
||||||
STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
|
STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
|
||||||
ktr_requestpool--;
|
ktr_requestpool--;
|
||||||
mtx_unlock(&ktrace_mtx);
|
|
||||||
free(req, M_KTRACE);
|
free(req, M_KTRACE);
|
||||||
mtx_lock(&ktrace_mtx);
|
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
/* Grow pool up to newsize. */
|
/* Grow pool up to newsize. */
|
||||||
|
STAILQ_INIT(&ktr_new);
|
||||||
while (bound-- > 0) {
|
while (bound-- > 0) {
|
||||||
mtx_unlock(&ktrace_mtx);
|
|
||||||
req = malloc(sizeof(struct ktr_request), M_KTRACE,
|
req = malloc(sizeof(struct ktr_request), M_KTRACE,
|
||||||
M_WAITOK);
|
M_WAITOK);
|
||||||
mtx_lock(&ktrace_mtx);
|
STAILQ_INSERT_HEAD(&ktr_new, req, ktr_list);
|
||||||
STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
|
|
||||||
ktr_requestpool++;
|
|
||||||
}
|
}
|
||||||
|
mtx_lock(&ktrace_mtx);
|
||||||
|
STAILQ_CONCAT(&ktr_free, &ktr_new);
|
||||||
|
ktr_requestpool += (newsize - oldsize);
|
||||||
|
}
|
||||||
|
mtx_unlock(&ktrace_mtx);
|
||||||
return (ktr_requestpool);
|
return (ktr_requestpool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user