mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 08:33:12 -05:00
A shared mapping is a view of a file section created on the descriptor's handle, read-write when the descriptor is, otherwise read-only. A private mapping is a copy of the file read at mmap, as POSIX allows. Anonymous shm_open objects and JIT shared memory descriptors are temporary files on Windows, so mmap now maps them too (it failed with EOPNOTSUPP before). mprotect of a mapped view above the view's protection fails with EACCES before any bookkeeping changes. The cases Windows cannot represent are listed in the libkernel debt. Dusklight (PPSA99305) uses SQLite in WAL mode, which maps its -shm file. On Windows mainf0634088bevery start logged "Failed to start transaction: disk I/O error" for its Dawn and pipeline caches (3 of 3 runs); with this change the caches initialise and their WAL files fill (4 of 4 runs). The title reaches its menu either way. A shared mapping may end inside the 16 KiB page that holds the end of the file, as POSIX mmap allows: the view ends with the file's last 4 KiB host page, which Windows zero-fills past the end, the rest of the guest page is private zero pages, and the file never grows. A mapping that reaches a whole page past the end still fails with EOPNOTSUPP. PS5LM Plus (PPSA99581) loads its model with llama.cpp, which maps the whole GGUF file shared and read-only. With a 491,400,032-byte model, Windows main5de7a46e0and this change without the last page logged "llama_model_load: error loading model: mmap failed: Operation not supported" (3 of 3 runs); now the model loads and the completion of "The capital of France is" starts with " Paris" (3 of 3 runs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
3.4 KiB
C++
74 lines
3.4 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <stdexcept>
|
|
extern "C" {
|
|
int APS5_VABI shm_open_nid_postfix(const char*, int, int);
|
|
int APS5_VABI ftruncate_nid_postfix(int, std::int64_t);
|
|
std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t);
|
|
std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t);
|
|
int APS5_VABI close_nid_postfix(int);
|
|
void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept;
|
|
int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept;
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
static const char* const anonymous = reinterpret_cast<const char*>(1);
|
|
static void RequireInvalid(const char* path, int flags) {
|
|
*__error_nid_postfix() = 0;
|
|
Require(shm_open_nid_postfix(path, flags, 0600) == -1);
|
|
Require(*__error_nid_postfix() == 22);
|
|
}
|
|
int main() {
|
|
*__error_nid_postfix() = 13;
|
|
const int first = shm_open_nid_postfix(anonymous, 0x100202, 0600);
|
|
const int second = shm_open_nid_postfix(anonymous, 0x2, 0);
|
|
const int third = shm_open_nid_postfix(anonymous, 0x100e02, 0400);
|
|
Require(first >= 0 && second >= 0 && third >= 0);
|
|
Require(first != second && second != third && first != third);
|
|
Require(*__error_nid_postfix() == 13);
|
|
Require(ftruncate_nid_postfix(first, 0x4000) == 0);
|
|
const char text[] = "anonymous";
|
|
Require(pwrite_nid_disambig1_nid_postfix(first, text, sizeof(text), 0x1000) == static_cast<std::int64_t>(sizeof(text)));
|
|
char back[sizeof(text)] = {};
|
|
Require(pread_nid_postfix(first, back, sizeof(back), 0x1000) == static_cast<std::int64_t>(sizeof(back)));
|
|
Require(std::memcmp(back, text, sizeof(text)) == 0);
|
|
char last = 1;
|
|
Require(pread_nid_postfix(first, &last, 1, 0x3fff) == 1 && last == 0);
|
|
Require(pread_nid_postfix(first, &last, 1, 0x4000) == 0);
|
|
Require(pread_nid_postfix(second, back, sizeof(back), 0) == 0);
|
|
auto* view = static_cast<volatile char*>(mmap_nid_postfix(nullptr, 0x4000, 3, 0x1, first, 0));
|
|
Require(view != reinterpret_cast<void*>(static_cast<std::uintptr_t>(-1)));
|
|
Require(view[0x1000] == 'a' && view[0x3fff] == 0);
|
|
view[0x2000] = 'm';
|
|
Require(pread_nid_postfix(first, &last, 1, 0x2000) == 1 && last == 'm');
|
|
Require(munmap_nid_postfix(const_cast<char*>(view), 0x4000) == 0);
|
|
#ifndef _WIN32
|
|
Require(pwrite_nid_disambig1_nid_postfix(third, text, sizeof(text), 0) == 0);
|
|
#endif
|
|
Require(ftruncate_nid_postfix(third, 0x4000) == 0);
|
|
Require(pwrite_nid_disambig1_nid_postfix(third, text, sizeof(text), 0) == static_cast<std::int64_t>(sizeof(text)));
|
|
Require(close_nid_postfix(first) == 0 && close_nid_postfix(second) == 0 && close_nid_postfix(third) == 0);
|
|
RequireInvalid(anonymous, 0x0);
|
|
RequireInvalid(anonymous, 0x200);
|
|
RequireInvalid(anonymous, 0x1);
|
|
RequireInvalid(anonymous, 0x3);
|
|
RequireInvalid(anonymous, 0x2 | 0x8);
|
|
RequireInvalid(anonymous, 0x2 | 0x4);
|
|
RequireInvalid("/anyps5-shm", 0x1);
|
|
RequireInvalid("/anyps5-shm", 0x202 | 0x8);
|
|
#ifdef _WIN32
|
|
bool threw = false;
|
|
try {
|
|
shm_open_nid_postfix("/anyps5-shm", 0x202, 0600);
|
|
} catch (const std::runtime_error&) {
|
|
threw = true;
|
|
}
|
|
Require(threw);
|
|
#else
|
|
RequireInvalid("", 0x202);
|
|
#endif
|
|
}
|