diff options
author | alfred <alfred@FreeBSD.org> | 2002-03-27 21:36:18 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2002-03-27 21:36:18 +0000 |
commit | c513408927799beb8e88e8b08ae677bd46e77762 (patch) | |
tree | d0767f02bd164a185d51f517305b003af562e955 /sys/kern | |
parent | 706e613c585af652438c7e21c1741947752de3b8 (diff) | |
download | FreeBSD-src-c513408927799beb8e88e8b08ae677bd46e77762.zip FreeBSD-src-c513408927799beb8e88e8b08ae677bd46e77762.tar.gz |
Make the reference counting of 'struct pargs' SMP safe.
There is still some locations where the PROC lock should be held
in order to prevent inconsistent views from outside (like the
proc->p_fd fix for kern/vfs_syscalls.c:checkdirs()) that can be
fixed later.
Submitted by: Jonathan Mini <mini@haikugeek.com>
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exec.c | 8 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 12 |
4 files changed, 9 insertions, 17 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 8e88de6..fe0be73 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -441,8 +441,7 @@ interpret: pa = p->p_args; p->p_args = NULL; PROC_UNLOCK(p); - if (pa != NULL && --pa->ar_ref == 0) - FREE(pa, M_PARGS); + pargs_drop(pa); /* Set values passed into the program in registers. */ setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base, @@ -451,10 +450,7 @@ interpret: /* Cache arguments if they fit inside our allowance */ i = imgp->endargs - imgp->stringbase; if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { - MALLOC(pa, struct pargs *, sizeof(struct pargs) + i, - M_PARGS, M_WAITOK); - pa->ar_ref = 1; - pa->ar_length = i; + pa = pargs_alloc(i); bcopy(imgp->stringbase, pa->ar_args, i); PROC_LOCK(p); p->p_args = pa; diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 6e38fd0..172fd10 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -637,8 +637,7 @@ loop: /* * Remove unused arguments */ - if (p->p_args && --p->p_args->ar_ref == 0) - FREE(p->p_args, M_PARGS); + pargs_drop(p->p_args); if (--p->p_procsig->ps_refcnt == 0) { if (p->p_sigacts != &p->p_uarea->u_sigacts) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index db4a459..ddd962a 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -482,8 +482,7 @@ again: p2->p_ucred = crhold(p1->p_ucred); td2->td_ucred = crhold(p2->p_ucred); /* XXXKSE */ - if (p2->p_args) - p2->p_args->ar_ref++; + pargs_hold(p2->p_args); if (flags & RFSIGSHARE) { p2->p_procsig = p1->p_procsig; diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 0e236cb..b81141b 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -80,6 +80,7 @@ struct proclist zombproc; struct sx allproc_lock; struct sx proctree_lock; struct sx pgrpsess_lock; +struct mtx pargs_ref_lock; uma_zone_t proc_zone; uma_zone_t ithread_zone; @@ -94,6 +95,7 @@ procinit() sx_init(&allproc_lock, "allproc"); sx_init(&proctree_lock, "proctree"); sx_init(&pgrpsess_lock, "pgrpsess"); + mtx_init(&pargs_ref_lock, "struct pargs.ref", MTX_DEF); LIST_INIT(&allproc); LIST_INIT(&zombproc); pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); @@ -982,23 +984,19 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) pa = p->p_args; p->p_args = NULL; PROC_UNLOCK(p); - if (pa != NULL && --pa->ar_ref == 0) - FREE(pa, M_PARGS); + pargs_drop(pa); if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) return (error); - MALLOC(pa, struct pargs *, sizeof(struct pargs) + req->newlen, - M_PARGS, M_WAITOK); - pa->ar_ref = 1; - pa->ar_length = req->newlen; + pa = pargs_alloc(req->newlen); error = SYSCTL_IN(req, pa->ar_args, req->newlen); if (!error) { PROC_LOCK(p); p->p_args = pa; PROC_UNLOCK(p); } else - FREE(pa, M_PARGS); + pargs_free(pa); return (error); } |