more-or-less working with new proc & user structs
[unix-history] / usr / src / sys / kern / kern_resource.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
0cee12d3 6 * @(#)kern_resource.c 7.10 (Berkeley) %G%
da7c5cc6 7 */
1b64633a 8
94368568 9#include "param.h"
0cee12d3
MK
10#include "resourcevar.h"
11#include "malloc.h"
94368568 12#include "proc.h"
db1874da 13
93cc02ac
BJ
14/*
15 * Resource controls and accounting.
16 */
17
8eea23a6
KM
18getpriority(curp, uap, retval)
19 struct proc *curp;
20 register struct args {
db1874da
BJ
21 int which;
22 int who;
8eea23a6
KM
23 } *uap;
24 int *retval;
25{
db1874da 26 register struct proc *p;
8fe87cbb 27 register int low = PRIO_MAX + 1;
db1874da 28
db1874da
BJ
29 switch (uap->which) {
30
31 case PRIO_PROCESS:
32 if (uap->who == 0)
8eea23a6 33 p = curp;
db1874da
BJ
34 else
35 p = pfind(uap->who);
36 if (p == 0)
957edfef 37 break;
3fa5efae 38 low = p->p_nice;
db1874da
BJ
39 break;
40
8fe87cbb
MT
41 case PRIO_PGRP: {
42 register struct pgrp *pg;
43
db1874da 44 if (uap->who == 0)
8eea23a6 45 pg = curp->p_pgrp;
8fe87cbb
MT
46 else if ((pg = pgfind(uap->who)) == NULL)
47 break;
48 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
49 if (p->p_nice < low)
3fa5efae 50 low = p->p_nice;
93cc02ac
BJ
51 }
52 break;
8fe87cbb 53 }
93cc02ac
BJ
54
55 case PRIO_USER:
56 if (uap->who == 0)
0cee12d3 57 uap->who = curp->p_ucred->cr_uid;
1d348849 58 for (p = allproc; p != NULL; p = p->p_nxt) {
0cee12d3 59 if (p->p_ucred->cr_uid == uap->who &&
3fa5efae
MK
60 p->p_nice < low)
61 low = p->p_nice;
93cc02ac 62 }
db1874da
BJ
63 break;
64
65 default:
d9c2f47f 66 return (EINVAL);
db1874da 67 }
8eea23a6 68 if (low == PRIO_MAX + 1)
d9c2f47f 69 return (ESRCH);
8eea23a6 70 *retval = low;
d9c2f47f 71 return (0);
db1874da
BJ
72}
73
8eea23a6
KM
74/* ARGSUSED */
75setpriority(curp, uap, retval)
76 struct proc *curp;
77 register struct args {
db1874da
BJ
78 int which;
79 int who;
80 int prio;
8eea23a6
KM
81 } *uap;
82 int *retval;
83{
db1874da 84 register struct proc *p;
8eea23a6 85 int found = 0, error = 0;
db1874da 86
db1874da
BJ
87 switch (uap->which) {
88
89 case PRIO_PROCESS:
93cc02ac 90 if (uap->who == 0)
8eea23a6 91 p = curp;
93cc02ac
BJ
92 else
93 p = pfind(uap->who);
db1874da 94 if (p == 0)
957edfef 95 break;
8eea23a6 96 error = donice(curp, p, uap->prio);
3fa5efae 97 found++;
db1874da
BJ
98 break;
99
8fe87cbb
MT
100 case PRIO_PGRP: {
101 register struct pgrp *pg;
102
93cc02ac 103 if (uap->who == 0)
8eea23a6 104 pg = curp->p_pgrp;
8fe87cbb
MT
105 else if ((pg = pgfind(uap->who)) == NULL)
106 break;
107 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
8eea23a6 108 error = donice(curp, p, uap->prio);
8fe87cbb
MT
109 found++;
110 }
db1874da 111 break;
8fe87cbb 112 }
db1874da 113
93cc02ac
BJ
114 case PRIO_USER:
115 if (uap->who == 0)
0cee12d3 116 uap->who = curp->p_ucred->cr_uid;
1d348849 117 for (p = allproc; p != NULL; p = p->p_nxt)
0cee12d3 118 if (p->p_ucred->cr_uid == uap->who) {
8eea23a6 119 error = donice(curp, p, uap->prio);
3fa5efae
MK
120 found++;
121 }
93cc02ac
BJ
122 break;
123
db1874da 124 default:
d9c2f47f 125 return (EINVAL);
db1874da 126 }
3fa5efae 127 if (found == 0)
d9c2f47f
MK
128 return (ESRCH);
129 return (0);
db1874da
BJ
130}
131
8eea23a6
KM
132donice(curp, chgp, n)
133 register struct proc *curp, *chgp;
db1874da
BJ
134 register int n;
135{
0cee12d3 136 register struct pcred *pcred = curp->p_cred;
db1874da 137
0cee12d3
MK
138 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
139 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
140 pcred->p_ruid != chgp->p_ucred->cr_uid)
8eea23a6 141 return (EPERM);
3fa5efae
MK
142 if (n > PRIO_MAX)
143 n = PRIO_MAX;
144 if (n < PRIO_MIN)
145 n = PRIO_MIN;
0cee12d3 146 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
8eea23a6
KM
147 return (EACCES);
148 chgp->p_nice = n;
149 (void) setpri(chgp);
150 return (0);
db1874da
BJ
151}
152
8eea23a6
KM
153/* ARGSUSED */
154setrlimit(p, uap, retval)
155 struct proc *p;
156 register struct args {
db1874da
BJ
157 u_int which;
158 struct rlimit *lim;
8eea23a6
KM
159 } *uap;
160 int *retval;
161{
db1874da
BJ
162 struct rlimit alim;
163 register struct rlimit *alimp;
63ce5236 164 extern unsigned maxdmap;
8eea23a6 165 int error;
db1874da 166
8eea23a6 167 if (uap->which >= RLIM_NLIMITS)
d9c2f47f 168 return (EINVAL);
0cee12d3 169 alimp = &p->p_rlimit[uap->which];
8eea23a6
KM
170 if (error =
171 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
d9c2f47f 172 return (error);
db1874da 173 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
0cee12d3 174 if (error = suser(p->p_ucred, &p->p_acflag))
d9c2f47f 175 return (error);
0cee12d3
MK
176 if (p->p_limit->p_refcnt > 1 &&
177 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
178 p->p_limit->p_refcnt--;
179 p->p_limit = limcopy(p->p_limit);
180 }
181
db1874da
BJ
182 switch (uap->which) {
183
184 case RLIMIT_DATA:
d9937da6
KM
185 if (alim.rlim_cur > maxdmap)
186 alim.rlim_cur = maxdmap;
187 if (alim.rlim_max > maxdmap)
188 alim.rlim_max = maxdmap;
db1874da
BJ
189 break;
190
191 case RLIMIT_STACK:
d9937da6
KM
192 if (alim.rlim_cur > maxdmap)
193 alim.rlim_cur = maxdmap;
194 if (alim.rlim_max > maxdmap)
195 alim.rlim_max = maxdmap;
db1874da
BJ
196 break;
197 }
198 *alimp = alim;
d9c2f47f 199 return (0);
db1874da
BJ
200}
201
8eea23a6
KM
202/* ARGSUSED */
203getrlimit(p, uap, retval)
204 struct proc *p;
205 register struct args {
db1874da
BJ
206 u_int which;
207 struct rlimit *rlp;
8eea23a6
KM
208 } *uap;
209 int *retval;
210{
db1874da 211
8eea23a6 212 if (uap->which >= RLIM_NLIMITS)
d9c2f47f 213 return (EINVAL);
0cee12d3 214 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
8eea23a6 215 sizeof (struct rlimit)));
db1874da
BJ
216}
217
8eea23a6
KM
218/* ARGSUSED */
219getrusage(p, uap, retval)
220 register struct proc *p;
221 register struct args {
db1874da
BJ
222 int who;
223 struct rusage *rusage;
8eea23a6
KM
224 } *uap;
225 int *retval;
226{
db1874da
BJ
227 register struct rusage *rup;
228
229 switch (uap->who) {
230
e9e38d76
MK
231 case RUSAGE_SELF: {
232 int s;
233
0cee12d3 234 rup = &p->p_stats->p_ru;
e9e38d76
MK
235 s = splclock();
236 rup->ru_stime = p->p_stime;
237 rup->ru_utime = p->p_utime;
238 splx(s);
db1874da 239 break;
e9e38d76 240 }
db1874da
BJ
241
242 case RUSAGE_CHILDREN:
0cee12d3 243 rup = &p->p_stats->p_cru;
db1874da
BJ
244 break;
245
246 default:
d9c2f47f 247 return (EINVAL);
db1874da 248 }
d9c2f47f 249 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
8eea23a6 250 sizeof (struct rusage)));
db1874da
BJ
251}
252
253ruadd(ru, ru2)
254 register struct rusage *ru, *ru2;
255{
3fd23f5c 256 register long *ip, *ip2;
db1874da
BJ
257 register int i;
258
259 timevaladd(&ru->ru_utime, &ru2->ru_utime);
260 timevaladd(&ru->ru_stime, &ru2->ru_stime);
261 if (ru->ru_maxrss < ru2->ru_maxrss)
262 ru->ru_maxrss = ru2->ru_maxrss;
263 ip = &ru->ru_first; ip2 = &ru2->ru_first;
264 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
265 *ip++ += *ip2++;
266}
0cee12d3
MK
267
268/*
269 * Make a copy of the plimit structure.
270 * We share these structures copy-on-write after fork,
271 * and copy when a limit is changed.
272 */
273struct plimit *
274limcopy(lim)
275 struct plimit *lim;
276{
277 register struct plimit *copy;
278
279 MALLOC(copy, struct plimit *, sizeof(struct plimit),
280 M_SUBPROC, M_WAITOK);
281 bcopy(lim->pl_rlimit, copy->pl_rlimit,
282 sizeof(struct rlimit) * RLIM_NLIMITS);
283 copy->p_lflags = 0;
284 copy->p_refcnt = 1;
285 return (copy);
286}