kern_racct.c revision 225938
1303980Sngie/*-
2303980Sngie * Copyright (c) 2010 The FreeBSD Foundation
3303980Sngie * All rights reserved.
4303980Sngie *
5303980Sngie * This software was developed by Edward Tomasz Napierala under sponsorship
6303980Sngie * from the FreeBSD Foundation.
7303980Sngie *
8303980Sngie * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/kern/kern_racct.c 225938 2011-10-03 15:32:15Z trasz $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/kern_racct.c 225938 2011-10-03 15:32:15Z trasz $");
34
35#include "opt_kdtrace.h"
36
37#include <sys/param.h>
38#include <sys/eventhandler.h>
39#include <sys/param.h>
40#include <sys/jail.h>
41#include <sys/kernel.h>
42#include <sys/kthread.h>
43#include <sys/lock.h>
44#include <sys/loginclass.h>
45#include <sys/malloc.h>
46#include <sys/mutex.h>
47#include <sys/proc.h>
48#include <sys/racct.h>
49#include <sys/resourcevar.h>
50#include <sys/sbuf.h>
51#include <sys/sched.h>
52#include <sys/sdt.h>
53#include <sys/sx.h>
54#include <sys/sysent.h>
55#include <sys/sysproto.h>
56#include <sys/systm.h>
57#include <sys/umtx.h>
58
59#ifdef RCTL
60#include <sys/rctl.h>
61#endif
62
63#ifdef RACCT
64
65FEATURE(racct, "Resource Accounting");
66
67static struct mtx racct_lock;
68MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF);
69
70static uma_zone_t racct_zone;
71
72static void racct_sub_racct(struct racct *dest, const struct racct *src);
73static void racct_sub_cred_locked(struct ucred *cred, int resource,
74		uint64_t amount);
75static void racct_add_cred_locked(struct ucred *cred, int resource,
76		uint64_t amount);
77
78SDT_PROVIDER_DEFINE(racct);
79SDT_PROBE_DEFINE3(racct, kernel, rusage, add, add, "struct proc *", "int",
80    "uint64_t");
81SDT_PROBE_DEFINE3(racct, kernel, rusage, add_failure, add-failure,
82    "struct proc *", "int", "uint64_t");
83SDT_PROBE_DEFINE3(racct, kernel, rusage, add_cred, add-cred, "struct ucred *",
84    "int", "uint64_t");
85SDT_PROBE_DEFINE3(racct, kernel, rusage, add_force, add-force, "struct proc *",
86    "int", "uint64_t");
87SDT_PROBE_DEFINE3(racct, kernel, rusage, set, set, "struct proc *", "int",
88    "uint64_t");
89SDT_PROBE_DEFINE3(racct, kernel, rusage, set_failure, set-failure,
90    "struct proc *", "int", "uint64_t");
91SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, sub, "struct proc *", "int",
92    "uint64_t");
93SDT_PROBE_DEFINE3(racct, kernel, rusage, sub_cred, sub-cred, "struct ucred *",
94    "int", "uint64_t");
95SDT_PROBE_DEFINE1(racct, kernel, racct, create, create, "struct racct *");
96SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, destroy, "struct racct *");
97SDT_PROBE_DEFINE2(racct, kernel, racct, join, join, "struct racct *",
98    "struct racct *");
99SDT_PROBE_DEFINE2(racct, kernel, racct, join_failure, join-failure,
100    "struct racct *", "struct racct *");
101SDT_PROBE_DEFINE2(racct, kernel, racct, leave, leave, "struct racct *",
102    "struct racct *");
103
104int racct_types[] = {
105	[RACCT_CPU] =
106		RACCT_IN_MILLIONS,
107	[RACCT_DATA] =
108		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
109	[RACCT_STACK] =
110		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
111	[RACCT_CORE] =
112		RACCT_DENIABLE,
113	[RACCT_RSS] =
114		RACCT_RECLAIMABLE,
115	[RACCT_MEMLOCK] =
116		RACCT_RECLAIMABLE | RACCT_DENIABLE,
117	[RACCT_NPROC] =
118		RACCT_RECLAIMABLE | RACCT_DENIABLE,
119	[RACCT_NOFILE] =
120		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
121	[RACCT_VMEM] =
122		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
123	[RACCT_NPTS] =
124		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
125	[RACCT_SWAP] =
126		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
127	[RACCT_NTHR] =
128		RACCT_RECLAIMABLE | RACCT_DENIABLE,
129	[RACCT_MSGQQUEUED] =
130		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
131	[RACCT_MSGQSIZE] =
132		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
133	[RACCT_NMSGQ] =
134		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
135	[RACCT_NSEM] =
136		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
137	[RACCT_NSEMOP] =
138		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
139	[RACCT_NSHM] =
140		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
141	[RACCT_SHMSIZE] =
142		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
143	[RACCT_WALLCLOCK] =
144		RACCT_IN_MILLIONS };
145
146static void
147racct_add_racct(struct racct *dest, const struct racct *src)
148{
149	int i;
150
151	mtx_assert(&racct_lock, MA_OWNED);
152
153	/*
154	 * Update resource usage in dest.
155	 */
156	for (i = 0; i <= RACCT_MAX; i++) {
157		KASSERT(dest->r_resources[i] >= 0,
158		    ("racct propagation meltdown: dest < 0"));
159		KASSERT(src->r_resources[i] >= 0,
160		    ("racct propagation meltdown: src < 0"));
161		dest->r_resources[i] += src->r_resources[i];
162	}
163}
164
165static void
166racct_sub_racct(struct racct *dest, const struct racct *src)
167{
168	int i;
169
170	mtx_assert(&racct_lock, MA_OWNED);
171
172	/*
173	 * Update resource usage in dest.
174	 */
175	for (i = 0; i <= RACCT_MAX; i++) {
176		if (!RACCT_IS_SLOPPY(i)) {
177			KASSERT(dest->r_resources[i] >= 0,
178			    ("racct propagation meltdown: dest < 0"));
179			KASSERT(src->r_resources[i] >= 0,
180			    ("racct propagation meltdown: src < 0"));
181			KASSERT(src->r_resources[i] <= dest->r_resources[i],
182			    ("racct propagation meltdown: src > dest"));
183		}
184		if (RACCT_IS_RECLAIMABLE(i)) {
185			dest->r_resources[i] -= src->r_resources[i];
186			if (dest->r_resources[i] < 0) {
187				KASSERT(RACCT_IS_SLOPPY(i),
188				    ("racct_sub_racct: usage < 0"));
189				dest->r_resources[i] = 0;
190			}
191		}
192	}
193}
194
195void
196racct_create(struct racct **racctp)
197{
198
199	SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0);
200
201	KASSERT(*racctp == NULL, ("racct already allocated"));
202
203	*racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO);
204}
205
206static void
207racct_destroy_locked(struct racct **racctp)
208{
209	int i;
210	struct racct *racct;
211
212	SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0);
213
214	mtx_assert(&racct_lock, MA_OWNED);
215	KASSERT(racctp != NULL, ("NULL racctp"));
216	KASSERT(*racctp != NULL, ("NULL racct"));
217
218	racct = *racctp;
219
220	for (i = 0; i <= RACCT_MAX; i++) {
221		if (RACCT_IS_SLOPPY(i))
222			continue;
223		if (!RACCT_IS_RECLAIMABLE(i))
224			continue;
225		KASSERT(racct->r_resources[i] == 0,
226		    ("destroying non-empty racct: "
227		    "%ju allocated for resource %d\n",
228		    racct->r_resources[i], i));
229	}
230	uma_zfree(racct_zone, racct);
231	*racctp = NULL;
232}
233
234void
235racct_destroy(struct racct **racct)
236{
237
238	mtx_lock(&racct_lock);
239	racct_destroy_locked(racct);
240	mtx_unlock(&racct_lock);
241}
242
243/*
244 * Increase consumption of 'resource' by 'amount' for 'racct'
245 * and all its parents.  Differently from other cases, 'amount' here
246 * may be less than zero.
247 */
248static void
249racct_alloc_resource(struct racct *racct, int resource,
250    uint64_t amount)
251{
252
253	mtx_assert(&racct_lock, MA_OWNED);
254	KASSERT(racct != NULL, ("NULL racct"));
255
256	racct->r_resources[resource] += amount;
257	if (racct->r_resources[resource] < 0) {
258		KASSERT(RACCT_IS_SLOPPY(resource),
259		    ("racct_alloc_resource: usage < 0"));
260		racct->r_resources[resource] = 0;
261	}
262}
263
264/*
265 * Increase allocation of 'resource' by 'amount' for process 'p'.
266 * Return 0 if it's below limits, or errno, if it's not.
267 */
268int
269racct_add(struct proc *p, int resource, uint64_t amount)
270{
271#ifdef RCTL
272	int error;
273#endif
274
275	if (p->p_flag & P_SYSTEM)
276		return (0);
277
278	SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0);
279
280	/*
281	 * We need proc lock to dereference p->p_ucred.
282	 */
283	PROC_LOCK_ASSERT(p, MA_OWNED);
284
285	mtx_lock(&racct_lock);
286#ifdef RCTL
287	error = rctl_enforce(p, resource, amount);
288	if (error && RACCT_IS_DENIABLE(resource)) {
289		SDT_PROBE(racct, kernel, rusage, add_failure, p, resource,
290		    amount, 0, 0);
291		mtx_unlock(&racct_lock);
292		return (error);
293	}
294#endif
295	racct_alloc_resource(p->p_racct, resource, amount);
296	racct_add_cred_locked(p->p_ucred, resource, amount);
297	mtx_unlock(&racct_lock);
298
299	return (0);
300}
301
302static void
303racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
304{
305	struct prison *pr;
306
307	SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount,
308	    0, 0);
309
310	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
311	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
312		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
313		    amount);
314	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount);
315}
316
317/*
318 * Increase allocation of 'resource' by 'amount' for credential 'cred'.
319 * Doesn't check for limits and never fails.
320 *
321 * XXX: Shouldn't this ever return an error?
322 */
323void
324racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
325{
326
327	mtx_lock(&racct_lock);
328	racct_add_cred_locked(cred, resource, amount);
329	mtx_unlock(&racct_lock);
330}
331
332/*
333 * Increase allocation of 'resource' by 'amount' for process 'p'.
334 * Doesn't check for limits and never fails.
335 */
336void
337racct_add_force(struct proc *p, int resource, uint64_t amount)
338{
339
340	if (p->p_flag & P_SYSTEM)
341		return;
342
343	SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0);
344
345	/*
346	 * We need proc lock to dereference p->p_ucred.
347	 */
348	PROC_LOCK_ASSERT(p, MA_OWNED);
349
350	mtx_lock(&racct_lock);
351	racct_alloc_resource(p->p_racct, resource, amount);
352	mtx_unlock(&racct_lock);
353	racct_add_cred(p->p_ucred, resource, amount);
354}
355
356static int
357racct_set_locked(struct proc *p, int resource, uint64_t amount)
358{
359	int64_t diff;
360#ifdef RCTL
361	int error;
362#endif
363
364	if (p->p_flag & P_SYSTEM)
365		return (0);
366
367	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
368
369	/*
370	 * We need proc lock to dereference p->p_ucred.
371	 */
372	PROC_LOCK_ASSERT(p, MA_OWNED);
373
374	diff = amount - p->p_racct->r_resources[resource];
375#ifdef notyet
376	KASSERT(diff >= 0 || RACCT_IS_RECLAIMABLE(resource),
377	    ("racct_set: usage of non-reclaimable resource %d dropping",
378	     resource));
379#endif
380#ifdef RCTL
381	if (diff > 0) {
382		error = rctl_enforce(p, resource, diff);
383		if (error && RACCT_IS_DENIABLE(resource)) {
384			SDT_PROBE(racct, kernel, rusage, set_failure, p,
385			    resource, amount, 0, 0);
386			return (error);
387		}
388	}
389#endif
390	racct_alloc_resource(p->p_racct, resource, diff);
391	if (diff > 0)
392		racct_add_cred_locked(p->p_ucred, resource, diff);
393	else if (diff < 0)
394		racct_sub_cred_locked(p->p_ucred, resource, -diff);
395
396	return (0);
397}
398
399/*
400 * Set allocation of 'resource' to 'amount' for process 'p'.
401 * Return 0 if it's below limits, or errno, if it's not.
402 *
403 * Note that decreasing the allocation always returns 0,
404 * even if it's above the limit.
405 */
406int
407racct_set(struct proc *p, int resource, uint64_t amount)
408{
409	int error;
410
411	mtx_lock(&racct_lock);
412	error = racct_set_locked(p, resource, amount);
413	mtx_unlock(&racct_lock);
414	return (error);
415}
416
417void
418racct_set_force(struct proc *p, int resource, uint64_t amount)
419{
420	int64_t diff;
421
422	if (p->p_flag & P_SYSTEM)
423		return;
424
425	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
426
427	/*
428	 * We need proc lock to dereference p->p_ucred.
429	 */
430	PROC_LOCK_ASSERT(p, MA_OWNED);
431
432	mtx_lock(&racct_lock);
433	diff = amount - p->p_racct->r_resources[resource];
434	racct_alloc_resource(p->p_racct, resource, diff);
435	if (diff > 0)
436		racct_add_cred_locked(p->p_ucred, resource, diff);
437	else if (diff < 0)
438		racct_sub_cred_locked(p->p_ucred, resource, -diff);
439	mtx_unlock(&racct_lock);
440}
441
442/*
443 * Returns amount of 'resource' the process 'p' can keep allocated.
444 * Allocating more than that would be denied, unless the resource
445 * is marked undeniable.  Amount of already allocated resource does
446 * not matter.
447 */
448uint64_t
449racct_get_limit(struct proc *p, int resource)
450{
451
452#ifdef RCTL
453	return (rctl_get_limit(p, resource));
454#else
455	return (UINT64_MAX);
456#endif
457}
458
459/*
460 * Returns amount of 'resource' the process 'p' can keep allocated.
461 * Allocating more than that would be denied, unless the resource
462 * is marked undeniable.  Amount of already allocated resource does
463 * matter.
464 */
465uint64_t
466racct_get_available(struct proc *p, int resource)
467{
468
469#ifdef RCTL
470	return (rctl_get_available(p, resource));
471#else
472	return (UINT64_MAX);
473#endif
474}
475
476/*
477 * Decrease allocation of 'resource' by 'amount' for process 'p'.
478 */
479void
480racct_sub(struct proc *p, int resource, uint64_t amount)
481{
482
483	if (p->p_flag & P_SYSTEM)
484		return;
485
486	SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0);
487
488	/*
489	 * We need proc lock to dereference p->p_ucred.
490	 */
491	PROC_LOCK_ASSERT(p, MA_OWNED);
492	KASSERT(RACCT_IS_RECLAIMABLE(resource),
493	    ("racct_sub: called for non-reclaimable resource %d", resource));
494
495	mtx_lock(&racct_lock);
496	KASSERT(amount <= p->p_racct->r_resources[resource],
497	    ("racct_sub: freeing %ju of resource %d, which is more "
498	     "than allocated %jd for %s (pid %d)", amount, resource,
499	    (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid));
500
501	racct_alloc_resource(p->p_racct, resource, -amount);
502	racct_sub_cred_locked(p->p_ucred, resource, amount);
503	mtx_unlock(&racct_lock);
504}
505
506static void
507racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
508{
509	struct prison *pr;
510
511	SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount,
512	    0, 0);
513
514#ifdef notyet
515	KASSERT(RACCT_IS_RECLAIMABLE(resource),
516	    ("racct_sub_cred: called for non-reclaimable resource %d",
517	     resource));
518#endif
519
520	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount);
521	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
522		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
523		    -amount);
524	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount);
525}
526
527/*
528 * Decrease allocation of 'resource' by 'amount' for credential 'cred'.
529 */
530void
531racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
532{
533
534	mtx_lock(&racct_lock);
535	racct_sub_cred_locked(cred, resource, amount);
536	mtx_unlock(&racct_lock);
537}
538
539/*
540 * Inherit resource usage information from the parent process.
541 */
542int
543racct_proc_fork(struct proc *parent, struct proc *child)
544{
545	int i, error = 0;
546
547	/*
548	 * Create racct for the child process.
549	 */
550	racct_create(&child->p_racct);
551
552	/*
553	 * No resource accounting for kernel processes.
554	 */
555	if (child->p_flag & P_SYSTEM)
556		return (0);
557
558	PROC_LOCK(parent);
559	PROC_LOCK(child);
560	mtx_lock(&racct_lock);
561
562	/*
563	 * Inherit resource usage.
564	 */
565	for (i = 0; i <= RACCT_MAX; i++) {
566		if (parent->p_racct->r_resources[i] == 0 ||
567		    !RACCT_IS_INHERITABLE(i))
568			continue;
569
570		error = racct_set_locked(child, i,
571		    parent->p_racct->r_resources[i]);
572		if (error != 0)
573			goto out;
574	}
575
576#ifdef RCTL
577	error = rctl_proc_fork(parent, child);
578#endif
579
580out:
581	mtx_unlock(&racct_lock);
582	PROC_UNLOCK(child);
583	PROC_UNLOCK(parent);
584
585	return (error);
586}
587
588void
589racct_proc_exit(struct proc *p)
590{
591	int i;
592	uint64_t runtime;
593
594	PROC_LOCK(p);
595	/*
596	 * We don't need to calculate rux, proc_reap() has already done this.
597	 */
598	runtime = cputick2usec(p->p_rux.rux_runtime);
599#ifdef notyet
600	KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
601#else
602	if (runtime < p->p_prev_runtime)
603		runtime = p->p_prev_runtime;
604#endif
605	mtx_lock(&racct_lock);
606	racct_set_locked(p, RACCT_CPU, runtime);
607
608	for (i = 0; i <= RACCT_MAX; i++) {
609		if (p->p_racct->r_resources[i] == 0)
610			continue;
611	    	if (!RACCT_IS_RECLAIMABLE(i))
612			continue;
613		racct_set_locked(p, i, 0);
614	}
615
616	mtx_unlock(&racct_lock);
617	PROC_UNLOCK(p);
618
619#ifdef RCTL
620	rctl_racct_release(p->p_racct);
621#endif
622	racct_destroy(&p->p_racct);
623}
624
625/*
626 * Called after credentials change, to move resource utilisation
627 * between raccts.
628 */
629void
630racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
631    struct ucred *newcred)
632{
633	struct uidinfo *olduip, *newuip;
634	struct loginclass *oldlc, *newlc;
635	struct prison *oldpr, *newpr, *pr;
636
637	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
638
639	newuip = newcred->cr_ruidinfo;
640	olduip = oldcred->cr_ruidinfo;
641	newlc = newcred->cr_loginclass;
642	oldlc = oldcred->cr_loginclass;
643	newpr = newcred->cr_prison;
644	oldpr = oldcred->cr_prison;
645
646	mtx_lock(&racct_lock);
647	if (newuip != olduip) {
648		racct_sub_racct(olduip->ui_racct, p->p_racct);
649		racct_add_racct(newuip->ui_racct, p->p_racct);
650	}
651	if (newlc != oldlc) {
652		racct_sub_racct(oldlc->lc_racct, p->p_racct);
653		racct_add_racct(newlc->lc_racct, p->p_racct);
654	}
655	if (newpr != oldpr) {
656		for (pr = oldpr; pr != NULL; pr = pr->pr_parent)
657			racct_sub_racct(pr->pr_prison_racct->prr_racct,
658			    p->p_racct);
659		for (pr = newpr; pr != NULL; pr = pr->pr_parent)
660			racct_add_racct(pr->pr_prison_racct->prr_racct,
661			    p->p_racct);
662	}
663	mtx_unlock(&racct_lock);
664
665#ifdef RCTL
666	rctl_proc_ucred_changed(p, newcred);
667#endif
668}
669
670static void
671racctd(void)
672{
673	struct thread *td;
674	struct proc *p;
675	struct timeval wallclock;
676	uint64_t runtime;
677
678	for (;;) {
679		sx_slock(&allproc_lock);
680
681		FOREACH_PROC_IN_SYSTEM(p) {
682			if (p->p_state != PRS_NORMAL)
683				continue;
684			if (p->p_flag & P_SYSTEM)
685				continue;
686
687			microuptime(&wallclock);
688			timevalsub(&wallclock, &p->p_stats->p_start);
689			PROC_LOCK(p);
690			PROC_SLOCK(p);
691			FOREACH_THREAD_IN_PROC(p, td) {
692				ruxagg(p, td);
693				thread_lock(td);
694				thread_unlock(td);
695			}
696			runtime = cputick2usec(p->p_rux.rux_runtime);
697			PROC_SUNLOCK(p);
698#ifdef notyet
699			KASSERT(runtime >= p->p_prev_runtime,
700			    ("runtime < p_prev_runtime"));
701#else
702			if (runtime < p->p_prev_runtime)
703				runtime = p->p_prev_runtime;
704#endif
705			p->p_prev_runtime = runtime;
706			mtx_lock(&racct_lock);
707			racct_set_locked(p, RACCT_CPU, runtime);
708			racct_set_locked(p, RACCT_WALLCLOCK,
709			    wallclock.tv_sec * 1000000 + wallclock.tv_usec);
710			mtx_unlock(&racct_lock);
711			PROC_UNLOCK(p);
712		}
713		sx_sunlock(&allproc_lock);
714		pause("-", hz);
715	}
716}
717
718static struct kproc_desc racctd_kp = {
719	"racctd",
720	racctd,
721	NULL
722};
723SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp);
724
725static void
726racct_init(void)
727{
728
729	racct_zone = uma_zcreate("racct", sizeof(struct racct),
730	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
731	/*
732	 * XXX: Move this somewhere.
733	 */
734	prison0.pr_prison_racct = prison_racct_find("0");
735}
736SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL);
737
738#else /* !RACCT */
739
740int
741racct_add(struct proc *p, int resource, uint64_t amount)
742{
743
744	return (0);
745}
746
747void
748racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
749{
750}
751
752void
753racct_add_force(struct proc *p, int resource, uint64_t amount)
754{
755
756	return;
757}
758
759int
760racct_set(struct proc *p, int resource, uint64_t amount)
761{
762
763	return (0);
764}
765
766void
767racct_set_force(struct proc *p, int resource, uint64_t amount)
768{
769}
770
771void
772racct_sub(struct proc *p, int resource, uint64_t amount)
773{
774}
775
776void
777racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
778{
779}
780
781uint64_t
782racct_get_limit(struct proc *p, int resource)
783{
784
785	return (UINT64_MAX);
786}
787
788uint64_t
789racct_get_available(struct proc *p, int resource)
790{
791
792	return (UINT64_MAX);
793}
794
795void
796racct_create(struct racct **racctp)
797{
798}
799
800void
801racct_destroy(struct racct **racctp)
802{
803}
804
805int
806racct_proc_fork(struct proc *parent, struct proc *child)
807{
808
809	return (0);
810}
811
812void
813racct_proc_exit(struct proc *p)
814{
815}
816
817#endif /* !RACCT */
818