Merge pull request #877 from adriadam10/feat/kernel-getrusage-thread
feat(kernel): support getrusage RUSAGE_THREAD on Linux
This commit is contained in:
commit
37a1e75f2c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue