2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
67 #include <sys/resourcevar.h>
68 #include <sys/malloc.h>
70 #include <machine/spl.h>
72 #include <sys/mount.h>
74 #include <machine/vmparam.h>
76 #include <mach/mach_types.h>
77 #include <mach/time_value.h>
78 #include <mach/task_info.h>
80 #include <vm/vm_map.h>
82 int donice
__P((struct proc
*curp
, struct proc
*chgp
, int n
));
83 int dosetrlimit
__P((struct proc
*p
, u_int which
, struct rlimit
*limp
));
85 rlim_t maxdmap
= MAXDSIZ
; /* XXX */
86 rlim_t maxsmap
= MAXSSIZ
; /* XXX */
89 * Resource controls and accounting.
91 struct getpriority_args
{
96 getpriority(curp
, uap
, retval
)
98 register struct getpriority_args
*uap
;
101 register struct proc
*p
;
102 register int low
= PRIO_MAX
+ 1;
104 switch (uap
->which
) {
117 register struct pgrp
*pg
;
121 else if ((pg
= pgfind(uap
->who
)) == NULL
)
123 for (p
= pg
->pg_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
132 uap
->who
= curp
->p_ucred
->cr_uid
;
133 for (p
= allproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
134 if (p
->p_ucred
->cr_uid
== uap
->who
&&
142 if (low
== PRIO_MAX
+ 1)
148 struct setpriority_args
{
155 setpriority(curp
, uap
, retval
)
157 register struct setpriority_args
*uap
;
160 register struct proc
*p
;
161 int found
= 0, error
= 0;
163 switch (uap
->which
) {
172 error
= donice(curp
, p
, uap
->prio
);
177 register struct pgrp
*pg
;
181 else if ((pg
= pgfind(uap
->who
)) == NULL
)
183 for (p
= pg
->pg_members
.lh_first
; p
!= 0;
184 p
= p
->p_pglist
.le_next
) {
185 error
= donice(curp
, p
, uap
->prio
);
193 uap
->who
= curp
->p_ucred
->cr_uid
;
194 for (p
= allproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
195 if (p
->p_ucred
->cr_uid
== uap
->who
) {
196 error
= donice(curp
, p
, uap
->prio
);
210 donice(curp
, chgp
, n
)
211 register struct proc
*curp
, *chgp
;
214 register struct pcred
*pcred
= curp
->p_cred
;
216 if (pcred
->pc_ucred
->cr_uid
&& pcred
->p_ruid
&&
217 pcred
->pc_ucred
->cr_uid
!= chgp
->p_ucred
->cr_uid
&&
218 pcred
->p_ruid
!= chgp
->p_ucred
->cr_uid
)
224 if (n
< chgp
->p_nice
&& suser(pcred
->pc_ucred
, &curp
->p_acflag
))
227 (void)resetpriority(chgp
);
232 struct osetrlimit_args
{
234 struct ogetrlimit
* rlp
;
238 osetrlimit(p
, uap
, retval
)
240 struct osetrlimit_args
*uap
;
247 if (error
= copyin((caddr_t
)uap
->rlp
, (caddr_t
)&olim
,
248 sizeof (struct orlimit
)))
250 lim
.rlim_cur
= olim
.rlim_cur
;
251 lim
.rlim_max
= olim
.rlim_max
;
252 return (dosetrlimit(p
, uap
->which
, &lim
));
255 struct ogetrlimit_args
{
257 struct ogetrlimit
* rlp
;
261 ogetrlimit(p
, uap
, retval
)
263 struct ogetrlimit_args
*uap
;
268 if (uap
->which
>= RLIM_NLIMITS
)
270 olim
.rlim_cur
= p
->p_rlimit
[uap
->which
].rlim_cur
;
271 if (olim
.rlim_cur
== -1)
272 olim
.rlim_cur
= 0x7fffffff;
273 olim
.rlim_max
= p
->p_rlimit
[uap
->which
].rlim_max
;
274 if (olim
.rlim_max
== -1)
275 olim
.rlim_max
= 0x7fffffff;
276 return (copyout((caddr_t
)&olim
, (caddr_t
)uap
->rlp
,
279 #endif /* COMPAT_43 */
281 struct setrlimit_args
{
287 setrlimit(p
, uap
, retval
)
289 register struct setrlimit_args
*uap
;
295 if (error
= copyin((caddr_t
)uap
->rlp
, (caddr_t
)&alim
,
296 sizeof (struct rlimit
)))
298 return (dosetrlimit(p
, uap
->which
, &alim
));
302 dosetrlimit(p
, which
, limp
)
307 register struct rlimit
*alimp
;
308 extern rlim_t maxdmap
, maxsmap
;
311 if (which
>= RLIM_NLIMITS
)
313 alimp
= &p
->p_rlimit
[which
];
314 if (limp
->rlim_cur
> alimp
->rlim_max
||
315 limp
->rlim_max
> alimp
->rlim_max
)
316 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
318 if (limp
->rlim_cur
> limp
->rlim_max
)
319 limp
->rlim_cur
= limp
->rlim_max
;
320 if (p
->p_limit
->p_refcnt
> 1 &&
321 (p
->p_limit
->p_lflags
& PL_SHAREMOD
) == 0) {
322 p
->p_limit
->p_refcnt
--;
323 p
->p_limit
= limcopy(p
->p_limit
);
324 alimp
= &p
->p_rlimit
[which
];
330 if (limp
->rlim_cur
> maxdmap
)
331 limp
->rlim_cur
= maxdmap
;
332 if (limp
->rlim_max
> maxdmap
)
333 limp
->rlim_max
= maxdmap
;
337 if (limp
->rlim_cur
> maxsmap
)
338 limp
->rlim_cur
= maxsmap
;
339 if (limp
->rlim_max
> maxsmap
)
340 limp
->rlim_max
= maxsmap
;
342 * Stack is allocated to the max at exec time with only
343 * "rlim_cur" bytes accessible. If stack limit is going
344 * up make more accessible, if going down make inaccessible.
346 if (limp
->rlim_cur
!= alimp
->rlim_cur
) {
351 if (limp
->rlim_cur
> alimp
->rlim_cur
) {
353 size
= round_page(limp
->rlim_cur
);
354 size
-= round_page(alimp
->rlim_cur
);
357 /* go to top of current stack */
358 addr
= trunc_page(p
->user_stack
+ alimp
->rlim_cur
);
359 #else STACK_GROWTH_UP
360 addr
= trunc_page(p
->user_stack
- alimp
->rlim_cur
);
362 #endif /* STACK_GROWTH_UP */
363 if (vm_allocate(current_map(),
364 &addr
, size
, FALSE
) != KERN_SUCCESS
)
374 * Only root can get the maxfiles limits, as it is systemwide resource
377 if (limp
->rlim_cur
> maxfiles
)
378 limp
->rlim_cur
= maxfiles
;
379 if (limp
->rlim_max
> maxfiles
)
380 limp
->rlim_max
= maxfiles
;
382 if (limp
->rlim_cur
> OPEN_MAX
)
383 limp
->rlim_cur
= OPEN_MAX
;
384 if (limp
->rlim_max
> OPEN_MAX
)
385 limp
->rlim_max
= OPEN_MAX
;
391 * Only root can get the maxproc limits, as it is systemwide resource
394 if (limp
->rlim_cur
> maxproc
)
395 limp
->rlim_cur
= maxproc
;
396 if (limp
->rlim_max
> maxproc
)
397 limp
->rlim_max
= maxproc
;
399 if (limp
->rlim_cur
> CHILD_MAX
)
400 limp
->rlim_cur
= CHILD_MAX
;
401 if (limp
->rlim_max
> CHILD_MAX
)
402 limp
->rlim_max
= CHILD_MAX
;
410 struct getrlimit_args
{
416 getrlimit(p
, uap
, retval
)
418 register struct getrlimit_args
*uap
;
422 if (uap
->which
>= RLIM_NLIMITS
)
424 return (copyout((caddr_t
)&p
->p_rlimit
[uap
->which
],
425 (caddr_t
)uap
->rlp
, sizeof (struct rlimit
)));
429 * Transform the running time and tick information in proc p into user,
430 * system, and interrupt time usage.
433 calcru(p
, up
, sp
, ip
)
434 register struct proc
*p
;
435 register struct timeval
*up
;
436 register struct timeval
*sp
;
437 register struct timeval
*ip
;
448 task_basic_info_data_t tinfo
;
449 task_thread_times_info_data_t ttimesinfo
;
450 int task_info_stuff
, task_ttimes_stuff
;
451 struct timeval ut
,st
;
453 task_info_stuff
= TASK_BASIC_INFO_COUNT
;
454 task_info(task
, TASK_BASIC_INFO
,
455 &tinfo
, &task_info_stuff
);
456 ut
.tv_sec
= tinfo
.user_time
.seconds
;
457 ut
.tv_usec
= tinfo
.user_time
.microseconds
;
458 st
.tv_sec
= tinfo
.system_time
.seconds
;
459 st
.tv_usec
= tinfo
.system_time
.microseconds
;
463 task_ttimes_stuff
= TASK_THREAD_TIMES_INFO_COUNT
;
464 task_info(task
, TASK_THREAD_TIMES_INFO
,
465 &ttimesinfo
, &task_ttimes_stuff
);
467 ut
.tv_sec
= ttimesinfo
.user_time
.seconds
;
468 ut
.tv_usec
= ttimesinfo
.user_time
.microseconds
;
469 st
.tv_sec
= ttimesinfo
.system_time
.seconds
;
470 st
.tv_usec
= ttimesinfo
.system_time
.microseconds
;
476 struct getrusage_args
{
478 struct rusage
* rusage
;
482 getrusage(p
, uap
, retval
)
483 register struct proc
*p
;
484 register struct getrusage_args
*uap
;
487 struct rusage
*rup
, rubuf
;
492 rup
= &p
->p_stats
->p_ru
;
493 calcru(p
, &rup
->ru_utime
, &rup
->ru_stime
, NULL
);
497 case RUSAGE_CHILDREN
:
498 rup
= &p
->p_stats
->p_cru
;
505 return (copyout((caddr_t
)&rubuf
, (caddr_t
)uap
->rusage
,
506 sizeof (struct rusage
)));
511 register struct rusage
*ru
, *ru2
;
513 register long *ip
, *ip2
;
516 timeradd(&ru
->ru_utime
, &ru2
->ru_utime
, &ru
->ru_utime
);
517 timeradd(&ru
->ru_stime
, &ru2
->ru_stime
, &ru
->ru_stime
);
518 if (ru
->ru_maxrss
< ru2
->ru_maxrss
)
519 ru
->ru_maxrss
= ru2
->ru_maxrss
;
520 ip
= &ru
->ru_first
; ip2
= &ru2
->ru_first
;
521 for (i
= &ru
->ru_last
- &ru
->ru_first
; i
>= 0; i
--)
526 * Make a copy of the plimit structure.
527 * We share these structures copy-on-write after fork,
528 * and copy when a limit is changed.
534 register struct plimit
*copy
;
536 MALLOC_ZONE(copy
, struct plimit
*,
537 sizeof(struct plimit
), M_SUBPROC
, M_WAITOK
);
538 bcopy(lim
->pl_rlimit
, copy
->pl_rlimit
,
539 sizeof(struct rlimit
) * RLIM_NLIMITS
);