xref: /csrg-svn/sys/kern/kern_resource.c (revision 8031)
1 /*	kern_resource.c	4.12	82/09/04	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/acct.h"
6 #include "../h/dir.h"
7 #include "../h/user.h"
8 #include "../h/inode.h"
9 #include "../h/proc.h"
10 #include "../h/seg.h"
11 #include "../h/fs.h"
12 #include "../h/uio.h"
13 #include "../h/vm.h"
14 
15 getpriority()
16 {
17 	register struct a {
18 		int	which;
19 		int	who;
20 	} *uap = (struct a *)u.u_ap;
21 	register struct proc *p;
22 
23 	u.u_r.r_val1 = NZERO+20;
24 	u.u_error = ESRCH;
25 	switch (uap->which) {
26 
27 	case PRIO_PROCESS:
28 		if (uap->who == 0)
29 			p = u.u_procp;
30 		else
31 			p = pfind(uap->who);
32 		if (p == 0)
33 			return;
34 		u.u_r.r_val1 = u.u_procp->p_nice;
35 		break;
36 
37 	case PRIO_PGRP:
38 		if (uap->who == 0)
39 			uap->who = u.u_procp->p_pgrp;
40 		for (p = proc; p < procNPROC; p++)
41 			if (p->p_pgrp == uap->who &&
42 			    p->p_nice < u.u_r.r_val1) {
43 				u.u_r.r_val1 = p->p_nice;
44 				u.u_error = 0;
45 			}
46 		break;
47 
48 	default:
49 		u.u_error = EINVAL;
50 		break;
51 	}
52 	u.u_r.r_val1 -= NZERO;
53 }
54 
55 setpriority()
56 {
57 	register struct a {
58 		int	which;
59 		int	who;
60 		int	prio;
61 	} *uap = (struct a *)u.u_ap;
62 	register struct proc *p;
63 
64 	u.u_error = ESRCH;
65 	switch (uap->which) {
66 
67 	case PRIO_PROCESS:
68 		p = pfind(uap->who);
69 		if (p == 0)
70 			return;
71 		donice(p, uap->prio);
72 		break;
73 
74 	case PRIO_PGRP:
75 		for (p = proc; p < procNPROC; p++)
76 			if (p->p_pgrp == uap->who)
77 				donice(p, uap->prio);
78 		break;
79 
80 	default:
81 		u.u_error = EINVAL;
82 		break;
83 	}
84 }
85 
86 donice(p, n)
87 	register struct proc *p;
88 	register int n;
89 {
90 
91 	if (u.u_uid && u.u_ruid &&
92 	    u.u_uid != p->p_uid && u.u_ruid != p->p_uid) {
93 		u.u_error = EPERM;
94 		return;
95 	}
96 	n += p->p_nice;
97 	if (n >= 2*NZERO)
98 		n = 2*NZERO - 1;
99 	if (n < 0)
100 		n = 0;
101 	if (n < p->p_nice && !suser())
102 		return;
103 	p->p_nice = n;
104 	(void) setpri(p);
105 	if (u.u_error == ESRCH)
106 		u.u_error = 0;
107 }
108 
109 setlimit()
110 {
111 	register struct a {
112 		u_int	which;
113 		struct	rlimit *lim;
114 	} *uap = (struct a *)u.u_ap;
115 	struct rlimit alim;
116 	register struct rlimit *alimp;
117 
118 	if (uap->which >= RLIM_NLIMITS) {
119 		u.u_error = EINVAL;
120 		return;
121 	}
122 	alimp = &u.u_rlimit[uap->which];
123 	if (copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) {
124 		u.u_error = EFAULT;
125 		return;
126 	}
127 	if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
128 		if (!suser())
129 			return;
130 	switch (uap->which) {
131 
132 	case RLIMIT_DATA:
133 		if (alim.rlim_cur > ctob(MAXDSIZ))
134 			alim.rlim_cur = ctob(MAXDSIZ);
135 		break;
136 
137 	case RLIMIT_STACK:
138 		if (alim.rlim_cur > ctob(MAXSSIZ))
139 			alim.rlim_cur = ctob(MAXSSIZ);
140 		break;
141 	}
142 	*alimp = alim;
143 	if (uap->which == RLIMIT_RSS)
144 		u.u_procp->p_maxrss = alim.rlim_cur/NBPG;
145 }
146 
147 getlimit()
148 {
149 	register struct a {
150 		u_int	which;
151 		struct	rlimit *rlp;
152 	} *uap = (struct a *)u.u_ap;
153 
154 	if (uap->which >= RLIM_NLIMITS) {
155 		u.u_error = EINVAL;
156 		return;
157 	}
158 	if (copyout((caddr_t)&u.u_rlimit[uap->which], uap->rlp,
159 	    sizeof (struct rlimit))) {
160 		u.u_error = EFAULT;
161 		return;
162 	}
163 }
164 
165 getrusage()
166 {
167 	register struct a {
168 		int	who;
169 		struct	rusage *rusage;
170 	} *uap = (struct a *)u.u_ap;
171 	register struct rusage *rup;
172 
173 	switch (uap->who) {
174 
175 	case RUSAGE_SELF:
176 		rup = &u.u_ru;
177 		break;
178 
179 	case RUSAGE_CHILDREN:
180 		rup = &u.u_cru;
181 		break;
182 
183 	default:
184 		u.u_error = EINVAL;
185 		return;
186 	}
187 	if (copyout((caddr_t)rup, uap->rusage, sizeof (struct rusage))) {
188 		u.u_error = EFAULT;
189 		return;
190 	}
191 }
192 
193 ruadd(ru, ru2)
194 	register struct rusage *ru, *ru2;
195 {
196 	register int *ip, *ip2;
197 	register int i;
198 
199 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
200 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
201 	if (ru->ru_maxrss < ru2->ru_maxrss)
202 		ru->ru_maxrss = ru2->ru_maxrss;
203 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
204 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
205 		*ip++ += *ip2++;
206 }
207 
208 struct	inode *acctp;
209 struct	inode *savacctp;
210 
211 long	acctlow	= 2;		/* stop accounting when < 2% data space left */
212 long	accthigh = 4;		/* resume when space risen to > 4% */
213 
214 /*
215  * Perform process accounting functions.
216  */
217 sysacct()
218 {
219 	register struct inode *ip;
220 	register struct a {
221 		char	*fname;
222 	} *uap;
223 
224 	uap = (struct a *)u.u_ap;
225 	if (suser()) {
226 		if (savacctp) {
227 			acctp = savacctp;
228 			savacctp = NULL;
229 		}
230 		if (uap->fname==NULL) {
231 			if (ip = acctp) {
232 				irele(ip);
233 				acctp = NULL;
234 			}
235 			return;
236 		}
237 		ip = namei(uchar, 0, 1);
238 		if(ip == NULL)
239 			return;
240 		if((ip->i_mode & IFMT) != IFREG) {
241 			u.u_error = EACCES;
242 			iput(ip);
243 			return;
244 		}
245 		if (acctp && (acctp->i_number != ip->i_number ||
246 		    acctp->i_dev != ip->i_dev))
247 			irele(acctp);
248 		acctp = ip;
249 		iunlock(ip);
250 	}
251 }
252 
253 struct	acct acctbuf;
254 /*
255  * On exit, write a record on the accounting file.
256  */
257 acct()
258 {
259 	register i;
260 	register struct inode *ip;
261 	off_t siz;
262 	register struct acct *ap = &acctbuf;
263 
264 	if (savacctp && savacctp->i_fs->fs_cstotal.cs_nbfree >
265 	    accthigh * savacctp->i_fs->fs_dsize / 100) {
266 		acctp = savacctp;
267 		savacctp = NULL;
268 		printf("Accounting resumed\n");
269 	}
270 	if ((ip=acctp)==NULL)
271 		return;
272 	if (acctp->i_fs->fs_cstotal.cs_nbfree <
273 	    acctlow * acctp->i_fs->fs_dsize / 100) {
274 		savacctp = acctp;
275 		acctp = NULL;
276 		printf("Accounting suspended\n");
277 		return;
278 	}
279 	ilock(ip);
280 	for (i=0; i<sizeof(ap->ac_comm); i++)
281 		ap->ac_comm[i] = u.u_comm[i];
282 	ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec);
283 	ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec);
284 	ap->ac_etime = compress((long)(time - u.u_start));
285 	ap->ac_btime = u.u_start;
286 	ap->ac_uid = u.u_ruid;
287 	ap->ac_gid = u.u_rgid;
288 	ap->ac_mem = 0;
289 	if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec)
290 		ap->ac_mem =
291 		    (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i;
292 	ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock));
293 	if (u.u_ttyp)
294 		ap->ac_tty = u.u_ttyd;
295 	else
296 		ap->ac_tty = NODEV;
297 	ap->ac_flag = u.u_acflag;
298 	siz = ip->i_size;
299 	u.u_error =
300 	    rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
301 		1, (int *)0);
302 	if (u.u_error)
303 		ip->i_size = siz;
304 	iunlock(ip);
305 }
306 
307 /*
308  * Produce a pseudo-floating point representation
309  * with 3 bits base-8 exponent, 13 bits fraction.
310  */
311 compress(t)
312 register long t;
313 {
314 	register exp = 0, round = 0;
315 
316 	while (t >= 8192) {
317 		exp++;
318 		round = t&04;
319 		t >>= 3;
320 	}
321 	if (round) {
322 		t++;
323 		if (t >= 8192) {
324 			t >>= 3;
325 			exp++;
326 		}
327 	}
328 	return((exp<<13) + t);
329 }
330 
331 #ifndef NOCOMPAT
332 onice()
333 {
334 	register struct a {
335 		int	niceness;
336 	} *uap;
337 
338 	uap = (struct a *)u.u_ap;
339 	donice(u.u_procp, uap->niceness);
340 }
341 #endif
342