#include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include #include #include #include #include #include #include #include #include #include #include extern "C" { int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); int APS5_VABI sceKernelClose(int); std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); } static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Positioned close check failed at line %d\n", line); std::abort(); } } #define Require(value) Check((value), __LINE__) static constexpr std::int64_t ErrorEbadf = static_cast(0x80020009u); int main() { const auto root = std::filesystem::path("anyps5-positioned-close-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); Require(std::filesystem::create_directory(root)); const auto path = (root / "data.bin").string(); constexpr std::size_t fileSize = 48u << 20; { std::ofstream stream(path, std::ios::binary); const std::vector block(1u << 20, 'x'); for (std::size_t written = 0; written < fileSize; written += block.size()) stream.write(block.data(), static_cast(block.size())); Require(stream.good()); } std::vector buffer(32u << 20); int overlapped = 0; for (int round = 0; round < 60; ++round) { const int descriptor = sceKernelOpen(path.c_str(), SCE_KERNEL_O_RDONLY, 0); Require(descriptor >= 0); std::atomic state{0}; std::atomic threw{false}; std::int64_t result = 0; std::thread reader([&] { state = 1; try { result = sceKernelPread(descriptor, buffer.data(), buffer.size(), 0); } catch (const std::exception&) { threw = true; } state = 2; }); while (state.load() == 0) std::this_thread::yield(); std::this_thread::sleep_for(std::chrono::microseconds(300)); const int closed = sceKernelClose(descriptor); reader.join(); Require(!threw.load()); Require(closed == 0); Require(result == static_cast(buffer.size()) || result == ErrorEbadf); if (result == static_cast(buffer.size())) ++overlapped; } Require(overlapped > 0); std::filesystem::remove_all(root); return 0; }