386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / kern / kern_resource.c
CommitLineData
d61ef689
WJ
1/*-
2 * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)kern_resource.c 7.13 (Berkeley) 5/9/91
34 */
35
36#include "param.h"
37#include "resourcevar.h"
38#include "malloc.h"
39#include "proc.h"
40
41#include "vm/vm.h"
42
43/*
44 * Resource controls and accounting.
45 */
46
47getpriority(curp, uap, retval)
48 struct proc *curp;
49 register struct args {
50 int which;
51 int who;
52 } *uap;
53 int *retval;
54{
55 register struct proc *p;
56 register int low = PRIO_MAX + 1;
57
58 switch (uap->which) {
59
60 case PRIO_PROCESS:
61 if (uap->who == 0)
62 p = curp;
63 else
64 p = pfind(uap->who);
65 if (p == 0)
66 break;
67 low = p->p_nice;
68 break;
69
70 case PRIO_PGRP: {
71 register struct pgrp *pg;
72
73 if (uap->who == 0)
74 pg = curp->p_pgrp;
75 else if ((pg = pgfind(uap->who)) == NULL)
76 break;
77 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
78 if (p->p_nice < low)
79 low = p->p_nice;
80 }
81 break;
82 }
83
84 case PRIO_USER:
85 if (uap->who == 0)
86 uap->who = curp->p_ucred->cr_uid;
87 for (p = allproc; p != NULL; p = p->p_nxt) {
88 if (p->p_ucred->cr_uid == uap->who &&
89 p->p_nice < low)
90 low = p->p_nice;
91 }
92 break;
93
94 default:
95 return (EINVAL);
96 }
97 if (low == PRIO_MAX + 1)
98 return (ESRCH);
99 *retval = low;
100 return (0);
101}
102
103/* ARGSUSED */
104setpriority(curp, uap, retval)
105 struct proc *curp;
106 register struct args {
107 int which;
108 int who;
109 int prio;
110 } *uap;
111 int *retval;
112{
113 register struct proc *p;
114 int found = 0, error = 0;
115
116 switch (uap->which) {
117
118 case PRIO_PROCESS:
119 if (uap->who == 0)
120 p = curp;
121 else
122 p = pfind(uap->who);
123 if (p == 0)
124 break;
125 error = donice(curp, p, uap->prio);
126 found++;
127 break;
128
129 case PRIO_PGRP: {
130 register struct pgrp *pg;
131
132 if (uap->who == 0)
133 pg = curp->p_pgrp;
134 else if ((pg = pgfind(uap->who)) == NULL)
135 break;
136 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
137 error = donice(curp, p, uap->prio);
138 found++;
139 }
140 break;
141 }
142
143 case PRIO_USER:
144 if (uap->who == 0)
145 uap->who = curp->p_ucred->cr_uid;
146 for (p = allproc; p != NULL; p = p->p_nxt)
147 if (p->p_ucred->cr_uid == uap->who) {
148 error = donice(curp, p, uap->prio);
149 found++;
150 }
151 break;
152
153 default:
154 return (EINVAL);
155 }
156 if (found == 0)
157 return (ESRCH);
158 return (0);
159}
160
161donice(curp, chgp, n)
162 register struct proc *curp, *chgp;
163 register int n;
164{
165 register struct pcred *pcred = curp->p_cred;
166
167 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
168 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
169 pcred->p_ruid != chgp->p_ucred->cr_uid)
170 return (EPERM);
171 if (n > PRIO_MAX)
172 n = PRIO_MAX;
173 if (n < PRIO_MIN)
174 n = PRIO_MIN;
175 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
176 return (EACCES);
177 chgp->p_nice = n;
178 (void) setpri(chgp);
179 return (0);
180}
181
182/* ARGSUSED */
183setrlimit(p, uap, retval)
184 struct proc *p;
185 register struct args {
186 u_int which;
187 struct rlimit *lim;
188 } *uap;
189 int *retval;
190{
191 struct rlimit alim;
192 register struct rlimit *alimp;
193 extern unsigned maxdmap;
194 int error;
195
196 if (uap->which >= RLIM_NLIMITS)
197 return (EINVAL);
198 alimp = &p->p_rlimit[uap->which];
199 if (error =
200 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
201 return (error);
202 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
203 if (error = suser(p->p_ucred, &p->p_acflag))
204 return (error);
205 if (p->p_limit->p_refcnt > 1 &&
206 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
207 p->p_limit->p_refcnt--;
208 p->p_limit = limcopy(p->p_limit);
209 }
210
211 switch (uap->which) {
212
213 case RLIMIT_DATA:
214 if (alim.rlim_cur > maxdmap)
215 alim.rlim_cur = maxdmap;
216 if (alim.rlim_max > maxdmap)
217 alim.rlim_max = maxdmap;
218 break;
219
220 case RLIMIT_STACK:
221 if (alim.rlim_cur > maxdmap)
222 alim.rlim_cur = maxdmap;
223 if (alim.rlim_max > maxdmap)
224 alim.rlim_max = maxdmap;
225 /*
226 * Stack is allocated to the max at exec time with only
227 * "rlim_cur" bytes accessible. If stack limit is going
228 * up make more accessible, if going down make inaccessible.
229 */
230 if (alim.rlim_cur != alimp->rlim_cur) {
231 vm_offset_t addr;
232 vm_size_t size;
233 vm_prot_t prot;
234 struct vmspace *vm = p->p_vmspace;
235
236 addr = (unsigned) vm->vm_maxsaddr + MAXSSIZ;
237 if (alim.rlim_cur > alimp->rlim_cur) {
238 prot = VM_PROT_ALL;
239 size = alim.rlim_cur - alimp->rlim_cur;
240 addr -= alim.rlim_cur;
241 } else {
242 prot = VM_PROT_NONE;
243 size = alimp->rlim_cur - alim.rlim_cur;
244 addr -= alimp->rlim_cur;
245 }
246 addr = trunc_page(addr);
247 size = round_page(size);
248 (void) vm_map_protect(&p->p_vmspace->vm_map,
249 addr, addr+size, prot, FALSE);
250 }
251 break;
252 }
253 p->p_rlimit[uap->which] = alim;
254 return (0);
255}
256
257/* ARGSUSED */
258getrlimit(p, uap, retval)
259 struct proc *p;
260 register struct args {
261 u_int which;
262 struct rlimit *rlp;
263 } *uap;
264 int *retval;
265{
266
267 if (uap->which >= RLIM_NLIMITS)
268 return (EINVAL);
269 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
270 sizeof (struct rlimit)));
271}
272
273/* ARGSUSED */
274getrusage(p, uap, retval)
275 register struct proc *p;
276 register struct args {
277 int who;
278 struct rusage *rusage;
279 } *uap;
280 int *retval;
281{
282 register struct rusage *rup;
283
284 switch (uap->who) {
285
286 case RUSAGE_SELF: {
287 int s;
288
289 rup = &p->p_stats->p_ru;
290 s = splclock();
291 rup->ru_stime = p->p_stime;
292 rup->ru_utime = p->p_utime;
293 splx(s);
294 break;
295 }
296
297 case RUSAGE_CHILDREN:
298 rup = &p->p_stats->p_cru;
299 break;
300
301 default:
302 return (EINVAL);
303 }
304 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
305 sizeof (struct rusage)));
306}
307
308ruadd(ru, ru2)
309 register struct rusage *ru, *ru2;
310{
311 register long *ip, *ip2;
312 register int i;
313
314 timevaladd(&ru->ru_utime, &ru2->ru_utime);
315 timevaladd(&ru->ru_stime, &ru2->ru_stime);
316 if (ru->ru_maxrss < ru2->ru_maxrss)
317 ru->ru_maxrss = ru2->ru_maxrss;
318 ip = &ru->ru_first; ip2 = &ru2->ru_first;
319 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
320 *ip++ += *ip2++;
321}
322
323/*
324 * Make a copy of the plimit structure.
325 * We share these structures copy-on-write after fork,
326 * and copy when a limit is changed.
327 */
328struct plimit *
329limcopy(lim)
330 struct plimit *lim;
331{
332 register struct plimit *copy;
333
334 MALLOC(copy, struct plimit *, sizeof(struct plimit),
335 M_SUBPROC, M_WAITOK);
336 bcopy(lim->pl_rlimit, copy->pl_rlimit,
337 sizeof(struct rlimit) * RLIM_NLIMITS);
338 copy->p_lflags = 0;
339 copy->p_refcnt = 1;
340 return (copy);
341}