#include <sys/user.h>
#include <sys/reg.h>
+#include <sys/refcount.h>
#include <sys/thread2.h>
#include <sys/mplock2.h>
struct lwp *lp = td->td_lwp;
struct proc *p = td->td_proc;
register_t *stack_base;
+ struct pargs *pa;
int error, len, i;
struct image_params image_params, *imgp;
struct vattr attr;
}
KKASSERT(p);
+ lwkt_gettoken(&p->p_token);
imgp = &image_params;
/*
/* Set the access time on the vnode */
vn_mark_atime(imgp->vp, td);
- /* Free any previous argument cache */
- if (p->p_args && --p->p_args->ar_ref == 0)
- FREE(p->p_args, M_PARGS);
+ /*
+ * Free any previous argument cache
+ */
+ pa = p->p_args;
p->p_args = NULL;
+ if (pa && refcount_release(&pa->ar_ref)) {
+ kfree(pa, M_PARGS);
+ pa = NULL;
+ }
- /* Cache arguments if they fit inside our allowance */
+ /*
+ * Cache arguments if they fit inside our allowance
+ */
i = imgp->args->begin_envv - imgp->args->begin_argv;
- if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
- MALLOC(p->p_args, struct pargs *, sizeof(struct pargs) + i,
- M_PARGS, M_WAITOK);
- p->p_args->ar_ref = 1;
- p->p_args->ar_length = i;
- bcopy(imgp->args->begin_argv, p->p_args->ar_args, i);
+ if (sizeof(struct pargs) + i <= ps_arg_cache_limit) {
+ pa = kmalloc(sizeof(struct pargs) + i, M_PARGS, M_WAITOK);
+ refcount_init(&pa->ar_ref, 1);
+ pa->ar_length = i;
+ bcopy(imgp->args->begin_argv, pa->ar_args, i);
+ KKASSERT(p->p_args == NULL);
+ p->p_args = pa;
}
exec_fail_dealloc:
if (error == 0) {
++mycpu->gd_cnt.v_exec;
+ lwkt_reltoken(&p->p_token);
return (0);
}
*/
if (imgp->vmspace_destroyed & 2)
p->p_flag &= ~P_INEXEC;
+ lwkt_reltoken(&p->p_token);
if (imgp->vmspace_destroyed) {
/*
* Sorry, no more process anymore. exit gracefully.
int *name = (int*) arg1;
u_int namelen = arg2;
struct proc *p;
+ struct pargs *opa;
struct pargs *pa;
int error = 0;
struct ucred *cr1 = curproc->p_ucred;
if (namelen != 1)
return (EINVAL);
- lwkt_gettoken(&proc_token);
p = pfindn((pid_t)name[0]);
if (p == NULL)
- goto done;
+ goto done2;
+ lwkt_gettoken(&p->p_token);
+ PHOLD(p);
if ((!ps_argsopen) && p_trespass(cr1, p->p_ucred))
goto done;
error = EPERM;
goto done;
}
-
- PHOLD(p);
if (req->oldptr && p->p_args != NULL) {
error = SYSCTL_OUT(req, p->p_args->ar_args,
p->p_args->ar_length);
}
- if (req->newptr == NULL) {
- PRELE(p);
+ if (req->newptr == NULL)
goto done;
- }
-
- if (p->p_args && --p->p_args->ar_ref == 0)
- FREE(p->p_args, M_PARGS);
- p->p_args = NULL;
if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) {
- PRELE(p);
goto done;
}
- MALLOC(pa, struct pargs *, sizeof(struct pargs) + req->newlen,
- M_PARGS, M_WAITOK);
- pa->ar_ref = 1;
+ pa = kmalloc(sizeof(struct pargs) + req->newlen, M_PARGS, M_WAITOK);
+ refcount_init(&pa->ar_ref, 1);
pa->ar_length = req->newlen;
error = SYSCTL_IN(req, pa->ar_args, req->newlen);
- if (!error)
- p->p_args = pa;
- else
- FREE(pa, M_PARGS);
- PRELE(p);
+ if (error) {
+ kfree(pa, M_PARGS);
+ goto done;
+ }
+
+ opa = p->p_args;
+ p->p_args = pa;
+
+ KKASSERT(opa->ar_ref > 0);
+ if (refcount_release(&opa->ar_ref)) {
+ kfree(opa, M_PARGS);
+ }
done:
- lwkt_reltoken(&proc_token);
+ PRELE(p);
+ lwkt_reltoken(&p->p_token);
+done2:
return (error);
}