X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..c7d2c2c6ee645e10cbccdd01c6191873ec77239d:/osfmk/kern/ledger.c diff --git a/osfmk/kern/ledger.c b/osfmk/kern/ledger.c index 13146ce6f..1f90ef24c 100644 --- a/osfmk/kern/ledger.c +++ b/osfmk/kern/ledger.c @@ -29,10 +29,11 @@ * @OSF_COPYRIGHT@ */ -#include +#include #include #include #include +#include #include #include @@ -54,23 +55,24 @@ #define LF_CALLED_BACK 0x1000 /* callback was called for balance in deficit */ #define LF_WARNED 0x2000 /* callback was called for balance warning */ #define LF_TRACKING_MAX 0x4000 /* track max balance over user-specfied time */ +#define LF_PANIC_ON_NEGATIVE 0x8000 /* panic if it goes negative */ /* Determine whether a ledger entry exists and has been initialized and active */ #define ENTRY_VALID(l, e) \ (((l) != NULL) && ((e) >= 0) && ((e) < (l)->l_size) && \ (((l)->l_entries[e].le_flags & LF_ENTRY_ACTIVE) == LF_ENTRY_ACTIVE)) +#define ASSERT(a) assert(a) + #ifdef LEDGER_DEBUG int ledger_debug = 0; -#define ASSERT(a) assert(a) #define lprintf(a) if (ledger_debug) { \ printf("%lld ", abstime_to_nsecs(mach_absolute_time() / 1000000)); \ printf a ; \ } #else #define lprintf(a) -#define ASSERT(a) #endif struct ledger_callback { @@ -321,7 +323,7 @@ ledger_key_lookup(ledger_template_t template, const char *key) template_lock(template); for (idx = 0; idx < template->lt_cnt; idx++) - if (template->lt_entries[idx].et_key && + if (template->lt_entries != NULL && (strcmp(key, template->lt_entries[idx].et_key) == 0)) break; @@ -650,7 +652,7 @@ ledger_refill(uint64_t now, ledger_t ledger, int entry) */ #define TOCKSTAMP_IS_STALE(now, tock) ((((now) - (tock)) < NTOCKS) ? FALSE : TRUE) -static void +void ledger_check_new_balance(ledger_t ledger, int entry) { struct ledger_entry *le; @@ -746,6 +748,12 @@ ledger_check_new_balance(ledger_t ledger, int entry) } } } + + if ((le->le_flags & LF_PANIC_ON_NEGATIVE) && + (le->le_credit < le->le_debit)) { + panic("ledger_check_new_balance(%p,%d): negative ledger %p balance:%lld\n", + ledger, entry, le, le->le_credit - le->le_debit); + } } /* @@ -773,6 +781,34 @@ ledger_credit(ledger_t ledger, int entry, ledger_amount_t amount) return (KERN_SUCCESS); } +/* Add all of one ledger's values into another. + * They must have been created from the same template. + * This is not done atomically. Another thread (if not otherwise synchronized) + * may see bogus values when comparing one entry to another. + * As each entry's credit & debit are modified one at a time, the warning/limit + * may spuriously trip, or spuriously fail to trip, or another thread (if not + * otherwise synchronized) may see a bogus balance. + */ +kern_return_t +ledger_rollup(ledger_t to_ledger, ledger_t from_ledger) +{ + int i; + struct ledger_entry *from_le, *to_le; + + assert(to_ledger->l_template == from_ledger->l_template); + + for (i = 0; i < to_ledger->l_size; i++) { + if (ENTRY_VALID(from_ledger, i) && ENTRY_VALID(to_ledger, i)) { + from_le = &from_ledger->l_entries[i]; + to_le = &to_ledger->l_entries[i]; + OSAddAtomic64(from_le->le_credit, &to_le->le_credit); + OSAddAtomic64(from_le->le_debit, &to_le->le_debit); + } + } + + return (KERN_SUCCESS); +} + /* * Zero the balance of a ledger by adding to its credit or debit, whichever is smaller. * Note that some clients of ledgers (notably, task wakeup statistics) require that @@ -921,6 +957,22 @@ ledger_track_maximum(ledger_template_t template, int entry, return (KERN_SUCCESS); } +kern_return_t +ledger_panic_on_negative(ledger_template_t template, int entry) +{ + template_lock(template); + + if ((entry < 0) || (entry >= template->lt_cnt)) { + template_unlock(template); + return (KERN_INVALID_VALUE); + } + + template->lt_entries[entry].et_flags |= LF_PANIC_ON_NEGATIVE; + + template_unlock(template); + + return (KERN_SUCCESS); +} /* * Add a callback to be executed when the resource goes into deficit. */ @@ -1099,29 +1151,6 @@ ledger_set_action(ledger_t ledger, int entry, int action) return (KERN_SUCCESS); } -void -set_astledger(thread_t thread) -{ - spl_t s = splsched(); - - if (thread == current_thread()) { - thread_ast_set(thread, AST_LEDGER); - ast_propagate(thread->ast); - } else { - processor_t p; - - thread_lock(thread); - thread_ast_set(thread, AST_LEDGER); - p = thread->last_processor; - if ((p != PROCESSOR_NULL) && (p->state == PROCESSOR_RUNNING) && - (p->active_thread == thread)) - cause_ast_check(p); - thread_unlock(thread); - } - - splx(s); -} - kern_return_t ledger_debit(ledger_t ledger, int entry, ledger_amount_t amount) { @@ -1377,6 +1406,36 @@ ledger_get_entries(ledger_t ledger, int entry, ledger_amount_t *credit, return (KERN_SUCCESS); } +kern_return_t +ledger_reset_callback_state(ledger_t ledger, int entry) +{ + struct ledger_entry *le; + + if (!ENTRY_VALID(ledger, entry)) + return (KERN_INVALID_ARGUMENT); + + le = &ledger->l_entries[entry]; + + flag_clear(&le->le_flags, LF_CALLED_BACK); + + return (KERN_SUCCESS); +} + +kern_return_t +ledger_disable_panic_on_negative(ledger_t ledger, int entry) +{ + struct ledger_entry *le; + + if (!ENTRY_VALID(ledger, entry)) + return (KERN_INVALID_ARGUMENT); + + le = &ledger->l_entries[entry]; + + flag_clear(&le->le_flags, LF_PANIC_ON_NEGATIVE); + + return (KERN_SUCCESS); +} + kern_return_t ledger_get_balance(ledger_t ledger, int entry, ledger_amount_t *balance) {