#ifndef KTRACE_HELPERS_H #define KTRACE_HELPERS_H #include #include #include #include #include static inline void reset_ktrace(void) { (void)sysctl((int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDREMOVE }, 3, NULL, 0, NULL, 0); kperf_reset(); } static inline void start_controlling_ktrace(void) { T_SETUPBEGIN; int state = 0; size_t statesz = sizeof(state); int ret = sysctlbyname("ktrace.state", &state, &statesz, NULL, 0); T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "getting ktrace state"); if (state == 1) { int ownerpid = 0; size_t pidsz = sizeof(ownerpid); ret = sysctlbyname("ktrace.owning_pid", &ownerpid, &pidsz, NULL, 0); T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "getting owning pid"); if (ownerpid <= 0) { T_LOG("ktrace is in foreground, but no owner"); goto out; } char ownername[1024]; ret = proc_name(ownerpid, ownername, sizeof(ownername)); if (ret == 0) { T_LOG("ktrace is in foreground, but owner (%d) has no name", ownerpid); goto out; } T_LOG("ktrace is in foreground, owned by %s, sending SIGKILL", ownername); kill(ownerpid, SIGKILL); usleep(500000); ret = proc_name(ownerpid, ownername, sizeof(ownername)); T_QUIET; T_ASSERT_EQ(ret, 0, "should have killed ktrace owner"); } out: reset_ktrace(); T_ATEND(reset_ktrace); T_SETUPEND; } static inline void assert_kdebug_test(kdebug_test_t flavor, const char *msg) { size_t size = flavor; int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDTEST }; T_ASSERT_POSIX_SUCCESS(sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &size, NULL, 0), "KERN_KDTEST %d: %s", flavor, msg); } static inline uint64_t ns_from_abs(ktrace_session_t s, uint64_t abstime) { uint64_t ns = 0; int error = ktrace_convert_timestamp_to_nanoseconds(s, abstime, &ns); T_QUIET; T_ASSERT_POSIX_ZERO(error, "convert abstime to nanoseconds"); return ns; } static inline uint64_t relns_from_abs(ktrace_session_t s, uint64_t abstime) { return ns_from_abs(s, abstime - ktrace_get_earliest_timestamp(s)); } #endif /* !defined(KTRACE_HELPERS_H) */