Merge pull request #877 from adriadam10/feat/kernel-getrusage-thread

feat(kernel): support getrusage RUSAGE_THREAD on Linux
This commit is contained in:
Dean 2026-10-07 10:11:00 +13:00 committed by GitHub
commit 37a1e75f2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 3 deletions

View File

@ -303,6 +303,16 @@ if(BUILD_TESTING)
set_tests_properties(guest_available_cpumask PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_getrusage_tests ${LIBS_INCLUDE_DIR}/tests/GuestGetrusage.cpp)
target_include_directories(guest_getrusage_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_getrusage_tests PRIVATE libkernel libc)
configure_windows_unwind(guest_getrusage_tests)
add_test(NAME guest_getrusage COMMAND guest_getrusage_tests)
set_tests_properties(guest_getrusage PROPERTIES TIMEOUT 20)
if(WIN32)
set_tests_properties(guest_getrusage PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_kernel_error_tests ${LIBS_INCLUDE_DIR}/tests/GuestKernelErrors.cpp)
target_include_directories(guest_kernel_error_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_kernel_error_tests PRIVATE libkernel libc)

View File

@ -290,10 +290,8 @@ int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) {
usage->ru_nvcsw = 0;
usage->ru_nivcsw = 0;
#else
if (who == 1)
throw std::invalid_argument("getrusage: RUSAGE_THREAD is not supported on this platform");
struct rusage native{};
if (::getrusage(RUSAGE_SELF, &native) != 0)
if (::getrusage(who == 0 ? RUSAGE_SELF : RUSAGE_THREAD, &native) != 0)
throw std::system_error(errno, std::generic_category(), "getrusage: getrusage failed");
usage->ru_utime.tv_sec = static_cast<std::int64_t>(native.ru_utime.tv_sec);
usage->ru_utime.tv_usec = static_cast<std::int64_t>(native.ru_utime.tv_usec);

View File

@ -0,0 +1,42 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <thread>
struct Timeval {
std::int64_t tv_sec;
std::int64_t tv_usec;
};
struct ResourceUsage {
Timeval ru_utime;
Timeval ru_stime;
std::int64_t rest[14];
};
extern "C" int APS5_VABI getrusage_nid_postfix(int who, ResourceUsage* usage);
static void Require(bool value) { if (!value) std::abort(); }
static std::int64_t CpuMicros(int who) {
ResourceUsage usage{};
Require(getrusage_nid_postfix(who, &usage) == 0);
return (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000 + usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
}
static void SpinUntil(int who, std::int64_t micros) {
const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(10);
volatile std::uint64_t sink = 0;
while (CpuMicros(who) < micros) {
for (int i = 0; i < 100000; ++i) sink = sink + i;
Require(std::chrono::steady_clock::now() < deadline);
}
}
int main() {
SpinUntil(0, 400000);
const std::int64_t mainThread = CpuMicros(1);
Require(mainThread >= 200000);
std::thread worker([] {
const std::int64_t fresh = CpuMicros(1);
Require(fresh < 100000);
SpinUntil(1, fresh + 100000);
Require(CpuMicros(0) >= CpuMicros(1) + 300000);
});
worker.join();
Require(CpuMicros(0) >= 500000);
}