version 1.60, 2001/02/06 19:54:43 |
version 1.60.2.7, 2002/09/17 21:22:09 |
|
|
* @(#)kern_resource.c 8.8 (Berkeley) 2/14/95 |
* @(#)kern_resource.c 8.8 (Berkeley) 2/14/95 |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/kernel.h> |
|
|
#include <sys/proc.h> |
#include <sys/proc.h> |
|
|
#include <sys/mount.h> |
#include <sys/mount.h> |
|
#include <sys/sa.h> |
#include <sys/syscallargs.h> |
#include <sys/syscallargs.h> |
|
|
#include <uvm/uvm_extern.h> |
#include <uvm/uvm_extern.h> |
Line 68 rlim_t maxsmap = MAXSSIZ; |
|
Line 72 rlim_t maxsmap = MAXSSIZ; |
|
*/ |
*/ |
|
|
int |
int |
sys_getpriority(curp, v, retval) |
sys_getpriority(l, v, retval) |
struct proc *curp; |
struct lwp *l; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
Line 77 sys_getpriority(curp, v, retval) |
|
Line 81 sys_getpriority(curp, v, retval) |
|
syscallarg(int) which; |
syscallarg(int) which; |
syscallarg(int) who; |
syscallarg(int) who; |
} */ *uap = v; |
} */ *uap = v; |
struct proc *p; |
struct proc *curp = l->l_proc, *p; |
int low = NZERO + PRIO_MAX + 1; |
int low = NZERO + PRIO_MAX + 1; |
|
|
switch (SCARG(uap, which)) { |
switch (SCARG(uap, which)) { |
Line 99 sys_getpriority(curp, v, retval) |
|
Line 103 sys_getpriority(curp, v, retval) |
|
pg = curp->p_pgrp; |
pg = curp->p_pgrp; |
else if ((pg = pgfind(SCARG(uap, who))) == NULL) |
else if ((pg = pgfind(SCARG(uap, who))) == NULL) |
break; |
break; |
for (p = pg->pg_members.lh_first; p != 0; |
LIST_FOREACH(p, &pg->pg_members, p_pglist) { |
p = p->p_pglist.le_next) { |
|
if (p->p_nice < low) |
if (p->p_nice < low) |
low = p->p_nice; |
low = p->p_nice; |
} |
} |
Line 111 sys_getpriority(curp, v, retval) |
|
Line 114 sys_getpriority(curp, v, retval) |
|
if (SCARG(uap, who) == 0) |
if (SCARG(uap, who) == 0) |
SCARG(uap, who) = curp->p_ucred->cr_uid; |
SCARG(uap, who) = curp->p_ucred->cr_uid; |
proclist_lock_read(); |
proclist_lock_read(); |
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) |
LIST_FOREACH(p, &allproc, p_list) { |
if (p->p_ucred->cr_uid == SCARG(uap, who) && |
if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who) && |
p->p_nice < low) |
p->p_nice < low) |
low = p->p_nice; |
low = p->p_nice; |
|
} |
proclist_unlock_read(); |
proclist_unlock_read(); |
break; |
break; |
|
|
Line 129 sys_getpriority(curp, v, retval) |
|
Line 133 sys_getpriority(curp, v, retval) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
sys_setpriority(curp, v, retval) |
sys_setpriority(l, v, retval) |
struct proc *curp; |
struct lwp *l; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
Line 139 sys_setpriority(curp, v, retval) |
|
Line 143 sys_setpriority(curp, v, retval) |
|
syscallarg(int) who; |
syscallarg(int) who; |
syscallarg(int) prio; |
syscallarg(int) prio; |
} */ *uap = v; |
} */ *uap = v; |
struct proc *p; |
struct proc *curp = l->l_proc, *p; |
int found = 0, error = 0; |
int found = 0, error = 0; |
|
|
switch (SCARG(uap, which)) { |
switch (SCARG(uap, which)) { |
Line 162 sys_setpriority(curp, v, retval) |
|
Line 166 sys_setpriority(curp, v, retval) |
|
pg = curp->p_pgrp; |
pg = curp->p_pgrp; |
else if ((pg = pgfind(SCARG(uap, who))) == NULL) |
else if ((pg = pgfind(SCARG(uap, who))) == NULL) |
break; |
break; |
for (p = pg->pg_members.lh_first; p != 0; |
LIST_FOREACH(p, &pg->pg_members, p_pglist) { |
p = p->p_pglist.le_next) { |
|
error = donice(curp, p, SCARG(uap, prio)); |
error = donice(curp, p, SCARG(uap, prio)); |
found++; |
found++; |
} |
} |
Line 174 sys_setpriority(curp, v, retval) |
|
Line 177 sys_setpriority(curp, v, retval) |
|
if (SCARG(uap, who) == 0) |
if (SCARG(uap, who) == 0) |
SCARG(uap, who) = curp->p_ucred->cr_uid; |
SCARG(uap, who) = curp->p_ucred->cr_uid; |
proclist_lock_read(); |
proclist_lock_read(); |
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) |
LIST_FOREACH(p, &allproc, p_list) { |
if (p->p_ucred->cr_uid == SCARG(uap, who)) { |
if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who)) { |
error = donice(curp, p, SCARG(uap, prio)); |
error = donice(curp, p, SCARG(uap, prio)); |
found++; |
found++; |
} |
} |
|
} |
proclist_unlock_read(); |
proclist_unlock_read(); |
break; |
break; |
|
|
Line 211 donice(curp, chgp, n) |
|
Line 215 donice(curp, chgp, n) |
|
return (EACCES); |
return (EACCES); |
chgp->p_nice = n; |
chgp->p_nice = n; |
SCHED_LOCK(s); |
SCHED_LOCK(s); |
(void)resetpriority(chgp); |
(void)resetprocpriority(chgp); |
SCHED_UNLOCK(s); |
SCHED_UNLOCK(s); |
return (0); |
return (0); |
} |
} |
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
sys_setrlimit(p, v, retval) |
sys_setrlimit(l, v, retval) |
struct proc *p; |
struct lwp *l; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
Line 227 sys_setrlimit(p, v, retval) |
|
Line 231 sys_setrlimit(p, v, retval) |
|
syscallarg(int) which; |
syscallarg(int) which; |
syscallarg(const struct rlimit *) rlp; |
syscallarg(const struct rlimit *) rlp; |
} */ *uap = v; |
} */ *uap = v; |
|
struct proc *p = l->l_proc; |
int which = SCARG(uap, which); |
int which = SCARG(uap, which); |
struct rlimit alim; |
struct rlimit alim; |
int error; |
int error; |
Line 260 dosetrlimit(p, cred, which, limp) |
|
Line 265 dosetrlimit(p, cred, which, limp) |
|
limp->rlim_max == alimp->rlim_max) |
limp->rlim_max == alimp->rlim_max) |
return 0; |
return 0; |
|
|
if (limp->rlim_cur > alimp->rlim_max || |
if (limp->rlim_cur > limp->rlim_max) { |
limp->rlim_max > alimp->rlim_max) |
/* |
if ((error = suser(cred->pc_ucred, &p->p_acflag)) != 0) |
* This is programming error. According to SUSv2, we should |
|
* return error in this case. |
|
*/ |
|
return (EINVAL); |
|
} |
|
if (limp->rlim_max > alimp->rlim_max |
|
&& (error = suser(cred->pc_ucred, &p->p_acflag)) != 0) |
return (error); |
return (error); |
if (limp->rlim_cur > limp->rlim_max) |
|
limp->rlim_cur = limp->rlim_max; |
|
if (p->p_limit->p_refcnt > 1 && |
if (p->p_limit->p_refcnt > 1 && |
(p->p_limit->p_lflags & PL_SHAREMOD) == 0) { |
(p->p_limit->p_lflags & PL_SHAREMOD) == 0) { |
newplim = limcopy(p->p_limit); |
newplim = limcopy(p->p_limit); |
Line 290 dosetrlimit(p, cred, which, limp) |
|
Line 300 dosetrlimit(p, cred, which, limp) |
|
limp->rlim_max = maxsmap; |
limp->rlim_max = maxsmap; |
|
|
/* |
/* |
|
* Return EINVAL if the new stack size limit is lower than |
|
* current usage. Otherwise, the process would get SIGSEGV the |
|
* moment it would try to access anything on it's current stack. |
|
* This conforms to SUSv2. |
|
*/ |
|
if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE |
|
|| limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) |
|
return (EINVAL); |
|
|
|
/* |
* Stack is allocated to the max at exec time with |
* Stack is allocated to the max at exec time with |
* only "rlim_cur" bytes accessible (In other words, |
* only "rlim_cur" bytes accessible (In other words, |
* allocates stack dividing two contiguous regions at |
* allocates stack dividing two contiguous regions at |
Line 340 dosetrlimit(p, cred, which, limp) |
|
Line 360 dosetrlimit(p, cred, which, limp) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
sys_getrlimit(p, v, retval) |
sys_getrlimit(l, v, retval) |
struct proc *p; |
struct lwp *l; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
Line 349 sys_getrlimit(p, v, retval) |
|
Line 369 sys_getrlimit(p, v, retval) |
|
syscallarg(int) which; |
syscallarg(int) which; |
syscallarg(struct rlimit *) rlp; |
syscallarg(struct rlimit *) rlp; |
} */ *uap = v; |
} */ *uap = v; |
|
struct proc *p = l->l_proc; |
int which = SCARG(uap, which); |
int which = SCARG(uap, which); |
|
|
if ((u_int)which >= RLIM_NLIMITS) |
if ((u_int)which >= RLIM_NLIMITS) |
Line 372 calcru(p, up, sp, ip) |
|
Line 393 calcru(p, up, sp, ip) |
|
long sec, usec; |
long sec, usec; |
int s; |
int s; |
struct timeval tv; |
struct timeval tv; |
|
struct lwp *l; |
|
|
s = splstatclock(); |
s = splstatclock(); |
st = p->p_sticks; |
st = p->p_sticks; |
Line 390 calcru(p, up, sp, ip) |
|
Line 412 calcru(p, up, sp, ip) |
|
|
|
sec = p->p_rtime.tv_sec; |
sec = p->p_rtime.tv_sec; |
usec = p->p_rtime.tv_usec; |
usec = p->p_rtime.tv_usec; |
if (p->p_stat == SONPROC) { |
for (l = LIST_FIRST(&p->p_lwps); l != NULL; |
struct schedstate_percpu *spc; |
l = LIST_NEXT(l, l_sibling)) { |
|
if (l->l_stat == LSONPROC) { |
KDASSERT(p->p_cpu != NULL); |
struct schedstate_percpu *spc; |
spc = &p->p_cpu->ci_schedstate; |
|
|
KDASSERT(l->l_cpu != NULL); |
/* |
spc = &l->l_cpu->ci_schedstate; |
* Adjust for the current time slice. This is actually fairly |
|
* important since the error here is on the order of a time |
/* |
* quantum, which is much greater than the sampling error. |
* Adjust for the current time slice. This is |
*/ |
* actually fairly important since the error |
microtime(&tv); |
* here is on the order of a time quantum, |
sec += tv.tv_sec - spc->spc_runtime.tv_sec; |
* which is much greater than the sampling |
usec += tv.tv_usec - spc->spc_runtime.tv_usec; |
* error. |
|
*/ |
|
microtime(&tv); |
|
sec += tv.tv_sec - spc->spc_runtime.tv_sec; |
|
usec += tv.tv_usec - spc->spc_runtime.tv_usec; |
|
|
|
break; |
|
} |
} |
} |
u = (u_quad_t) sec * 1000000 + usec; |
u = (u_quad_t) sec * 1000000 + usec; |
st = (u * st) / tot; |
st = (u * st) / tot; |
Line 421 calcru(p, up, sp, ip) |
|
Line 450 calcru(p, up, sp, ip) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
sys_getrusage(p, v, retval) |
sys_getrusage(l, v, retval) |
struct proc *p; |
struct lwp *l; |
void *v; |
void *v; |
register_t *retval; |
register_t *retval; |
{ |
{ |
Line 431 sys_getrusage(p, v, retval) |
|
Line 460 sys_getrusage(p, v, retval) |
|
syscallarg(struct rusage *) rusage; |
syscallarg(struct rusage *) rusage; |
} */ *uap = v; |
} */ *uap = v; |
struct rusage *rup; |
struct rusage *rup; |
|
struct proc *p = l->l_proc; |
|
|
switch (SCARG(uap, who)) { |
switch (SCARG(uap, who)) { |
|
|
|
|
free(lim->pl_corename, M_TEMP); |
free(lim->pl_corename, M_TEMP); |
pool_put(&plimit_pool, lim); |
pool_put(&plimit_pool, lim); |
} |
} |
|
|
|
struct pstats * |
|
pstatscopy(ps) |
|
struct pstats *ps; |
|
{ |
|
|
|
struct pstats *newps; |
|
|
|
newps = pool_get(&pstats_pool, PR_WAITOK); |
|
|
|
memset(&newps->pstat_startzero, 0, |
|
(unsigned) ((caddr_t)&newps->pstat_endzero - |
|
(caddr_t)&newps->pstat_startzero)); |
|
memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy, |
|
((caddr_t)&newps->pstat_endcopy - |
|
(caddr_t)&newps->pstat_startcopy)); |
|
|
|
return (newps); |
|
|
|
} |
|
|
|
void |
|
pstatsfree(ps) |
|
struct pstats *ps; |
|
{ |
|
|
|
pool_put(&pstats_pool, ps); |
|
} |