Install tmac.s & tmac.mm correctly
[unix-history] / sys / kern / kern_resource.c
CommitLineData
15637ed4
RG
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;
d7f27d01 194 extern int maxfdescs;
15637ed4
RG
195 int error;
196
197 if (uap->which >= RLIM_NLIMITS)
198 return (EINVAL);
199 alimp = &p->p_rlimit[uap->which];
200 if (error =
201 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
202 return (error);
203 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
204 if (error = suser(p->p_ucred, &p->p_acflag))
205 return (error);
206 if (p->p_limit->p_refcnt > 1 &&
207 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
208 p->p_limit->p_refcnt--;
209 p->p_limit = limcopy(p->p_limit);
210 }
211
212 switch (uap->which) {
213
214 case RLIMIT_DATA:
215 if (alim.rlim_cur > maxdmap)
216 alim.rlim_cur = maxdmap;
217 if (alim.rlim_max > maxdmap)
218 alim.rlim_max = maxdmap;
219 break;
220
d7f27d01
NW
221 case RLIMIT_OFILE:
222 if (alim.rlim_cur > maxfdescs)
223 alim.rlim_cur = maxfdescs;
224 if (alim.rlim_max > maxfdescs)
225 alim.rlim_max = maxfdescs;
226 break;
15637ed4
RG
227 case RLIMIT_STACK:
228 if (alim.rlim_cur > maxdmap)
229 alim.rlim_cur = maxdmap;
230 if (alim.rlim_max > maxdmap)
231 alim.rlim_max = maxdmap;
232 /*
233 * Stack is allocated to the max at exec time with only
234 * "rlim_cur" bytes accessible. If stack limit is going
235 * up make more accessible, if going down make inaccessible.
236 */
237 if (alim.rlim_cur != alimp->rlim_cur) {
238 vm_offset_t addr;
239 vm_size_t size;
240 vm_prot_t prot;
241 struct vmspace *vm = p->p_vmspace;
242
243 addr = (unsigned) vm->vm_maxsaddr + MAXSSIZ;
244 if (alim.rlim_cur > alimp->rlim_cur) {
245 prot = VM_PROT_ALL;
246 size = alim.rlim_cur - alimp->rlim_cur;
247 addr -= alim.rlim_cur;
248 } else {
249 prot = VM_PROT_NONE;
250 size = alimp->rlim_cur - alim.rlim_cur;
251 addr -= alimp->rlim_cur;
252 }
253 addr = trunc_page(addr);
254 size = round_page(size);
255 (void) vm_map_protect(&p->p_vmspace->vm_map,
256 addr, addr+size, prot, FALSE);
257 }
258 break;
259 }
260 p->p_rlimit[uap->which] = alim;
261 return (0);
262}
263
264/* ARGSUSED */
265getrlimit(p, uap, retval)
266 struct proc *p;
267 register struct args {
268 u_int which;
269 struct rlimit *rlp;
270 } *uap;
271 int *retval;
272{
273
274 if (uap->which >= RLIM_NLIMITS)
275 return (EINVAL);
276 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
277 sizeof (struct rlimit)));
278}
279
280/* ARGSUSED */
281getrusage(p, uap, retval)
282 register struct proc *p;
283 register struct args {
284 int who;
285 struct rusage *rusage;
286 } *uap;
287 int *retval;
288{
289 register struct rusage *rup;
290
291 switch (uap->who) {
292
293 case RUSAGE_SELF: {
294 int s;
295
296 rup = &p->p_stats->p_ru;
297 s = splclock();
298 rup->ru_stime = p->p_stime;
299 rup->ru_utime = p->p_utime;
300 splx(s);
301 break;
302 }
303
304 case RUSAGE_CHILDREN:
305 rup = &p->p_stats->p_cru;
306 break;
307
308 default:
309 return (EINVAL);
310 }
311 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
312 sizeof (struct rusage)));
313}
314
315ruadd(ru, ru2)
316 register struct rusage *ru, *ru2;
317{
318 register long *ip, *ip2;
319 register int i;
320
321 timevaladd(&ru->ru_utime, &ru2->ru_utime);
322 timevaladd(&ru->ru_stime, &ru2->ru_stime);
323 if (ru->ru_maxrss < ru2->ru_maxrss)
324 ru->ru_maxrss = ru2->ru_maxrss;
325 ip = &ru->ru_first; ip2 = &ru2->ru_first;
326 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
327 *ip++ += *ip2++;
328}
329
330/*
331 * Make a copy of the plimit structure.
332 * We share these structures copy-on-write after fork,
333 * and copy when a limit is changed.
334 */
335struct plimit *
336limcopy(lim)
337 struct plimit *lim;
338{
339 register struct plimit *copy;
340
341 MALLOC(copy, struct plimit *, sizeof(struct plimit),
342 M_SUBPROC, M_WAITOK);
343 bcopy(lim->pl_rlimit, copy->pl_rlimit,
344 sizeof(struct rlimit) * RLIM_NLIMITS);
345 copy->p_lflags = 0;
346 copy->p_refcnt = 1;
347 return (copy);
348}