]> git.saurik.com Git - apple/xnu.git/blobdiff - tests/telemetry.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tests / telemetry.c
index 810dcf2d8ed4f952e6d803d1f16bd13b3e3159ad..68d99ad9444a55c41915bc234d0d9deee96b7b42 100644 (file)
@@ -4,11 +4,15 @@
 #include <darwintest.h>
 #include <dispatch/dispatch.h>
 #include <ktrace/ktrace.h>
+#include <kperf/kperf.h>
 #include <kern/debug.h>
 #include <notify.h>
 #include <sys/kdebug.h>
+#include <sys/sysctl.h>
 #include <TargetConditionals.h>
 
+#include "ktrace_helpers.h"
+
 enum telemetry_pmi {
        TELEMETRY_PMI_NONE,
        TELEMETRY_PMI_INSTRS,
@@ -23,6 +27,26 @@ T_GLOBAL_META(T_META_NAMESPACE("xnu.debugging.telemetry"),
 extern int __telemetry(uint64_t cmd, uint64_t deadline, uint64_t interval,
     uint64_t leeway, uint64_t arg4, uint64_t arg5);
 
+/*
+ * Microstackshots based on PMI are only supported on devices with monotonic
+ * support.
+ */
+
+static void
+skip_if_pmi_unsupported(void)
+{
+       int supported = 0;
+       int ret = sysctlbyname("kern.monotonic.supported", &supported,
+           &(size_t){ sizeof(supported), }, NULL, 0);
+       if (ret < 0) {
+               T_SKIP("monotonic sysctl generated an error: %d (%s)", errno,
+                   strerror(errno));
+       }
+       if (!supported) {
+               T_SKIP("monotonic must be supported for microstackshots");
+       }
+}
+
 /*
  * Data Analytics (da) also has a microstackshot configuration -- set a PMI
  * cycle interval of 0 to force it to disable microstackshot on PMI.
@@ -50,7 +74,11 @@ disable_da_microstackshots(void)
        CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt64Type, &zero);
        set_da_microstackshot_period(num);
        T_LOG("notified da of tasking change, sleeping");
+#if TARGET_OS_WATCH
+       sleep(8);
+#else /* TARGET_OS_WATCH */
        sleep(3);
+#endif /* !TARGET_OS_WATCH */
 }
 
 /*
@@ -68,8 +96,7 @@ reenable_da_microstackshots(void)
 static void
 telemetry_cleanup(void)
 {
-       int ret = __telemetry(TELEMETRY_CMD_PMI_SETUP, TELEMETRY_PMI_NONE, 0, 0, 0, 0);
-       T_EXPECT_POSIX_SUCCESS(ret, "telemetry(... NONE ...)");
+       (void)__telemetry(TELEMETRY_CMD_PMI_SETUP, TELEMETRY_PMI_NONE, 0, 0, 0, 0);
        reenable_da_microstackshots();
 }
 
@@ -107,9 +134,8 @@ thread_spin(__unused void *arg)
 
 T_DECL(microstackshot_pmi, "attempt to configure microstackshots on PMI")
 {
-#if TARGET_OS_WATCH
-       T_SKIP("unsupported platform");
-#endif /* TARGET_OS_WATCH */
+       skip_if_pmi_unsupported();
+       start_controlling_ktrace();
 
        T_SETUPBEGIN;
        ktrace_session_t s = ktrace_session_create();
@@ -122,6 +148,7 @@ T_DECL(microstackshot_pmi, "attempt to configure microstackshots on PMI")
        __block int interrupt_records = 0;
        __block int timer_arm_records = 0;
        __block int unknown_records = 0;
+       __block int empty_records = 0;
 
        ktrace_events_single(s, MT_MICROSTACKSHOT, ^(__unused struct trace_point *tp) {
                pmi_events++;
@@ -141,6 +168,14 @@ T_DECL(microstackshot_pmi, "attempt to configure microstackshots on PMI")
                        timer_arm_records++;
                }
 
+               if (start->arg2 == end->arg2) {
+                       /*
+                        * The buffer didn't grow for this record -- there was
+                        * an error.
+                        */
+                       empty_records++;
+               }
+
                const uint8_t any_record = kPMIRecord | kIORecord | kInterruptRecord |
                kTimerArmingRecord;
                if ((start->arg1 & any_record) == 0) {
@@ -158,8 +193,11 @@ T_DECL(microstackshot_pmi, "attempt to configure microstackshots on PMI")
                pmi_records / (double)SLEEP_SECS);
                T_EXPECT_EQ(unknown_records, 0, "saw zero unknown record events");
                T_EXPECT_GT(microstackshot_record_events, 0,
-               "saw non-zero microstackshot record events (%g/sec)",
+               "saw non-zero microstackshot record events (%d -- %g/sec)",
+               microstackshot_record_events,
                microstackshot_record_events / (double)SLEEP_SECS);
+               T_EXPECT_NE(empty_records, microstackshot_record_events,
+               "saw non-empty records (%d empty)", empty_records);
 
                if (interrupt_records > 0) {
                        T_LOG("saw %g interrupt records per second",
@@ -216,6 +254,8 @@ T_DECL(microstackshot_pmi, "attempt to configure microstackshots on PMI")
 T_DECL(error_handling,
     "ensure that error conditions for the telemetry syscall are observed")
 {
+       skip_if_pmi_unsupported();
+
        telemetry_init();
 
        int ret = __telemetry(TELEMETRY_CMD_PMI_SETUP, TELEMETRY_PMI_INSTRS,