mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-21 16:12:47 -05:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
3.0 KiB
C++
74 lines
3.0 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
struct GuestTimeval {
|
|
std::int64_t seconds;
|
|
std::int64_t microseconds;
|
|
};
|
|
|
|
extern "C" {
|
|
int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*);
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
|
|
static void Require(bool value, const char* message) {
|
|
if (!value) {
|
|
std::fprintf(stderr, "%s\n", message);
|
|
std::abort();
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
using Clock = std::chrono::steady_clock;
|
|
for (const std::int64_t micros : {0, 50, 500, 1000, 2000, 16667}) {
|
|
const GuestTimeval limit{0, micros};
|
|
for (const int count : {0, 1024}) {
|
|
const auto start = Clock::now();
|
|
Require(select_nid_postfix(count, nullptr, nullptr, nullptr, &limit) == 0,
|
|
"select without descriptors did not time out");
|
|
Require(Clock::now() - start >= std::chrono::microseconds(micros),
|
|
"select returned before its deadline");
|
|
Require(limit.seconds == 0 && limit.microseconds == micros,
|
|
"select changed the guest timeout");
|
|
}
|
|
}
|
|
const GuestTimeval shortLimit{0, 1000};
|
|
const auto shortWaitStart = Clock::now();
|
|
for (int i = 0; i < 20; ++i) {
|
|
Require(select_nid_postfix(0, nullptr, nullptr, nullptr, &shortLimit) == 0,
|
|
"repeated select without descriptors did not time out");
|
|
}
|
|
const auto shortWait = Clock::now() - shortWaitStart;
|
|
Require(shortWait >= std::chrono::milliseconds(20) && shortWait < std::chrono::milliseconds(200),
|
|
"twenty 1 ms selects did not stay close to their deadlines");
|
|
for (const GuestTimeval limit : {GuestTimeval{-1, 0}, GuestTimeval{0, -1}, GuestTimeval{0, 1000000}}) {
|
|
Require(select_nid_postfix(0, nullptr, nullptr, nullptr, &limit) == -1 && *__error_nid_postfix() == 22,
|
|
"select accepted an invalid timeout");
|
|
}
|
|
const GuestTimeval zero{};
|
|
for (const int count : {-1, 1025}) {
|
|
Require(select_nid_postfix(count, nullptr, nullptr, nullptr, &zero) == -1 && *__error_nid_postfix() == 22,
|
|
"select accepted an invalid descriptor limit");
|
|
}
|
|
std::array<std::uint64_t, 16> read{};
|
|
read[0] = 1 | (std::uint64_t{1} << 63);
|
|
const GuestTimeval limit{0, 500};
|
|
const auto start = Clock::now();
|
|
Require(select_nid_postfix(1, read.data(), nullptr, nullptr, &limit) == 0,
|
|
"select with no ready device did not time out");
|
|
Require(Clock::now() - start >= std::chrono::microseconds(limit.microseconds),
|
|
"select with no ready device returned before its deadline");
|
|
Require(read[0] == (std::uint64_t{1} << 63),
|
|
"select did not preserve bits outside the descriptor limit");
|
|
std::array<std::uint64_t, 16> write{};
|
|
write[0] = 2;
|
|
const GuestTimeval longLimit{1, 0};
|
|
Require(select_nid_postfix(2, nullptr, write.data(), nullptr, &longLimit) == 1 && write[0] == 2,
|
|
"select did not report a ready device");
|
|
std::puts("20 select wait scenarios passed");
|
|
}
|