#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include #include #include namespace { constexpr int Einval = 22; constexpr int SigBlock = 1; constexpr int SigSetmask = 3; constexpr int SigUsr1 = 30; struct Timespec { std::int64_t seconds; std::int64_t nanoseconds; }; struct SignalSet { std::uint32_t bits[4]{}; }; struct DescriptorSet { std::array words{}; void Add(int descriptor) { words[descriptor / 64] |= std::uint64_t{1} << (descriptor % 64); } bool Has(int descriptor) const { return ((words[descriptor / 64] >> (descriptor % 64)) & 1u) != 0; } }; void Require(bool condition, std::source_location location = std::source_location::current()) { if (condition) return; std::fprintf(stderr, "check failed at line %u\n", static_cast(location.line())); std::exit(1); } int Error() { return *__error_nid_postfix(); } SignalSet CurrentMask() { SignalSet current{}; Require(sigprocmask_nid_postfix(SigBlock, nullptr, ¤t) == 0); return current; } bool Same(const SignalSet& left, const SignalSet& right) { return std::memcmp(left.bits, right.bits, sizeof(left.bits)) == 0; } } int main() { int descriptors[2]{-1, -1}; Require(pipe_nid_postfix(descriptors) == 0); const int reader = descriptors[0]; const int writer = descriptors[1]; SignalSet blocked{}; blocked.bits[(SigUsr1 - 1) / 32] |= 1u << ((SigUsr1 - 1) % 32); const SignalSet before = CurrentMask(); { DescriptorSet read{}; read.Add(reader); const Timespec limit{0, 200000000}; const auto start = std::chrono::steady_clock::now(); Require(pselect_nid_postfix(reader + 1, read.words.data(), nullptr, nullptr, &limit, &blocked) == 0); Require(std::chrono::steady_clock::now() - start >= std::chrono::milliseconds(150)); Require(!read.Has(reader)); Require(Same(CurrentMask(), before)); } Require(write_nid_postfix(writer, "x", 1) == 1); { DescriptorSet read{}; read.Add(reader); const Timespec limit{0, 999999999}; Require(pselect_nid_postfix(reader + 1, read.words.data(), nullptr, nullptr, &limit, nullptr) == 1); Require(read.Has(reader)); } { DescriptorSet read{}; read.Add(reader); Require(pselect_nid_postfix(reader + 1, read.words.data(), nullptr, nullptr, nullptr, &blocked) == 1); Require(read.Has(reader)); Require(Same(CurrentMask(), before)); } { const Timespec invalid{0, 1000000000}; Require(pselect_nid_postfix(0, nullptr, nullptr, nullptr, &invalid, &blocked) == -1 && Error() == Einval); Require(Same(CurrentMask(), before)); const Timespec zero{0, 0}; Require(pselect_nid_postfix(-1, nullptr, nullptr, nullptr, &zero, nullptr) == -1 && Error() == Einval); } Require(sigprocmask_nid_postfix(SigSetmask, &before, nullptr) == 0); Require(close_nid_postfix(reader) == 0 && close_nid_postfix(writer) == 0); std::puts("pselect passed"); return 0; }