- Remove FORK_SHARELIMIT and PL_SHAREMOD, simplify lim_privatise().

- Use kmem(9) for struct plimit::pl_corename.
This commit is contained in:
rmind 2011-05-01 01:15:18 +00:00
parent 14a4134463
commit a38faca994
6 changed files with 66 additions and 77 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_acct.c,v 1.91 2011/03/26 21:31:23 dholland Exp $ */
/* $NetBSD: kern_acct.c,v 1.92 2011/05/01 01:15:18 rmind Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_acct.c,v 1.91 2011/03/26 21:31:23 dholland Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_acct.c,v 1.92 2011/05/01 01:15:18 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -423,7 +423,7 @@ acct_process(struct lwp *l)
*
* XXX We should think about the CPU limit, too.
*/
lim_privatise(p, false);
lim_privatise(p);
orlim = p->p_rlimit[RLIMIT_FSIZE];
/* Set current and max to avoid illegal values */
p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_fork.c,v 1.182 2011/04/26 16:36:42 joerg Exp $ */
/* $NetBSD: kern_fork.c,v 1.183 2011/05/01 01:15:18 rmind Exp $ */
/*-
* Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.182 2011/04/26 16:36:42 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.183 2011/05/01 01:15:18 rmind Exp $");
#include "opt_ktrace.h"
@ -358,20 +358,15 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
p2->p_cwdi = cwdinit();
/*
* p_limit (rlimit stuff) is usually copy-on-write, so we just need
* to bump pl_refcnt.
* However in some cases like clone the parent and child
* share limits - in which case nothing else must have a copy
* of the limits (PL_SHAREMOD is set).
* Note: p_limit (rlimit stuff) is copy-on-write, so normally
* we just need increase pl_refcnt.
*/
if (__predict_false(flags & FORK_SHARELIMIT))
lim_privatise(p1, 1);
p1_lim = p1->p_limit;
if (p1_lim->pl_flags & PL_WRITEABLE && !(flags & FORK_SHARELIMIT))
p2->p_limit = lim_copy(p1_lim);
else {
if (!p1_lim->pl_writeable) {
lim_addref(p1_lim);
p2->p_limit = p1_lim;
} else {
p2->p_limit = lim_copy(p1_lim);
}
p2->p_lflag = ((flags & FORK_PPWAIT) ? PL_PPWAIT : 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_proc.c,v 1.178 2011/05/01 00:22:36 rmind Exp $ */
/* $NetBSD: kern_proc.c,v 1.179 2011/05/01 01:15:18 rmind Exp $ */
/*-
* Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.178 2011/05/01 00:22:36 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.179 2011/05/01 01:15:18 rmind Exp $");
#ifdef _KERNEL_OPT
#include "opt_kstack.h"
@ -453,8 +453,11 @@ proc0_init(void)
rlim[RLIMIT_MEMLOCK].rlim_max = lim;
rlim[RLIMIT_MEMLOCK].rlim_cur = lim / 3;
/* Note that default core name has zero length. */
limit0.pl_corename = defcorename;
limit0.pl_cnlen = 0;
limit0.pl_refcnt = 1;
limit0.pl_writeable = false;
limit0.pl_sv_limit = NULL;
/* Configure virtual memory system, set vm rlimits. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_resource.c,v 1.160 2011/05/01 00:22:36 rmind Exp $ */
/* $NetBSD: kern_resource.c,v 1.161 2011/05/01 01:15:18 rmind Exp $ */
/*-
* Copyright (c) 1982, 1986, 1991, 1993
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.160 2011/05/01 00:22:36 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.161 2011/05/01 01:15:18 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -355,7 +355,7 @@ dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
if (error)
return (error);
lim_privatise(p, false);
lim_privatise(p);
/* p->p_limit is now unchangeable */
alimp = &p->p_rlimit[which];
@ -598,12 +598,9 @@ rulwps(proc_t *p, struct rusage *ru)
}
/*
* Make a copy of the plimit structure.
* We share these structures copy-on-write after fork,
* and copy when a limit is changed.
* lim_copy: make a copy of the plimit structure.
*
* Unfortunately (due to PL_SHAREMOD) it is possibly for the structure
* we are copying to change beneath our feet!
* We use copy-on-write after fork, and copy when a limit is changed.
*/
struct plimit *
lim_copy(struct plimit *lim)
@ -614,7 +611,7 @@ lim_copy(struct plimit *lim)
newlim = pool_cache_get(plimit_cache, PR_WAITOK);
mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
newlim->pl_flags = 0;
newlim->pl_writeable = false;
newlim->pl_refcnt = 1;
newlim->pl_sv_limit = NULL;
@ -622,30 +619,38 @@ lim_copy(struct plimit *lim)
memcpy(newlim->pl_rlimit, lim->pl_rlimit,
sizeof(struct rlimit) * RLIM_NLIMITS);
/*
* Note: the common case is a use of default core name.
*/
alen = 0;
corename = NULL;
for (;;) {
if (lim->pl_corename == defcorename) {
newlim->pl_corename = defcorename;
newlim->pl_cnlen = 0;
break;
}
len = strlen(lim->pl_corename) + 1;
if (len <= alen) {
len = lim->pl_cnlen;
if (len == alen) {
newlim->pl_corename = corename;
newlim->pl_cnlen = len;
memcpy(corename, lim->pl_corename, len);
corename = NULL;
break;
}
mutex_exit(&lim->pl_lock);
if (corename != NULL)
free(corename, M_TEMP);
if (corename) {
kmem_free(corename, alen);
}
alen = len;
corename = malloc(alen, M_TEMP, M_WAITOK);
corename = kmem_alloc(alen, KM_SLEEP);
mutex_enter(&lim->pl_lock);
}
mutex_exit(&lim->pl_lock);
if (corename != NULL)
free(corename, M_TEMP);
if (corename) {
kmem_free(corename, alen);
}
return newlim;
}
@ -656,44 +661,33 @@ lim_addref(struct plimit *lim)
}
/*
* Give a process it's own private plimit structure.
* This will only be shared (in fork) if modifications are to be shared.
* lim_privatise: give a process its own private plimit structure.
*/
void
lim_privatise(struct proc *p, bool set_shared)
lim_privatise(proc_t *p)
{
struct plimit *lim, *newlim;
struct plimit *lim = p->p_limit, *newlim;
lim = p->p_limit;
if (lim->pl_flags & PL_WRITEABLE) {
if (set_shared)
lim->pl_flags |= PL_SHAREMOD;
if (lim->pl_writeable) {
return;
}
if (set_shared && lim->pl_flags & PL_SHAREMOD)
return;
newlim = lim_copy(lim);
mutex_enter(p->p_lock);
if (p->p_limit->pl_flags & PL_WRITEABLE) {
/* Someone crept in while we were busy */
if (p->p_limit->pl_writeable) {
/* Other thread won the race. */
mutex_exit(p->p_lock);
lim_free(newlim);
if (set_shared)
p->p_limit->pl_flags |= PL_SHAREMOD;
return;
}
/*
* Since most accesses to p->p_limit aren't locked, we must not
* delete the old limit structure yet.
* Since p->p_limit can be accessed without locked held,
* old limit structure must not be deleted yet.
*/
newlim->pl_sv_limit = p->p_limit;
newlim->pl_flags |= PL_WRITEABLE;
if (set_shared)
newlim->pl_flags |= PL_SHAREMOD;
newlim->pl_writeable = true;
p->p_limit = newlim;
mutex_exit(p->p_lock);
}
@ -703,17 +697,20 @@ lim_setcorename(proc_t *p, char *name, size_t len)
{
struct plimit *lim;
char *oname;
size_t olen;
lim_privatise(p, false);
lim_privatise(p);
lim = p->p_limit;
mutex_enter(&lim->pl_lock);
oname = lim->pl_corename;
olen = lim->pl_cnlen;
lim->pl_corename = name;
lim->pl_cnlen = len;
mutex_exit(&lim->pl_lock);
if (oname != defcorename) {
free(oname, M_TEMP);
kmem_free(oname, olen);
}
}
@ -727,7 +724,7 @@ lim_free(struct plimit *lim)
return;
}
if (lim->pl_corename != defcorename) {
free(lim->pl_corename, M_TEMP);
kmem_free(lim->pl_corename, lim->pl_cnlen);
}
sv_lim = lim->pl_sv_limit;
mutex_destroy(&lim->pl_lock);
@ -871,7 +868,7 @@ sysctl_proc_corename(SYSCTLFN_ARGS)
}
/* Allocate, copy and set the new core name for plimit structure. */
cname = malloc(++len, M_TEMP, M_WAITOK | M_CANFAIL);
cname = kmem_alloc(++len, KM_NOSLEEP);
if (cname == NULL) {
error = ENOMEM;
goto done;

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.305 2011/04/27 00:36:48 rmind Exp $ */
/* $NetBSD: proc.h,v 1.306 2011/05/01 01:15:18 rmind Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -432,7 +432,6 @@ struct proclist_desc {
#define FORK_NOWAIT 0x0020 /* Make init the parent of the child */
#define FORK_CLEANFILES 0x0040 /* Start with a clean descriptor set */
#define FORK_SYSTEM 0x0080 /* Fork a kernel thread */
#define FORK_SHARELIMIT 0x0100 /* Share rlimit values */
extern struct proc proc0; /* Process slot for swapper */
extern u_int nprocs; /* Current number of procs */

View File

@ -1,4 +1,4 @@
/* $NetBSD: resourcevar.h,v 1.50 2011/05/01 00:22:36 rmind Exp $ */
/* $NetBSD: resourcevar.h,v 1.51 2011/05/01 01:15:18 rmind Exp $ */
/*
* Copyright (c) 1991, 1993
@ -63,25 +63,20 @@ struct pstats {
#ifdef _KERNEL
/*
* Kernel shareable process resource limits. Because this structure
* is moderately large but changes infrequently, it is normally
* shared copy-on-write after forks. If a group of processes
* ("threads") share modifications, the PL_SHAREMOD flag is set,
* and a copy must be made for the child of a new fork that isn't
* sharing modifications to the limits.
* Process resource limits. Since this structure is moderately large,
* but changes infrequently, it is shared copy-on-write after forks.
*
* The PL_xxx flags are never cleared, once either is set p->p_limit
* will never be changed again.
* When a separate copy is created, then 'pl_writeable' is set to true,
* and 'pl_sv_limit' is pointed to the old proc_t::p_limit structure.
*/
struct plimit {
struct rlimit pl_rlimit[RLIM_NLIMITS];
char * pl_corename;
#define PL_SHAREMOD 0x01 /* modifications are shared */
#define PL_WRITEABLE 0x02 /* private to this process */
int pl_flags;
int pl_refcnt; /* number of references */
kmutex_t pl_lock; /* mutex for pl_refcnt */
struct plimit * pl_sv_limit; /* saved when PL_WRITEABLE set */
size_t pl_cnlen;
u_int pl_refcnt;
bool pl_writeable;
kmutex_t pl_lock;
struct plimit * pl_sv_limit;
};
/* add user profiling from AST XXXSMP */
@ -107,9 +102,9 @@ void addupc_task(struct lwp *, u_long, u_int);
void calcru(struct proc *, struct timeval *, struct timeval *,
struct timeval *, struct timeval *);
struct plimit *lim_copy(struct plimit *lim);
void lim_addref(struct plimit *lim);
void lim_privatise(struct proc *p, bool set_shared);
struct plimit *lim_copy(struct plimit *);
void lim_addref(struct plimit *);
void lim_privatise(struct proc *);
void lim_setcorename(struct proc *, char *, size_t);
void lim_free(struct plimit *);