]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/sched_prim.c
xnu-2050.24.15.tar.gz
[apple/xnu.git] / osfmk / kern / sched_prim.c
index 5f4803119455b6a24e442ad9217f5fb42717f26a..eebc19bf5b613150da8e046c0e9f90d0460240a7 100644 (file)
@@ -165,6 +165,14 @@ uint32_t   sched_fixed_shift;
 
 static boolean_t sched_traditional_use_pset_runqueue = FALSE;
 
+/* Defaults for timer deadline profiling */
+#define TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT 2000000 /* Timers with deadlines <=
+                                                        * 2ms */
+#define TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT 5000000 /* Timers with deadlines
+                                                          <= 5ms */
+uint64_t timer_deadline_tracking_bin_1;
+uint64_t timer_deadline_tracking_bin_2;
+
 __attribute__((always_inline))
 static inline run_queue_t runq_for_processor(processor_t processor)
 {
@@ -309,6 +317,9 @@ sched_realtime_init(void)  __attribute__((section("__TEXT, initcode")));
 static void
 sched_realtime_timebase_init(void);
 
+static void
+sched_timer_deadline_tracking_init(void);
+
 #if defined(CONFIG_SCHED_TRADITIONAL)
 static void
 sched_traditional_tick_continue(void);
@@ -563,6 +574,7 @@ sched_init(void)
        SCHED(fairshare_init)();
        sched_realtime_init();
        ast_init();
+       sched_timer_deadline_tracking_init();
        
        SCHED(pset_init)(&pset0);
        SCHED(processor_init)(master_processor);
@@ -858,6 +870,7 @@ thread_unblock(
        wait_result_t   wresult)
 {
        boolean_t               result = FALSE;
+       thread_t                cthread = current_thread();
 
        /*
         *      Set wait_result.
@@ -924,6 +937,43 @@ thread_unblock(
        thread->computation_metered = 0;
        thread->reason = AST_NONE;
 
+       /* Obtain power-relevant interrupt and "platform-idle exit" statistics.
+        * We also account for "double hop" thread signaling via
+        * the thread callout infrastructure.
+        * DRK: consider removing the callout wakeup counters in the future
+        * they're present for verification at the moment.
+        */
+       boolean_t aticontext, pidle;
+       ml_get_power_state(&aticontext, &pidle);
+       if (__improbable(aticontext)) {
+               ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
+               uint64_t ttd = PROCESSOR_DATA(current_processor(), timer_call_ttd);
+               if (ttd) {
+                       if (ttd <= timer_deadline_tracking_bin_1)
+                               thread->thread_timer_wakeups_bin_1++;
+                       else
+                               if (ttd <= timer_deadline_tracking_bin_2)
+                                       thread->thread_timer_wakeups_bin_2++;
+               }
+               if (pidle) {
+                       ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
+               }
+       } else if (thread_get_tag_internal(cthread) & THREAD_TAG_CALLOUT) {
+               if (cthread->callout_woken_from_icontext) {
+                       ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
+                       thread->thread_callout_interrupt_wakeups++;
+                       if (cthread->callout_woken_from_platform_idle) {
+                               ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
+                               thread->thread_callout_platform_idle_wakeups++;
+                       }
+               }
+       }
+       
+       if (thread_get_tag_internal(thread) & THREAD_TAG_CALLOUT) {
+                       thread->callout_woken_from_icontext = aticontext;
+                       thread->callout_woken_from_platform_idle = pidle;
+       }
+
        /* Event should only be triggered if thread is not already running */
        if (result == FALSE) {
                KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
@@ -4039,8 +4089,12 @@ processor_idle(
                IDLE_KERNEL_DEBUG_CONSTANT(
                        MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), rt_runq.count, SCHED(processor_runq_count)(processor), -1, 0);
 
+               machine_track_platform_idle(TRUE);
+
                machine_idle();
 
+               machine_track_platform_idle(FALSE);
+
                (void)splsched();
 
                IDLE_KERNEL_DEBUG_CONSTANT(
@@ -4506,3 +4560,9 @@ thread_runnable(
        return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN);
 }
 #endif /* DEBUG */
+
+static void
+sched_timer_deadline_tracking_init(void) {
+       nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT, &timer_deadline_tracking_bin_1);
+       nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT, &timer_deadline_tracking_bin_2);
+}