// Kernel statistics ABI smoke test. // Verifies size queries, trailing CPU records, and generic filesystem stats. #include #include #include #include static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } static void print_u64(uint64_t v) { char buf[32]; int i = 0; if (v == 0) { print("0"); return; } while (v && i < (int)sizeof(buf)) { buf[i++] = (char)('0' + (v % 10)); v /= 10; } while (i--) { char c = buf[i]; SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } } static void exit_now(int code) { while (true) SysExitProcess(code); } static void fail(const char* what) { print("stats_abi_smoke: "); print(what); print("\n"); exit_now(1); } static void fail_status(const char* what, KSTATUS status) { print("stats_abi_smoke: "); print(what); print(" status="); print_u64(status); print("\n"); exit_now(1); } // Requires one exact status value. static void expect_status(const char* what, uint32_t got, uint32_t expected) { if (got == expected) return; print("stats_abi_smoke: "); print(what); print(" got="); print_u64(got); print(" expected="); print_u64(expected); print("\n"); exit_now(1); } // Verifies fixed-size stats classes report and fill their public header. static void check_fixed_stats(void) { size_t required = 0; KSTATUS status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, 0, 0, &required); if (status != NTLSTATUS_SUCCESS) fail_status("scheduler size", status); if (required != sizeof(SYS_SCHEDULER_STATS)) fail("scheduler required size mismatch"); uint8_t small[sizeof(SYS_SCHEDULER_STATS) - 1u]; size_t smallRequired = 0; status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, small, sizeof(small), &smallRequired); expect_status("scheduler small buffer", status, NTLSTATUS_BUFFER_TOO_SMALL); if (smallRequired != sizeof(SYS_SCHEDULER_STATS)) fail("scheduler small required mismatch"); SYS_SCHEDULER_STATS scheduler; status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, &scheduler, sizeof(scheduler), 0); if (status != NTLSTATUS_SUCCESS) fail_status("scheduler exact", status); if (scheduler.Size != sizeof(scheduler)) fail("scheduler size field mismatch"); if (scheduler.Version != SYS_STATS_VERSION) fail("scheduler version mismatch"); SYS_FILESYSTEM_STATS filesystem; status = SysQueryKernelStats(SYS_KERNEL_STATS_FILESYSTEM, &filesystem, sizeof(filesystem), 0); if (status != NTLSTATUS_SUCCESS) fail_status("filesystem exact", status); if (filesystem.Size != sizeof(filesystem)) fail("filesystem size field mismatch"); if (filesystem.Version != SYS_STATS_VERSION) fail("filesystem version mismatch"); SYS_VOLUME_STATS volumeStats; status = SysQueryKernelStats(SYS_KERNEL_STATS_VOLUME, &volumeStats, sizeof(volumeStats), 0); if (status != NTLSTATUS_SUCCESS) fail_status("volume exact", status); if (volumeStats.Size != sizeof(volumeStats)) fail("volume size field mismatch"); if (volumeStats.Version != SYS_STATS_VERSION) fail("volume version mismatch"); if (volumeStats.CreatedVolumes == 0) fail("volume created count is zero"); if (volumeStats.MountedVolumes == 0) fail("volume mounted count is zero"); if (volumeStats.ProviderDestroys > volumeStats.RemovedVolumes) fail("volume destroy count exceeds removals"); SYS_VOLUME_MANAGER_STATS volumeManagerStats; status = SysQueryKernelStats(SYS_KERNEL_STATS_VOLUME_MANAGER, &volumeManagerStats, sizeof(volumeManagerStats), 0); if (status != NTLSTATUS_SUCCESS) fail_status("volume manager exact", status); if (volumeManagerStats.Size != sizeof(volumeManagerStats)) fail("volume manager size field mismatch"); if (volumeManagerStats.Version != SYS_STATS_VERSION) fail("volume manager version mismatch"); if (volumeManagerStats.Snapshots == 0) fail("volume manager snapshot count is zero"); if (volumeManagerStats.VolumeOpens == 0) fail("volume manager open count is zero"); SYS_EXCEPTION_STATS exceptionStats; status = SysQueryKernelStats(SYS_KERNEL_STATS_EXCEPTION, &exceptionStats, sizeof(exceptionStats), 0); if (status != NTLSTATUS_SUCCESS) fail_status("exception exact", status); if (exceptionStats.Size != sizeof(exceptionStats)) fail("exception size field mismatch"); if (exceptionStats.Version != SYS_STATS_VERSION) fail("exception version mismatch"); SYS_PORT_STATS portStats; status = SysQueryKernelStats(SYS_KERNEL_STATS_PORT, &portStats, sizeof(portStats), 0); if (status != NTLSTATUS_SUCCESS) fail_status("port exact", status); if (portStats.Size != sizeof(portStats)) fail("port size field mismatch"); if (portStats.Version != SYS_STATS_VERSION) fail("port version mismatch"); } // Verifies CPU stats use a size-reported trailing-record layout. static void check_cpu_stats(void) { size_t required = 0; KSTATUS status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, 0, 0, &required); if (status != NTLSTATUS_SUCCESS) fail_status("cpu size", status); if (required < sizeof(SYS_CPU_STATS) + sizeof(SYS_CPU_STAT)) fail("cpu required size too small"); SYS_CPU_STATS headerOnly; size_t smallRequired = 0; status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, &headerOnly, sizeof(headerOnly), &smallRequired); expect_status("cpu header-only buffer", status, NTLSTATUS_BUFFER_TOO_SMALL); if (smallRequired != required) fail("cpu small required mismatch"); void* buffer = 0; size_t pages = (required + 4095u) / 4096u; if (pages == 0) pages = 1; SYS_ALLOC_VM_REQUEST allocReq; memset(&allocReq, 0, sizeof(allocReq)); allocReq.Size = sizeof(allocReq); allocReq.PageCount = pages; allocReq.Protect = SYS_VM_READWRITE; allocReq.Flags = SYS_VM_FLAG_NONE; allocReq.BaseOut = &buffer; status = SysAllocVm(&allocReq); if (status != NTLSTATUS_SUCCESS || !buffer) fail_status("cpu buffer alloc", status); SYS_CPU_STATS* cpu = (SYS_CPU_STATS*)buffer; status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, cpu, pages * 4096u, 0); if (status != NTLSTATUS_SUCCESS) { SysFreeVm(buffer); fail_status("cpu exact", status); } if (cpu->Size != required) fail("cpu size field mismatch"); if (cpu->Version != SYS_STATS_VERSION) fail("cpu version mismatch"); if (cpu->HeaderSize != sizeof(SYS_CPU_STATS)) fail("cpu header size mismatch"); if (cpu->RecordSize != sizeof(SYS_CPU_STAT)) fail("cpu record size mismatch"); if (cpu->RecordCount == 0 || cpu->RecordCount > cpu->CpuCount) fail("cpu record count mismatch"); const SYS_CPU_STAT* records = SYS_CPU_STATS_CONST_RECORDS(cpu); if (records[0].CpuIndex >= cpu->CpuCount) fail("cpu first record index mismatch"); SysFreeVm(buffer); } // Runs the stats ABI smoke test. int main(void) { print("stats_abi_smoke: start\n"); check_fixed_stats(); check_cpu_stats(); print("stats_abi_smoke: PASS\n"); exit_now(0); return 0; }