- Remove FORK_SHARELIMIT and PL_SHAREMOD, simplify lim_privatise().
- Use kmem(9) for struct plimit::pl_corename.
This commit is contained in:
parent
14a4134463
commit
a38faca994
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user