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