1/*
2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32#include <kern/kern_types.h>
33#include <kern/ledger.h>
34#include <kern/kalloc.h>
35#include <kern/task.h>
36
37#include <kern/processor.h>
38#include <kern/machine.h>
39#include <kern/queue.h>
40#include <sys/errno.h>
41
42#include <libkern/OSAtomic.h>
43#include <mach/mach_types.h>
44
45/*
46 * Ledger entry flags. Bits in second nibble (masked by 0xF0) are used for
47 * ledger actions (LEDGER_ACTION_BLOCK, etc).
48 */
49#define	LF_ENTRY_ACTIVE         0x0001	/* entry is active if set */
50#define	LF_WAKE_NEEDED          0x0100	/* one or more threads are asleep */
51#define	LF_WAKE_INPROGRESS      0x0200	/* the wait queue is being processed */
52#define	LF_REFILL_SCHEDULED     0x0400	/* a refill timer has been set */
53#define	LF_REFILL_INPROGRESS    0x0800	/* the ledger is being refilled */
54#define	LF_CALLED_BACK          0x1000	/* callback was called for balance in deficit */
55#define	LF_WARNED               0x2000	/* callback was called for balance warning */
56#define	LF_TRACKING_MAX		0x4000	/* track max balance over user-specfied time */
57#define LF_PANIC_ON_NEGATIVE	0x8000	/* panic if it goes negative */
58
59/* Determine whether a ledger entry exists and has been initialized and active */
60#define	ENTRY_VALID(l, e)					\
61	(((l) != NULL) && ((e) >= 0) && ((e) < (l)->l_size) &&	\
62	(((l)->l_entries[e].le_flags & LF_ENTRY_ACTIVE) == LF_ENTRY_ACTIVE))
63
64#define ASSERT(a) assert(a)
65
66#ifdef LEDGER_DEBUG
67int ledger_debug = 0;
68
69#define	lprintf(a) if (ledger_debug) {					\
70	printf("%lld  ", abstime_to_nsecs(mach_absolute_time() / 1000000)); \
71	printf a ;							\
72}
73#else
74#define	lprintf(a)
75#endif
76
77struct ledger_callback {
78	ledger_callback_t	lc_func;
79	const void		*lc_param0;
80	const void		*lc_param1;
81};
82
83struct entry_template {
84	char			et_key[LEDGER_NAME_MAX];
85	char			et_group[LEDGER_NAME_MAX];
86	char			et_units[LEDGER_NAME_MAX];
87	uint32_t		et_flags;
88	struct ledger_callback	*et_callback;
89};
90
91lck_grp_t ledger_lck_grp;
92
93/*
94 * Modifying the reference count, table size, or table contents requires
95 * holding the lt_lock.  Modfying the table address requires both lt_lock
96 * and setting the inuse bit.  This means that the lt_entries field can be
97 * safely dereferenced if you hold either the lock or the inuse bit.  The
98 * inuse bit exists solely to allow us to swap in a new, larger entries
99 * table without requiring a full lock to be acquired on each lookup.
100 * Accordingly, the inuse bit should never be held for longer than it takes
101 * to extract a value from the table - i.e., 2 or 3 memory references.
102 */
103struct ledger_template {
104	const char		*lt_name;
105	int			lt_refs;
106	int			lt_cnt;
107	int			lt_table_size;
108	volatile uint32_t	lt_inuse;
109	lck_mtx_t		lt_lock;
110	struct entry_template	*lt_entries;
111};
112
113#define template_lock(template)		lck_mtx_lock(&(template)->lt_lock)
114#define template_unlock(template)	lck_mtx_unlock(&(template)->lt_lock)
115
116#define TEMPLATE_INUSE(s, t) { 					\
117	s = splsched();						\
118	while (OSCompareAndSwap(0, 1, &((t)->lt_inuse)))	\
119		;						\
120}
121
122#define TEMPLATE_IDLE(s, t) { 					\
123	(t)->lt_inuse = 0;					\
124	splx(s);						\
125}
126
127/*
128 * Use 2 "tocks" to track the rolling maximum balance of a ledger entry.
129 */
130#define	NTOCKS 2
131/*
132 * The explicit alignment is to ensure that atomic operations don't panic
133 * on ARM.
134 */
135struct ledger_entry {
136        volatile uint32_t               le_flags;
137        ledger_amount_t                 le_limit;
138        ledger_amount_t                 le_warn_level;
139        volatile ledger_amount_t        le_credit __attribute__((aligned(8)));
140        volatile ledger_amount_t        le_debit  __attribute__((aligned(8)));
141	union {
142		struct {
143			/*
144			 * XXX - the following two fields can go away if we move all of
145			 * the refill logic into process policy
146			 */
147		        uint64_t	le_refill_period;
148		        uint64_t	le_last_refill;
149		} le_refill;
150		struct _le_peak {
151			uint32_t 	le_max;  /* Lower 32-bits of observed max balance */
152			uint32_t	le_time; /* time when this peak was observed */
153		} le_peaks[NTOCKS];
154	} _le;
155} __attribute__((aligned(8)));
156
157struct ledger {
158	int			l_id;
159	struct ledger_template	*l_template;
160	int			l_refs;
161	int			l_size;
162	struct ledger_entry	*l_entries;
163};
164
165static int ledger_cnt = 0;
166/* ledger ast helper functions */
167static uint32_t ledger_check_needblock(ledger_t l, uint64_t now);
168static kern_return_t ledger_perform_blocking(ledger_t l);
169static uint32_t flag_set(volatile uint32_t *flags, uint32_t bit);
170static uint32_t flag_clear(volatile uint32_t *flags, uint32_t bit);
171
172#if 0
173static void
174debug_callback(const void *p0, __unused const void *p1)
175{
176	printf("ledger: resource exhausted [%s] for task %p\n",
177	    (const char *)p0, p1);
178}
179#endif
180
181/************************************/
182
183static uint64_t
184abstime_to_nsecs(uint64_t abstime)
185{
186	uint64_t nsecs;
187
188	absolutetime_to_nanoseconds(abstime, &nsecs);
189	return (nsecs);
190}
191
192static uint64_t
193nsecs_to_abstime(uint64_t nsecs)
194{
195	uint64_t abstime;
196
197	nanoseconds_to_absolutetime(nsecs, &abstime);
198	return (abstime);
199}
200
201void
202ledger_init(void)
203{
204        lck_grp_init(&ledger_lck_grp, "ledger", LCK_GRP_ATTR_NULL);
205}
206
207ledger_template_t
208ledger_template_create(const char *name)
209{
210	ledger_template_t template;
211
212	template = (ledger_template_t)kalloc(sizeof (*template));
213	if (template == NULL)
214		return (NULL);
215
216	template->lt_name = name;
217	template->lt_refs = 1;
218	template->lt_cnt = 0;
219	template->lt_table_size = 1;
220	template->lt_inuse = 0;
221	lck_mtx_init(&template->lt_lock, &ledger_lck_grp, LCK_ATTR_NULL);
222
223	template->lt_entries = (struct entry_template *)
224	    kalloc(sizeof (struct entry_template) * template->lt_table_size);
225	if (template->lt_entries == NULL) {
226		kfree(template, sizeof (*template));
227		template = NULL;
228	}
229
230	return (template);
231}
232
233void
234ledger_template_dereference(ledger_template_t template)
235{
236	template_lock(template);
237	template->lt_refs--;
238	template_unlock(template);
239
240	if (template->lt_refs == 0)
241		kfree(template, sizeof (*template));
242}
243
244/*
245 * Add a new entry to the list of entries in a ledger template. There is
246 * currently no mechanism to remove an entry.  Implementing such a mechanism
247 * would require us to maintain per-entry reference counts, which we would
248 * prefer to avoid if possible.
249 */
250int
251ledger_entry_add(ledger_template_t template, const char *key,
252    const char *group, const char *units)
253{
254	int idx;
255	struct entry_template *et;
256
257	if ((key == NULL) || (strlen(key) >= LEDGER_NAME_MAX))
258		return (-1);
259
260	template_lock(template);
261
262	/* If the table is full, attempt to double its size */
263	if (template->lt_cnt == template->lt_table_size) {
264		struct entry_template *new_entries, *old_entries;
265		int old_cnt, old_sz;
266		spl_t s;
267
268		old_cnt = template->lt_table_size;
269		old_sz = (int)(old_cnt * sizeof (struct entry_template));
270		new_entries = kalloc(old_sz * 2);
271		if (new_entries == NULL) {
272			template_unlock(template);
273			return (-1);
274		}
275		memcpy(new_entries, template->lt_entries, old_sz);
276		memset(((char *)new_entries) + old_sz, 0, old_sz);
277		template->lt_table_size = old_cnt * 2;
278
279		old_entries = template->lt_entries;
280
281		TEMPLATE_INUSE(s, template);
282		template->lt_entries = new_entries;
283		TEMPLATE_IDLE(s, template);
284
285		kfree(old_entries, old_sz);
286	}
287
288	et = &template->lt_entries[template->lt_cnt];
289	strlcpy(et->et_key, key, LEDGER_NAME_MAX);
290	strlcpy(et->et_group, group, LEDGER_NAME_MAX);
291	strlcpy(et->et_units, units, LEDGER_NAME_MAX);
292	et->et_flags = LF_ENTRY_ACTIVE;
293	et->et_callback = NULL;
294
295	idx = template->lt_cnt++;
296	template_unlock(template);
297
298	return (idx);
299}
300
301
302kern_return_t
303ledger_entry_setactive(ledger_t ledger, int entry)
304{
305	struct ledger_entry *le;
306
307	if ((ledger == NULL)  || (entry < 0) || (entry >= ledger->l_size))
308		return (KERN_INVALID_ARGUMENT);
309
310	le = &ledger->l_entries[entry];
311	if ((le->le_flags & LF_ENTRY_ACTIVE) == 0) {
312		flag_set(&le->le_flags, LF_ENTRY_ACTIVE);
313	}
314	return (KERN_SUCCESS);
315}
316
317
318int
319ledger_key_lookup(ledger_template_t template, const char *key)
320{
321	int idx;
322
323	template_lock(template);
324	for (idx = 0; idx < template->lt_cnt; idx++)
325		if (template->lt_entries[idx].et_key &&
326		    (strcmp(key, template->lt_entries[idx].et_key) == 0))
327			break;
328
329	if (idx >= template->lt_cnt)
330		idx = -1;
331	template_unlock(template);
332
333	return (idx);
334}
335
336/*
337 * Create a new ledger based on the specified template.  As part of the
338 * ledger creation we need to allocate space for a table of ledger entries.
339 * The size of the table is based on the size of the template at the time
340 * the ledger is created.  If additional entries are added to the template
341 * after the ledger is created, they will not be tracked in this ledger.
342 */
343ledger_t
344ledger_instantiate(ledger_template_t template, int entry_type)
345{
346	ledger_t ledger;
347	size_t sz;
348	int i;
349
350	ledger = (ledger_t)kalloc(sizeof (struct ledger));
351	if (ledger == NULL)
352		return (LEDGER_NULL);
353
354	ledger->l_template = template;
355	ledger->l_id = ledger_cnt++;
356	ledger->l_refs = 1;
357
358	template_lock(template);
359	template->lt_refs++;
360	ledger->l_size = template->lt_cnt;
361	template_unlock(template);
362
363	sz = ledger->l_size * sizeof (struct ledger_entry);
364	ledger->l_entries = kalloc(sz);
365	if (sz && (ledger->l_entries == NULL)) {
366		ledger_template_dereference(template);
367		kfree(ledger, sizeof(struct ledger));
368		return (LEDGER_NULL);
369	}
370
371	template_lock(template);
372	assert(ledger->l_size <= template->lt_cnt);
373	for (i = 0; i < ledger->l_size; i++) {
374		struct ledger_entry *le = &ledger->l_entries[i];
375		struct entry_template *et = &template->lt_entries[i];
376
377		le->le_flags = et->et_flags;
378		/* make entry inactive by removing  active bit */
379		if (entry_type == LEDGER_CREATE_INACTIVE_ENTRIES)
380			flag_clear(&le->le_flags, LF_ENTRY_ACTIVE);
381		/*
382		 * If template has a callback, this entry is opted-in,
383		 * by default.
384		 */
385		if (et->et_callback != NULL)
386			flag_set(&le->le_flags, LEDGER_ACTION_CALLBACK);
387		le->le_credit        = 0;
388		le->le_debit         = 0;
389		le->le_limit         = LEDGER_LIMIT_INFINITY;
390		le->le_warn_level    = LEDGER_LIMIT_INFINITY;
391		le->_le.le_refill.le_refill_period = 0;
392		le->_le.le_refill.le_last_refill   = 0;
393	}
394	template_unlock(template);
395
396	return (ledger);
397}
398
399static uint32_t
400flag_set(volatile uint32_t *flags, uint32_t bit)
401{
402	return (OSBitOrAtomic(bit, flags));
403}
404
405static uint32_t
406flag_clear(volatile uint32_t *flags, uint32_t bit)
407{
408	return (OSBitAndAtomic(~bit, flags));
409}
410
411/*
412 * Take a reference on a ledger
413 */
414kern_return_t
415ledger_reference(ledger_t ledger)
416{
417	if (!LEDGER_VALID(ledger))
418		return (KERN_INVALID_ARGUMENT);
419	OSIncrementAtomic(&ledger->l_refs);
420	return (KERN_SUCCESS);
421}
422
423int
424ledger_reference_count(ledger_t ledger)
425{
426	if (!LEDGER_VALID(ledger))
427		return (-1);
428
429	return (ledger->l_refs);
430}
431
432/*
433 * Remove a reference on a ledger.  If this is the last reference,
434 * deallocate the unused ledger.
435 */
436kern_return_t
437ledger_dereference(ledger_t ledger)
438{
439	int v;
440
441	if (!LEDGER_VALID(ledger))
442		return (KERN_INVALID_ARGUMENT);
443
444	v = OSDecrementAtomic(&ledger->l_refs);
445	ASSERT(v >= 1);
446
447	/* Just released the last reference.  Free it. */
448	if (v == 1) {
449		kfree(ledger->l_entries,
450		    ledger->l_size * sizeof (struct ledger_entry));
451		kfree(ledger, sizeof (*ledger));
452	}
453
454	return (KERN_SUCCESS);
455}
456
457/*
458 * Determine whether an entry has exceeded its warning level.
459 */
460static inline int
461warn_level_exceeded(struct ledger_entry *le)
462{
463	ledger_amount_t balance;
464
465	assert((le->le_credit >= 0) && (le->le_debit >= 0));
466
467	/*
468	 * XXX - Currently, we only support warnings for ledgers which
469	 * use positive limits.
470	 */
471	balance = le->le_credit - le->le_debit;
472	if ((le->le_warn_level != LEDGER_LIMIT_INFINITY) && (balance > le->le_warn_level))
473		return (1);
474	return (0);
475}
476
477/*
478 * Determine whether an entry has exceeded its limit.
479 */
480static inline int
481limit_exceeded(struct ledger_entry *le)
482{
483	ledger_amount_t balance;
484
485	assert((le->le_credit >= 0) && (le->le_debit >= 0));
486
487	balance = le->le_credit - le->le_debit;
488	if ((le->le_limit <= 0) && (balance < le->le_limit))
489		return (1);
490
491	if ((le->le_limit > 0) && (balance > le->le_limit))
492		return (1);
493	return (0);
494}
495
496static inline struct ledger_callback *
497entry_get_callback(ledger_t ledger, int entry)
498{
499	struct ledger_callback *callback;
500	spl_t s;
501
502	TEMPLATE_INUSE(s, ledger->l_template);
503	callback = ledger->l_template->lt_entries[entry].et_callback;
504	TEMPLATE_IDLE(s, ledger->l_template);
505
506	return (callback);
507}
508
509/*
510 * If the ledger value is positive, wake up anybody waiting on it.
511 */
512static inline void
513ledger_limit_entry_wakeup(struct ledger_entry *le)
514{
515	uint32_t flags;
516
517	if (!limit_exceeded(le)) {
518		flags = flag_clear(&le->le_flags, LF_CALLED_BACK);
519
520		while (le->le_flags & LF_WAKE_NEEDED) {
521			flag_clear(&le->le_flags, LF_WAKE_NEEDED);
522			thread_wakeup((event_t)le);
523		}
524	}
525}
526
527/*
528 * Refill the coffers.
529 */
530static void
531ledger_refill(uint64_t now, ledger_t ledger, int entry)
532{
533	uint64_t elapsed, period, periods;
534	struct ledger_entry *le;
535	ledger_amount_t balance, due;
536
537	le = &ledger->l_entries[entry];
538
539	assert(le->le_limit != LEDGER_LIMIT_INFINITY);
540
541	/*
542	 * If another thread is handling the refill already, we're not
543	 * needed.
544	 */
545	if (flag_set(&le->le_flags, LF_REFILL_INPROGRESS) & LF_REFILL_INPROGRESS) {
546		return;
547	}
548
549	/*
550	 * If the timestamp we're about to use to refill is older than the
551	 * last refill, then someone else has already refilled this ledger
552	 * and there's nothing for us to do here.
553	 */
554	if (now <= le->_le.le_refill.le_last_refill) {
555		flag_clear(&le->le_flags, LF_REFILL_INPROGRESS);
556		return;
557	}
558
559	/*
560	 * See how many refill periods have passed since we last
561	 * did a refill.
562	 */
563	period = le->_le.le_refill.le_refill_period;
564	elapsed = now - le->_le.le_refill.le_last_refill;
565	if ((period == 0) || (elapsed < period)) {
566		flag_clear(&le->le_flags, LF_REFILL_INPROGRESS);
567		return;
568	}
569
570	/*
571	 * Optimize for the most common case of only one or two
572	 * periods elapsing.
573	 */
574	periods = 0;
575	while ((periods < 2) && (elapsed > 0)) {
576		periods++;
577		elapsed -= period;
578	}
579
580	/*
581	 * OK, it's been a long time.  Do a divide to figure out
582	 * how long.
583	 */
584	if (elapsed > 0)
585		periods = (now - le->_le.le_refill.le_last_refill) / period;
586
587	balance = le->le_credit - le->le_debit;
588	due = periods * le->le_limit;
589	if (balance - due < 0)
590		due = balance;
591
592	assert(due >= 0);
593
594	OSAddAtomic64(due, &le->le_debit);
595
596	assert(le->le_debit >= 0);
597
598	/*
599	 * If we've completely refilled the pool, set the refill time to now.
600	 * Otherwise set it to the time at which it last should have been
601	 * fully refilled.
602	 */
603	if (balance == due)
604		le->_le.le_refill.le_last_refill = now;
605	else
606		le->_le.le_refill.le_last_refill += (le->_le.le_refill.le_refill_period * periods);
607
608	flag_clear(&le->le_flags, LF_REFILL_INPROGRESS);
609
610	lprintf(("Refill %lld %lld->%lld\n", periods, balance, balance - due));
611	if (!limit_exceeded(le))
612		ledger_limit_entry_wakeup(le);
613}
614
615/*
616 * In tenths of a second, the length of one lookback period (a "tock") for
617 * ledger rolling maximum calculations. The effective lookback window will be this times
618 * NTOCKS.
619 *
620 * Use a tock length of 2.5 seconds to get a total lookback period of 5 seconds.
621 *
622 * XXX Could make this caller-definable, at the point that rolling max tracking
623 * is enabled for the entry.
624 */
625#define	TOCKLEN 25
626
627/*
628 * How many sched_tick's are there in one tock (one of our lookback periods)?
629 *
630 *  X sched_ticks        2.5 sec      N sched_ticks
631 * ---------------   =  ----------  * -------------
632 *      tock               tock            sec
633 *
634 * where N sched_ticks/sec is calculated via 1 << SCHED_TICK_SHIFT (see sched_prim.h)
635 *
636 * This should give us 20 sched_tick's in one 2.5 second-long tock.
637 */
638#define SCHED_TICKS_PER_TOCK ((TOCKLEN * (1 << SCHED_TICK_SHIFT)) / 10)
639
640/*
641 * Rolling max timestamps use their own unit (let's call this a "tock"). One tock is the
642 * length of one lookback period that we use for our rolling max calculation.
643 *
644 * Calculate the current time in tocks from sched_tick (which runs at a some
645 * fixed rate).
646 */
647#define	CURRENT_TOCKSTAMP() (sched_tick / SCHED_TICKS_PER_TOCK)
648
649/*
650 * Does the given tockstamp fall in either the current or the previous tocks?
651 */
652#define TOCKSTAMP_IS_STALE(now, tock) ((((now) - (tock)) < NTOCKS) ? FALSE : TRUE)
653
654static void
655ledger_check_new_balance(ledger_t ledger, int entry)
656{
657	struct ledger_entry *le;
658
659	le = &ledger->l_entries[entry];
660
661	if (le->le_flags & LF_TRACKING_MAX) {
662		ledger_amount_t balance = le->le_credit - le->le_debit;
663		uint32_t now = CURRENT_TOCKSTAMP();
664		struct _le_peak *p = &le->_le.le_peaks[now % NTOCKS];
665
666		if (!TOCKSTAMP_IS_STALE(now, p->le_time) || (balance > p->le_max)) {
667			/*
668			 * The current balance is greater than the previously
669			 * observed peak for the current time block, *or* we
670			 * haven't yet recorded a peak for the current time block --
671			 * so this is our new peak.
672			 *
673			 * (We only track the lower 32-bits of a balance for rolling
674			 * max purposes.)
675			 */
676			p->le_max = (uint32_t)balance;
677			p->le_time = now;
678		}
679	}
680
681	/* Check to see whether we're due a refill */
682	if (le->le_flags & LF_REFILL_SCHEDULED) {
683		uint64_t now = mach_absolute_time();
684		if ((now - le->_le.le_refill.le_last_refill) > le->_le.le_refill.le_refill_period)
685			ledger_refill(now, ledger, entry);
686	}
687
688	if (limit_exceeded(le)) {
689		/*
690		 * We've exceeded the limit for this entry.  There
691		 * are several possible ways to handle it.  We can block,
692		 * we can execute a callback, or we can ignore it.  In
693		 * either of the first two cases, we want to set the AST
694		 * flag so we can take the appropriate action just before
695		 * leaving the kernel.  The one caveat is that if we have
696		 * already called the callback, we don't want to do it
697		 * again until it gets rearmed.
698		 */
699		if ((le->le_flags & LEDGER_ACTION_BLOCK) ||
700		    (!(le->le_flags & LF_CALLED_BACK) &&
701		    entry_get_callback(ledger, entry))) {
702			set_astledger(current_thread());
703		}
704	} else {
705		/*
706		 * The balance on the account is below the limit.
707		 *
708		 * If there are any threads blocked on this entry, now would
709		 * be a good time to wake them up.
710		 */
711		if (le->le_flags & LF_WAKE_NEEDED)
712			ledger_limit_entry_wakeup(le);
713
714		if (le->le_flags & LEDGER_ACTION_CALLBACK) {
715			/*
716			 * Client has requested that a callback be invoked whenever
717			 * the ledger's balance crosses into or out of the warning
718			 * level.
719			 */
720		 	if (warn_level_exceeded(le)) {
721		 		/*
722		 		 * This ledger's balance is above the warning level.
723		 		 */
724		 		if ((le->le_flags & LF_WARNED) == 0) {
725		 			/*
726		 			 * If we are above the warning level and
727		 			 * have not yet invoked the callback,
728		 			 * set the AST so it can be done before returning
729		 			 * to userland.
730		 			 */
731					set_astledger(current_thread());
732				}
733			} else {
734				/*
735				 * This ledger's balance is below the warning level.
736				 */
737		 		if (le->le_flags & LF_WARNED) {
738					/*
739					 * If we are below the warning level and
740					 * the LF_WARNED flag is still set, we need
741					 * to invoke the callback to let the client
742					 * know the ledger balance is now back below
743					 * the warning level.
744					 */
745					set_astledger(current_thread());
746				}
747			}
748		}
749	}
750
751	if ((le->le_flags & LF_PANIC_ON_NEGATIVE) &&
752	    (le->le_credit < le->le_debit)) {
753		panic("ledger_check_new_balance(%p,%d): negative ledger %p balance:%lld\n",
754		      ledger, entry, le, le->le_credit - le->le_debit);
755	}
756}
757
758/*
759 * Add value to an entry in a ledger.
760 */
761kern_return_t
762ledger_credit(ledger_t ledger, int entry, ledger_amount_t amount)
763{
764	ledger_amount_t old, new;
765	struct ledger_entry *le;
766
767	if (!ENTRY_VALID(ledger, entry) || (amount < 0))
768		return (KERN_INVALID_VALUE);
769
770	if (amount == 0)
771		return (KERN_SUCCESS);
772
773	le = &ledger->l_entries[entry];
774
775	old = OSAddAtomic64(amount, &le->le_credit);
776	new = old + amount;
777	lprintf(("%p Credit %lld->%lld\n", current_thread(), old, new));
778	ledger_check_new_balance(ledger, entry);
779
780	return (KERN_SUCCESS);
781}
782
783/* Add all of one ledger's values into another.
784 * They must have been created from the same template.
785 * This is not done atomically. Another thread (if not otherwise synchronized)
786 * may see bogus values when comparing one entry to another.
787 * As each entry's credit & debit are modified one at a time, the warning/limit
788 * may spuriously trip, or spuriously fail to trip, or another thread (if not
789 * otherwise synchronized) may see a bogus balance.
790 */
791kern_return_t
792ledger_rollup(ledger_t to_ledger, ledger_t from_ledger)
793{
794	int i;
795	struct ledger_entry *from_le, *to_le;
796
797	assert(to_ledger->l_template == from_ledger->l_template);
798
799	for (i = 0; i < to_ledger->l_size; i++) {
800		if (ENTRY_VALID(from_ledger, i) && ENTRY_VALID(to_ledger, i)) {
801			from_le = &from_ledger->l_entries[i];
802			to_le   =   &to_ledger->l_entries[i];
803			OSAddAtomic64(from_le->le_credit, &to_le->le_credit);
804			OSAddAtomic64(from_le->le_debit,  &to_le->le_debit);
805		}
806	}
807
808	return (KERN_SUCCESS);
809}
810
811/*
812 * Zero the balance of a ledger by adding to its credit or debit, whichever is smaller.
813 * Note that some clients of ledgers (notably, task wakeup statistics) require that
814 * le_credit only ever increase as a function of ledger_credit().
815 */
816kern_return_t
817ledger_zero_balance(ledger_t ledger, int entry)
818{
819	struct ledger_entry *le;
820
821	if (!ENTRY_VALID(ledger, entry))
822		return (KERN_INVALID_VALUE);
823
824	le = &ledger->l_entries[entry];
825
826top:
827	if (le->le_credit > le->le_debit) {
828		if (!OSCompareAndSwap64(le->le_debit, le->le_credit, &le->le_debit))
829			goto top;
830		lprintf(("%p zeroed %lld->%lld\n", current_thread(), le->le_debit, le->le_credit));
831	} else if (le->le_credit < le->le_debit) {
832		if (!OSCompareAndSwap64(le->le_credit, le->le_debit, &le->le_credit))
833			goto top;
834		lprintf(("%p zeroed %lld->%lld\n", current_thread(), le->le_credit, le->le_debit));
835	}
836
837	return (KERN_SUCCESS);
838}
839
840kern_return_t
841ledger_get_limit(ledger_t ledger, int entry, ledger_amount_t *limit)
842{
843	struct ledger_entry *le;
844
845	if (!ENTRY_VALID(ledger, entry))
846		return (KERN_INVALID_VALUE);
847
848	le = &ledger->l_entries[entry];
849	*limit = le->le_limit;
850
851	lprintf(("ledger_get_limit: %lld\n", *limit));
852
853	return (KERN_SUCCESS);
854}
855
856/*
857 * Adjust the limit of a limited resource.  This does not affect the
858 * current balance, so the change doesn't affect the thread until the
859 * next refill.
860 *
861 * warn_level: If non-zero, causes the callback to be invoked when
862 * the balance exceeds this level. Specified as a percentage [of the limit].
863 */
864kern_return_t
865ledger_set_limit(ledger_t ledger, int entry, ledger_amount_t limit,
866 		 uint8_t warn_level_percentage)
867{
868	struct ledger_entry *le;
869
870	if (!ENTRY_VALID(ledger, entry))
871		return (KERN_INVALID_VALUE);
872
873	lprintf(("ledger_set_limit: %lld\n", limit));
874	le = &ledger->l_entries[entry];
875
876	if (limit == LEDGER_LIMIT_INFINITY) {
877		/*
878		 * Caller wishes to disable the limit. This will implicitly
879		 * disable automatic refill, as refills implicitly depend
880		 * on the limit.
881		 */
882		ledger_disable_refill(ledger, entry);
883	}
884
885	le->le_limit = limit;
886	le->_le.le_refill.le_last_refill = 0;
887	flag_clear(&le->le_flags, LF_CALLED_BACK);
888	flag_clear(&le->le_flags, LF_WARNED);
889	ledger_limit_entry_wakeup(le);
890
891	if (warn_level_percentage != 0) {
892		assert(warn_level_percentage <= 100);
893		assert(limit > 0); /* no negative limit support for warnings */
894		assert(limit != LEDGER_LIMIT_INFINITY); /* warn % without limit makes no sense */
895		le->le_warn_level = (le->le_limit * warn_level_percentage) / 100;
896	} else {
897		le->le_warn_level = LEDGER_LIMIT_INFINITY;
898	}
899
900	return (KERN_SUCCESS);
901}
902
903kern_return_t
904ledger_get_maximum(ledger_t ledger, int entry,
905	ledger_amount_t *max_observed_balance)
906{
907	struct ledger_entry	*le;
908	uint32_t		now = CURRENT_TOCKSTAMP();
909	int			i;
910
911	le = &ledger->l_entries[entry];
912
913	if (!ENTRY_VALID(ledger, entry) || !(le->le_flags & LF_TRACKING_MAX)) {
914		return (KERN_INVALID_VALUE);
915	}
916
917	/*
918	 * Start with the current balance; if neither of the recorded peaks are
919	 * within recent history, we use this.
920	 */
921	*max_observed_balance = le->le_credit - le->le_debit;
922
923	for (i = 0; i < NTOCKS; i++) {
924		if (!TOCKSTAMP_IS_STALE(now, le->_le.le_peaks[i].le_time) &&
925		    (le->_le.le_peaks[i].le_max > *max_observed_balance)) {
926		    	/*
927		    	 * The peak for this time block isn't stale, and it
928		    	 * is greater than the current balance -- so use it.
929		    	 */
930		    	*max_observed_balance = le->_le.le_peaks[i].le_max;
931		}
932	}
933
934	lprintf(("ledger_get_maximum: %lld\n", *max_observed_balance));
935
936	return (KERN_SUCCESS);
937}
938
939/*
940 * Enable tracking of periodic maximums for this ledger entry.
941 */
942kern_return_t
943ledger_track_maximum(ledger_template_t template, int entry,
944	__unused int period_in_secs)
945{
946	template_lock(template);
947
948	if ((entry < 0) || (entry >= template->lt_cnt)) {
949		template_unlock(template);
950		return (KERN_INVALID_VALUE);
951	}
952
953	template->lt_entries[entry].et_flags |= LF_TRACKING_MAX;
954	template_unlock(template);
955
956	return (KERN_SUCCESS);
957}
958
959kern_return_t
960ledger_panic_on_negative(ledger_template_t template, int entry)
961{
962	template_lock(template);
963
964	if ((entry < 0) || (entry >= template->lt_cnt)) {
965		template_unlock(template);
966		return (KERN_INVALID_VALUE);
967	}
968
969	template->lt_entries[entry].et_flags |= LF_PANIC_ON_NEGATIVE;
970
971	template_unlock(template);
972
973	return (KERN_SUCCESS);
974}
975/*
976 * Add a callback to be executed when the resource goes into deficit.
977 */
978kern_return_t
979ledger_set_callback(ledger_template_t template, int entry,
980   ledger_callback_t func, const void *param0, const void *param1)
981{
982	struct entry_template *et;
983	struct ledger_callback *old_cb, *new_cb;
984
985	if ((entry < 0) || (entry >= template->lt_cnt))
986		return (KERN_INVALID_VALUE);
987
988	if (func) {
989		new_cb = (struct ledger_callback *)kalloc(sizeof (*new_cb));
990		new_cb->lc_func = func;
991		new_cb->lc_param0 = param0;
992		new_cb->lc_param1 = param1;
993	} else {
994		new_cb = NULL;
995	}
996
997	template_lock(template);
998	et = &template->lt_entries[entry];
999	old_cb = et->et_callback;
1000	et->et_callback = new_cb;
1001	template_unlock(template);
1002	if (old_cb)
1003		kfree(old_cb, sizeof (*old_cb));
1004
1005	return (KERN_SUCCESS);
1006}
1007
1008/*
1009 * Disable callback notification for a specific ledger entry.
1010 *
1011 * Otherwise, if using a ledger template which specified a
1012 * callback function (ledger_set_callback()), it will be invoked when
1013 * the resource goes into deficit.
1014 */
1015kern_return_t
1016ledger_disable_callback(ledger_t ledger, int entry)
1017{
1018	if (!ENTRY_VALID(ledger, entry))
1019		return (KERN_INVALID_VALUE);
1020
1021	/*
1022	 * le_warn_level is used to indicate *if* this ledger has a warning configured,
1023	 * in addition to what that warning level is set to.
1024	 * This means a side-effect of ledger_disable_callback() is that the
1025	 * warning level is forgotten.
1026	 */
1027	ledger->l_entries[entry].le_warn_level = LEDGER_LIMIT_INFINITY;
1028	flag_clear(&ledger->l_entries[entry].le_flags, LEDGER_ACTION_CALLBACK);
1029	return (KERN_SUCCESS);
1030}
1031
1032/*
1033 * Enable callback notification for a specific ledger entry.
1034 *
1035 * This is only needed if ledger_disable_callback() has previously
1036 * been invoked against an entry; there must already be a callback
1037 * configured.
1038 */
1039kern_return_t
1040ledger_enable_callback(ledger_t ledger, int entry)
1041{
1042	if (!ENTRY_VALID(ledger, entry))
1043		return (KERN_INVALID_VALUE);
1044
1045	assert(entry_get_callback(ledger, entry) != NULL);
1046
1047	flag_set(&ledger->l_entries[entry].le_flags, LEDGER_ACTION_CALLBACK);
1048	return (KERN_SUCCESS);
1049}
1050
1051/*
1052 * Query the automatic refill period for this ledger entry.
1053 *
1054 * A period of 0 means this entry has none configured.
1055 */
1056kern_return_t
1057ledger_get_period(ledger_t ledger, int entry, uint64_t *period)
1058{
1059	struct ledger_entry *le;
1060
1061	if (!ENTRY_VALID(ledger, entry))
1062		return (KERN_INVALID_VALUE);
1063
1064	le = &ledger->l_entries[entry];
1065	*period = abstime_to_nsecs(le->_le.le_refill.le_refill_period);
1066	lprintf(("ledger_get_period: %llx\n", *period));
1067	return (KERN_SUCCESS);
1068}
1069
1070/*
1071 * Adjust the automatic refill period.
1072 */
1073kern_return_t
1074ledger_set_period(ledger_t ledger, int entry, uint64_t period)
1075{
1076	struct ledger_entry *le;
1077
1078	lprintf(("ledger_set_period: %llx\n", period));
1079	if (!ENTRY_VALID(ledger, entry))
1080		return (KERN_INVALID_VALUE);
1081
1082	le = &ledger->l_entries[entry];
1083
1084	/*
1085	 * A refill period refills the ledger in multiples of the limit,
1086	 * so if you haven't set one yet, you need a lesson on ledgers.
1087	 */
1088	assert(le->le_limit != LEDGER_LIMIT_INFINITY);
1089
1090	if (le->le_flags & LF_TRACKING_MAX) {
1091		/*
1092		 * Refill is incompatible with rolling max tracking.
1093		 */
1094		return (KERN_INVALID_VALUE);
1095	}
1096
1097	le->_le.le_refill.le_refill_period = nsecs_to_abstime(period);
1098
1099	/*
1100	 * Set the 'starting time' for the next refill to now. Since
1101	 * we're resetting the balance to zero here, we consider this
1102	 * moment the starting time for accumulating a balance that
1103	 * counts towards the limit.
1104	 */
1105	le->_le.le_refill.le_last_refill = mach_absolute_time();
1106	ledger_zero_balance(ledger, entry);
1107
1108	flag_set(&le->le_flags, LF_REFILL_SCHEDULED);
1109
1110	return (KERN_SUCCESS);
1111}
1112
1113/*
1114 * Disable automatic refill.
1115 */
1116kern_return_t
1117ledger_disable_refill(ledger_t ledger, int entry)
1118{
1119	struct ledger_entry *le;
1120
1121	if (!ENTRY_VALID(ledger, entry))
1122		return (KERN_INVALID_VALUE);
1123
1124	le = &ledger->l_entries[entry];
1125
1126	flag_clear(&le->le_flags, LF_REFILL_SCHEDULED);
1127
1128	return (KERN_SUCCESS);
1129}
1130
1131kern_return_t
1132ledger_get_actions(ledger_t ledger, int entry, int *actions)
1133{
1134	if (!ENTRY_VALID(ledger, entry))
1135		return (KERN_INVALID_VALUE);
1136
1137	*actions = ledger->l_entries[entry].le_flags & LEDGER_ACTION_MASK;
1138	lprintf(("ledger_get_actions: %#x\n", *actions));
1139	return (KERN_SUCCESS);
1140}
1141
1142kern_return_t
1143ledger_set_action(ledger_t ledger, int entry, int action)
1144{
1145	lprintf(("ledger_set_action: %#x\n", action));
1146	if (!ENTRY_VALID(ledger, entry))
1147		return (KERN_INVALID_VALUE);
1148
1149	flag_set(&ledger->l_entries[entry].le_flags, action);
1150	return (KERN_SUCCESS);
1151}
1152
1153void
1154set_astledger(thread_t thread)
1155{
1156	spl_t s = splsched();
1157
1158	if (thread == current_thread()) {
1159		thread_ast_set(thread, AST_LEDGER);
1160		ast_propagate(thread->ast);
1161	} else {
1162		processor_t p;
1163
1164		thread_lock(thread);
1165		thread_ast_set(thread, AST_LEDGER);
1166		p = thread->last_processor;
1167		if ((p != PROCESSOR_NULL) && (p->state == PROCESSOR_RUNNING) &&
1168		   (p->active_thread == thread))
1169			cause_ast_check(p);
1170		thread_unlock(thread);
1171	}
1172
1173	splx(s);
1174}
1175
1176kern_return_t
1177ledger_debit(ledger_t ledger, int entry, ledger_amount_t amount)
1178{
1179	struct ledger_entry *le;
1180	ledger_amount_t old, new;
1181
1182	if (!ENTRY_VALID(ledger, entry) || (amount < 0))
1183		return (KERN_INVALID_ARGUMENT);
1184
1185	if (amount == 0)
1186		return (KERN_SUCCESS);
1187
1188	le = &ledger->l_entries[entry];
1189
1190	old = OSAddAtomic64(amount, &le->le_debit);
1191	new = old + amount;
1192
1193	lprintf(("%p Debit %lld->%lld\n", thread, old, new));
1194	ledger_check_new_balance(ledger, entry);
1195	return (KERN_SUCCESS);
1196
1197}
1198
1199void
1200ledger_ast(thread_t thread)
1201{
1202	struct ledger	*l = thread->t_ledger;
1203	struct ledger 	*thl;
1204	uint32_t	block;
1205	uint64_t	now;
1206	uint8_t		task_flags;
1207	uint8_t		task_percentage;
1208	uint64_t	task_interval;
1209
1210	kern_return_t ret;
1211	task_t task = thread->task;
1212
1213	lprintf(("Ledger AST for %p\n", thread));
1214
1215	ASSERT(task != NULL);
1216	ASSERT(thread == current_thread());
1217
1218top:
1219	/*
1220	 * Take a self-consistent snapshot of the CPU usage monitor parameters. The task
1221	 * can change them at any point (with the task locked).
1222	 */
1223	task_lock(task);
1224	task_flags = task->rusage_cpu_flags;
1225	task_percentage = task->rusage_cpu_perthr_percentage;
1226	task_interval = task->rusage_cpu_perthr_interval;
1227	task_unlock(task);
1228
1229	/*
1230	 * Make sure this thread is up to date with regards to any task-wide per-thread
1231	 * CPU limit, but only if it doesn't have a thread-private blocking CPU limit.
1232	 */
1233	if (((task_flags & TASK_RUSECPU_FLAGS_PERTHR_LIMIT) != 0) &&
1234	    ((thread->options & TH_OPT_PRVT_CPULIMIT) == 0)) {
1235		uint8_t	 percentage;
1236		uint64_t interval;
1237		int	 action;
1238
1239		thread_get_cpulimit(&action, &percentage, &interval);
1240
1241		/*
1242		 * If the thread's CPU limits no longer match the task's, or the
1243		 * task has a limit but the thread doesn't, update the limit.
1244		 */
1245		if (((thread->options & TH_OPT_PROC_CPULIMIT) == 0) ||
1246		    (interval != task_interval) || (percentage != task_percentage)) {
1247			thread_set_cpulimit(THREAD_CPULIMIT_EXCEPTION, task_percentage, task_interval);
1248			assert((thread->options & TH_OPT_PROC_CPULIMIT) != 0);
1249		}
1250	} else if (((task_flags & TASK_RUSECPU_FLAGS_PERTHR_LIMIT) == 0) &&
1251		   (thread->options & TH_OPT_PROC_CPULIMIT)) {
1252		assert((thread->options & TH_OPT_PRVT_CPULIMIT) == 0);
1253
1254		/*
1255		 * Task no longer has a per-thread CPU limit; remove this thread's
1256		 * corresponding CPU limit.
1257		 */
1258		thread_set_cpulimit(THREAD_CPULIMIT_DISABLE, 0, 0);
1259		assert((thread->options & TH_OPT_PROC_CPULIMIT) == 0);
1260	}
1261
1262	/*
1263	 * If the task or thread is being terminated, let's just get on with it
1264	 */
1265	if ((l == NULL) || !task->active || task->halting || !thread->active)
1266		return;
1267
1268	/*
1269	 * Examine all entries in deficit to see which might be eligble for
1270	 * an automatic refill, which require callbacks to be issued, and
1271	 * which require blocking.
1272	 */
1273	block = 0;
1274	now = mach_absolute_time();
1275
1276	/*
1277	 * Note that thread->t_threadledger may have been changed by the
1278	 * thread_set_cpulimit() call above - so don't examine it until afterwards.
1279	 */
1280	thl = thread->t_threadledger;
1281	if (LEDGER_VALID(thl)) {
1282		block |= ledger_check_needblock(thl, now);
1283	}
1284	block |= ledger_check_needblock(l, now);
1285
1286	/*
1287	 * If we are supposed to block on the availability of one or more
1288	 * resources, find the first entry in deficit for which we should wait.
1289	 * Schedule a refill if necessary and then sleep until the resource
1290	 * becomes available.
1291	 */
1292	if (block) {
1293		if (LEDGER_VALID(thl)) {
1294			ret = ledger_perform_blocking(thl);
1295			if (ret != KERN_SUCCESS)
1296				goto top;
1297		}
1298		ret = ledger_perform_blocking(l);
1299		if (ret != KERN_SUCCESS)
1300			goto top;
1301	} /* block */
1302}
1303
1304static uint32_t
1305ledger_check_needblock(ledger_t l, uint64_t now)
1306{
1307	int i;
1308	uint32_t flags, block = 0;
1309	struct ledger_entry *le;
1310	struct ledger_callback *lc;
1311
1312
1313	for (i = 0; i < l->l_size; i++) {
1314		le = &l->l_entries[i];
1315
1316		lc = entry_get_callback(l, i);
1317
1318		if (limit_exceeded(le) == FALSE) {
1319			if (le->le_flags & LEDGER_ACTION_CALLBACK) {
1320				/*
1321				 * If needed, invoke the callback as a warning.
1322				 * This needs to happen both when the balance rises above
1323				 * the warning level, and also when it dips back below it.
1324				 */
1325				assert(lc != NULL);
1326				/*
1327				 * See comments for matching logic in ledger_check_new_balance().
1328				 */
1329				if (warn_level_exceeded(le)) {
1330					flags = flag_set(&le->le_flags, LF_WARNED);
1331					if ((flags & LF_WARNED) == 0) {
1332						lc->lc_func(LEDGER_WARNING_ROSE_ABOVE, lc->lc_param0, lc->lc_param1);
1333					}
1334				} else {
1335					flags = flag_clear(&le->le_flags, LF_WARNED);
1336					if (flags & LF_WARNED) {
1337						lc->lc_func(LEDGER_WARNING_DIPPED_BELOW, lc->lc_param0, lc->lc_param1);
1338					}
1339				}
1340			}
1341
1342			continue;
1343		}
1344
1345		/* We're over the limit, so refill if we are eligible and past due. */
1346		if (le->le_flags & LF_REFILL_SCHEDULED) {
1347			if ((le->_le.le_refill.le_last_refill + le->_le.le_refill.le_refill_period) > now) {
1348				ledger_refill(now, l, i);
1349				if (limit_exceeded(le) == FALSE)
1350					continue;
1351			}
1352		}
1353
1354		if (le->le_flags & LEDGER_ACTION_BLOCK)
1355			block = 1;
1356		if ((le->le_flags & LEDGER_ACTION_CALLBACK) == 0)
1357			continue;
1358
1359                /*
1360                 * If the LEDGER_ACTION_CALLBACK flag is on, we expect there to
1361                 * be a registered callback.
1362                 */
1363		assert(lc != NULL);
1364		flags = flag_set(&le->le_flags, LF_CALLED_BACK);
1365		/* Callback has already been called */
1366		if (flags & LF_CALLED_BACK)
1367			continue;
1368		lc->lc_func(FALSE, lc->lc_param0, lc->lc_param1);
1369	}
1370	return(block);
1371}
1372
1373
1374/* return KERN_SUCCESS to continue, KERN_FAILURE to restart */
1375static kern_return_t
1376ledger_perform_blocking(ledger_t l)
1377{
1378	int i;
1379	kern_return_t ret;
1380	struct ledger_entry *le;
1381
1382	for (i = 0; i < l->l_size; i++) {
1383		le = &l->l_entries[i];
1384		if ((!limit_exceeded(le)) ||
1385		    ((le->le_flags & LEDGER_ACTION_BLOCK) == 0))
1386			continue;
1387
1388		/* Prepare to sleep until the resource is refilled */
1389		ret = assert_wait_deadline(le, TRUE,
1390		    le->_le.le_refill.le_last_refill + le->_le.le_refill.le_refill_period);
1391		if (ret != THREAD_WAITING)
1392			return(KERN_SUCCESS);
1393
1394		/* Mark that somebody is waiting on this entry  */
1395		flag_set(&le->le_flags, LF_WAKE_NEEDED);
1396
1397		ret = thread_block_reason(THREAD_CONTINUE_NULL, NULL,
1398		    AST_LEDGER);
1399		if (ret != THREAD_AWAKENED)
1400			return(KERN_SUCCESS);
1401
1402		/*
1403		 * The world may have changed while we were asleep.
1404		 * Some other resource we need may have gone into
1405		 * deficit.  Or maybe we're supposed to die now.
1406		 * Go back to the top and reevaluate.
1407		 */
1408		return(KERN_FAILURE);
1409	}
1410	return(KERN_SUCCESS);
1411}
1412
1413
1414kern_return_t
1415ledger_get_entries(ledger_t ledger, int entry, ledger_amount_t *credit,
1416    ledger_amount_t *debit)
1417{
1418	struct ledger_entry *le;
1419
1420	if (!ENTRY_VALID(ledger, entry))
1421		return (KERN_INVALID_ARGUMENT);
1422
1423	le = &ledger->l_entries[entry];
1424
1425	*credit = le->le_credit;
1426	*debit = le->le_debit;
1427
1428	return (KERN_SUCCESS);
1429}
1430
1431kern_return_t
1432ledger_reset_callback_state(ledger_t ledger, int entry)
1433{
1434	struct ledger_entry *le;
1435
1436	if (!ENTRY_VALID(ledger, entry))
1437		return (KERN_INVALID_ARGUMENT);
1438
1439	le = &ledger->l_entries[entry];
1440
1441	flag_clear(&le->le_flags, LF_CALLED_BACK);
1442
1443	return (KERN_SUCCESS);
1444}
1445
1446kern_return_t
1447ledger_disable_panic_on_negative(ledger_t ledger, int entry)
1448{
1449	struct ledger_entry *le;
1450
1451	if (!ENTRY_VALID(ledger, entry))
1452		return (KERN_INVALID_ARGUMENT);
1453
1454	le = &ledger->l_entries[entry];
1455
1456	flag_clear(&le->le_flags, LF_PANIC_ON_NEGATIVE);
1457
1458	return (KERN_SUCCESS);
1459}
1460
1461kern_return_t
1462ledger_get_balance(ledger_t ledger, int entry, ledger_amount_t *balance)
1463{
1464	struct ledger_entry *le;
1465
1466	if (!ENTRY_VALID(ledger, entry))
1467		return (KERN_INVALID_ARGUMENT);
1468
1469	le = &ledger->l_entries[entry];
1470
1471	assert((le->le_credit >= 0) && (le->le_debit >= 0));
1472
1473	*balance = le->le_credit - le->le_debit;
1474
1475	return (KERN_SUCCESS);
1476}
1477
1478int
1479ledger_template_info(void **buf, int *len)
1480{
1481	struct ledger_template_info *lti;
1482	struct entry_template *et;
1483	int i;
1484	ledger_t l;
1485
1486	/*
1487	 * Since all tasks share a ledger template, we'll just use the
1488	 * caller's as the source.
1489	 */
1490	l = current_task()->ledger;
1491	if ((*len < 0) || (l == NULL))
1492		return (EINVAL);
1493
1494	if (*len > l->l_size)
1495		 *len = l->l_size;
1496	lti = kalloc((*len) * sizeof (struct ledger_template_info));
1497	if (lti == NULL)
1498		return (ENOMEM);
1499	*buf = lti;
1500
1501	template_lock(l->l_template);
1502	et = l->l_template->lt_entries;
1503
1504	for (i = 0; i < *len; i++) {
1505		memset(lti, 0, sizeof (*lti));
1506		strlcpy(lti->lti_name, et->et_key, LEDGER_NAME_MAX);
1507		strlcpy(lti->lti_group, et->et_group, LEDGER_NAME_MAX);
1508		strlcpy(lti->lti_units, et->et_units, LEDGER_NAME_MAX);
1509		et++;
1510		lti++;
1511	}
1512	template_unlock(l->l_template);
1513
1514	return (0);
1515}
1516
1517static void
1518ledger_fill_entry_info(struct ledger_entry      *le,
1519                       struct ledger_entry_info *lei,
1520                       uint64_t                  now)
1521{
1522	assert(le  != NULL);
1523	assert(lei != NULL);
1524
1525	memset(lei, 0, sizeof (*lei));
1526
1527	lei->lei_limit         = le->le_limit;
1528	lei->lei_credit        = le->le_credit;
1529	lei->lei_debit         = le->le_debit;
1530	lei->lei_balance       = lei->lei_credit - lei->lei_debit;
1531	lei->lei_refill_period = (le->le_flags & LF_REFILL_SCHEDULED) ?
1532							     abstime_to_nsecs(le->_le.le_refill.le_refill_period) : 0;
1533	lei->lei_last_refill   = abstime_to_nsecs(now - le->_le.le_refill.le_last_refill);
1534}
1535
1536int
1537ledger_get_task_entry_info_multiple(task_t task, void **buf, int *len)
1538{
1539	struct ledger_entry_info *lei;
1540	struct ledger_entry *le;
1541	uint64_t now = mach_absolute_time();
1542	int i;
1543	ledger_t l;
1544
1545	if ((*len < 0) || ((l = task->ledger) == NULL))
1546		return (EINVAL);
1547
1548	if (*len > l->l_size)
1549		 *len = l->l_size;
1550	lei = kalloc((*len) * sizeof (struct ledger_entry_info));
1551	if (lei == NULL)
1552		return (ENOMEM);
1553	*buf = lei;
1554
1555	le = l->l_entries;
1556
1557	for (i = 0; i < *len; i++) {
1558		ledger_fill_entry_info(le, lei, now);
1559		le++;
1560		lei++;
1561	}
1562
1563	return (0);
1564}
1565
1566void
1567ledger_get_entry_info(ledger_t                  ledger,
1568                      int                       entry,
1569                      struct ledger_entry_info *lei)
1570{
1571	uint64_t now = mach_absolute_time();
1572
1573	assert(ledger != NULL);
1574	assert(lei != NULL);
1575	assert(entry < ledger->l_size);
1576
1577	struct ledger_entry *le = &ledger->l_entries[entry];
1578
1579	ledger_fill_entry_info(le, lei, now);
1580}
1581
1582int
1583ledger_info(task_t task, struct ledger_info *info)
1584{
1585	ledger_t l;
1586
1587	if ((l = task->ledger) == NULL)
1588		return (ENOENT);
1589
1590	memset(info, 0, sizeof (*info));
1591
1592	strlcpy(info->li_name, l->l_template->lt_name, LEDGER_NAME_MAX);
1593	info->li_id = l->l_id;
1594	info->li_entries = l->l_size;
1595	return (0);
1596}
1597
1598#ifdef LEDGER_DEBUG
1599int
1600ledger_limit(task_t task, struct ledger_limit_args *args)
1601{
1602	ledger_t l;
1603	int64_t limit;
1604	int idx;
1605
1606	if ((l = task->ledger) == NULL)
1607		return (EINVAL);
1608
1609	idx = ledger_key_lookup(l->l_template, args->lla_name);
1610	if ((idx < 0) || (idx >= l->l_size))
1611		return (EINVAL);
1612
1613	/*
1614	 * XXX - this doesn't really seem like the right place to have
1615	 * a context-sensitive conversion of userspace units into kernel
1616	 * units.  For now I'll handwave and say that the ledger() system
1617	 * call isn't meant for civilians to use - they should be using
1618	 * the process policy interfaces.
1619	 */
1620	if (idx == task_ledgers.cpu_time) {
1621		int64_t nsecs;
1622
1623		if (args->lla_refill_period) {
1624			/*
1625			 * If a refill is scheduled, then the limit is
1626			 * specified as a percentage of one CPU.  The
1627			 * syscall specifies the refill period in terms of
1628			 * milliseconds, so we need to convert to nsecs.
1629			 */
1630			args->lla_refill_period *= 1000000;
1631			nsecs = args->lla_limit *
1632			    (args->lla_refill_period / 100);
1633			lprintf(("CPU limited to %lld nsecs per second\n",
1634			    nsecs));
1635		} else {
1636			/*
1637			 * If no refill is scheduled, then this is a
1638			 * fixed amount of CPU time (in nsecs) that can
1639			 * be consumed.
1640			 */
1641			nsecs = args->lla_limit;
1642			lprintf(("CPU limited to %lld nsecs\n", nsecs));
1643		}
1644		limit = nsecs_to_abstime(nsecs);
1645	} else {
1646		limit = args->lla_limit;
1647		lprintf(("%s limited to %lld\n", args->lla_name, limit));
1648	}
1649
1650	if (args->lla_refill_period > 0)
1651		ledger_set_period(l, idx, args->lla_refill_period);
1652
1653	ledger_set_limit(l, idx, limit);
1654	flag_set(&l->l_entries[idx].le_flags, LEDGER_ACTION_BLOCK);
1655	return (0);
1656}
1657#endif
1658