xref: /csrg-svn/sys/kern/kern_resource.c (revision 44405)
123373Smckusick /*
229093Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323373Smckusick  * All rights reserved.  The Berkeley software License Agreement
423373Smckusick  * specifies the terms and conditions for redistribution.
523373Smckusick  *
6*44405Skarels  *	@(#)kern_resource.c	7.9 (Berkeley) 06/28/90
723373Smckusick  */
87Sbill 
917092Sbloom #include "param.h"
10*44405Skarels #include "user.h"
1117092Sbloom #include "proc.h"
127Sbill 
138176Sroot /*
148176Sroot  * Resource controls and accounting.
158176Sroot  */
168176Sroot 
1743365Smckusick getpriority(curp, uap, retval)
1843365Smckusick 	struct proc *curp;
1943365Smckusick 	register struct args {
208031Sroot 		int	which;
218031Sroot 		int	who;
2243365Smckusick 	} *uap;
2343365Smckusick 	int *retval;
2443365Smckusick {
258031Sroot 	register struct proc *p;
2635810Smarc 	register int low = PRIO_MAX + 1;
278031Sroot 
288031Sroot 	switch (uap->which) {
298031Sroot 
308031Sroot 	case PRIO_PROCESS:
318031Sroot 		if (uap->who == 0)
3243365Smckusick 			p = curp;
338031Sroot 		else
348031Sroot 			p = pfind(uap->who);
358031Sroot 		if (p == 0)
3628149Skarels 			break;
3717400Skarels 		low = p->p_nice;
388031Sroot 		break;
398031Sroot 
4035810Smarc 	case PRIO_PGRP: {
4135810Smarc 		register struct pgrp *pg;
4235810Smarc 
438031Sroot 		if (uap->who == 0)
4443365Smckusick 			pg = curp->p_pgrp;
4535810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
4635810Smarc 			break;
4735810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
4835810Smarc 			if (p->p_nice < low)
4917400Skarels 				low = p->p_nice;
508176Sroot 		}
518031Sroot 		break;
5235810Smarc 	}
538031Sroot 
548176Sroot 	case PRIO_USER:
558176Sroot 		if (uap->who == 0)
5643365Smckusick 			uap->who = p->p_uid;
5716530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt) {
588176Sroot 			if (p->p_uid == uap->who &&
5917400Skarels 			    p->p_nice < low)
6017400Skarels 				low = p->p_nice;
618176Sroot 		}
628176Sroot 		break;
638176Sroot 
648031Sroot 	default:
65*44405Skarels 		return (EINVAL);
668031Sroot 	}
6743365Smckusick 	if (low == PRIO_MAX + 1)
68*44405Skarels 		return (ESRCH);
6943365Smckusick 	*retval = low;
70*44405Skarels 	return (0);
718031Sroot }
728031Sroot 
7343365Smckusick /* ARGSUSED */
7443365Smckusick setpriority(curp, uap, retval)
7543365Smckusick 	struct proc *curp;
7643365Smckusick 	register struct args {
778031Sroot 		int	which;
788031Sroot 		int	who;
798031Sroot 		int	prio;
8043365Smckusick 	} *uap;
8143365Smckusick 	int *retval;
8243365Smckusick {
838031Sroot 	register struct proc *p;
8443365Smckusick 	int found = 0, error = 0;
858031Sroot 
868031Sroot 	switch (uap->which) {
878031Sroot 
888031Sroot 	case PRIO_PROCESS:
898176Sroot 		if (uap->who == 0)
9043365Smckusick 			p = curp;
918176Sroot 		else
928176Sroot 			p = pfind(uap->who);
938031Sroot 		if (p == 0)
9428149Skarels 			break;
9543365Smckusick 		error = donice(curp, p, uap->prio);
9617400Skarels 		found++;
978031Sroot 		break;
988031Sroot 
9935810Smarc 	case PRIO_PGRP: {
10035810Smarc 		register struct pgrp *pg;
10135810Smarc 
1028176Sroot 		if (uap->who == 0)
10343365Smckusick 			pg = curp->p_pgrp;
10435810Smarc 		else if ((pg = pgfind(uap->who)) == NULL)
10535810Smarc 			break;
10635810Smarc 		for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
10743365Smckusick 			error = donice(curp, p, uap->prio);
10835810Smarc 			found++;
10935810Smarc 		}
1108031Sroot 		break;
11135810Smarc 	}
1128031Sroot 
1138176Sroot 	case PRIO_USER:
1148176Sroot 		if (uap->who == 0)
11543365Smckusick 			uap->who = p->p_uid;
11616530Skarels 		for (p = allproc; p != NULL; p = p->p_nxt)
11717400Skarels 			if (p->p_uid == uap->who) {
11843365Smckusick 				error = donice(curp, p, uap->prio);
11917400Skarels 				found++;
12017400Skarels 			}
1218176Sroot 		break;
1228176Sroot 
1238031Sroot 	default:
124*44405Skarels 		return (EINVAL);
1258031Sroot 	}
12617400Skarels 	if (found == 0)
127*44405Skarels 		return (ESRCH);
128*44405Skarels 	return (0);
1298031Sroot }
1308031Sroot 
13143365Smckusick donice(curp, chgp, n)
13243365Smckusick 	register struct proc *curp, *chgp;
1338031Sroot 	register int n;
1348031Sroot {
1358031Sroot 
13643365Smckusick 	if (curp->p_uid && curp->p_ruid &&
13743365Smckusick 	    curp->p_uid != chgp->p_uid && curp->p_ruid != chgp->p_uid)
13843365Smckusick 		return (EPERM);
13917400Skarels 	if (n > PRIO_MAX)
14017400Skarels 		n = PRIO_MAX;
14117400Skarels 	if (n < PRIO_MIN)
14217400Skarels 		n = PRIO_MIN;
14343365Smckusick 	if (n < chgp->p_nice && suser(u.u_cred, &u.u_acflag))
14443365Smckusick 		return (EACCES);
14543365Smckusick 	chgp->p_nice = n;
14643365Smckusick 	(void) setpri(chgp);
14743365Smckusick 	return (0);
1488031Sroot }
1498031Sroot 
15043365Smckusick /* ARGSUSED */
15143365Smckusick setrlimit(p, uap, retval)
15243365Smckusick 	struct proc *p;
15343365Smckusick 	register struct args {
1548031Sroot 		u_int	which;
1558031Sroot 		struct	rlimit *lim;
15643365Smckusick 	} *uap;
15743365Smckusick 	int *retval;
15843365Smckusick {
1598031Sroot 	struct rlimit alim;
1608031Sroot 	register struct rlimit *alimp;
16125257Skarels 	extern unsigned maxdmap;
16243365Smckusick 	int error;
1638031Sroot 
16443365Smckusick 	if (uap->which >= RLIM_NLIMITS)
165*44405Skarels 		return (EINVAL);
1668031Sroot 	alimp = &u.u_rlimit[uap->which];
16743365Smckusick 	if (error =
16843365Smckusick 	    copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
169*44405Skarels 		return (error);
1708031Sroot 	if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
17143365Smckusick 		if (error = suser(u.u_cred, &u.u_acflag))
172*44405Skarels 			return (error);
1738031Sroot 	switch (uap->which) {
1748031Sroot 
1758031Sroot 	case RLIMIT_DATA:
17618279Smckusick 		if (alim.rlim_cur > maxdmap)
17718279Smckusick 			alim.rlim_cur = maxdmap;
17818279Smckusick 		if (alim.rlim_max > maxdmap)
17918279Smckusick 			alim.rlim_max = maxdmap;
1808031Sroot 		break;
1818031Sroot 
1828031Sroot 	case RLIMIT_STACK:
18318279Smckusick 		if (alim.rlim_cur > maxdmap)
18418279Smckusick 			alim.rlim_cur = maxdmap;
18518279Smckusick 		if (alim.rlim_max > maxdmap)
18618279Smckusick 			alim.rlim_max = maxdmap;
1878031Sroot 		break;
1888031Sroot 	}
1898031Sroot 	*alimp = alim;
1908031Sroot 	if (uap->which == RLIMIT_RSS)
19143365Smckusick 		p->p_maxrss = alim.rlim_cur/NBPG;
192*44405Skarels 	return (0);
1938031Sroot }
1948031Sroot 
19543365Smckusick /* ARGSUSED */
19643365Smckusick getrlimit(p, uap, retval)
19743365Smckusick 	struct proc *p;
19843365Smckusick 	register struct args {
1998031Sroot 		u_int	which;
2008031Sroot 		struct	rlimit *rlp;
20143365Smckusick 	} *uap;
20243365Smckusick 	int *retval;
20343365Smckusick {
2048031Sroot 
20543365Smckusick 	if (uap->which >= RLIM_NLIMITS)
206*44405Skarels 		return (EINVAL);
207*44405Skarels 	return (copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp,
20843365Smckusick 	    sizeof (struct rlimit)));
2098031Sroot }
2108031Sroot 
21143365Smckusick /* ARGSUSED */
21243365Smckusick getrusage(p, uap, retval)
21343365Smckusick 	register struct proc *p;
21443365Smckusick 	register struct args {
2158031Sroot 		int	who;
2168031Sroot 		struct	rusage *rusage;
21743365Smckusick 	} *uap;
21843365Smckusick 	int *retval;
21943365Smckusick {
2208031Sroot 	register struct rusage *rup;
2218031Sroot 
2228031Sroot 	switch (uap->who) {
2238031Sroot 
22440705Skarels 	case RUSAGE_SELF: {
22540705Skarels 		int s;
22640705Skarels 
2278031Sroot 		rup = &u.u_ru;
22840705Skarels 		s = splclock();
22940705Skarels 		rup->ru_stime = p->p_stime;
23040705Skarels 		rup->ru_utime = p->p_utime;
23140705Skarels 		splx(s);
2328031Sroot 		break;
23340705Skarels 	}
2348031Sroot 
2358031Sroot 	case RUSAGE_CHILDREN:
2368031Sroot 		rup = &u.u_cru;
2378031Sroot 		break;
2388031Sroot 
2398031Sroot 	default:
240*44405Skarels 		return (EINVAL);
2418031Sroot 	}
242*44405Skarels 	return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
24343365Smckusick 	    sizeof (struct rusage)));
2448031Sroot }
2458031Sroot 
2468031Sroot ruadd(ru, ru2)
2478031Sroot 	register struct rusage *ru, *ru2;
2488031Sroot {
2498666Sroot 	register long *ip, *ip2;
2508031Sroot 	register int i;
2518031Sroot 
2528031Sroot 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
2538031Sroot 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
2548031Sroot 	if (ru->ru_maxrss < ru2->ru_maxrss)
2558031Sroot 		ru->ru_maxrss = ru2->ru_maxrss;
2568031Sroot 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
2578031Sroot 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
2588031Sroot 		*ip++ += *ip2++;
2598031Sroot }
260