mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
74 lines
3.2 KiB
C++
74 lines
3.2 KiB
C++
#include "prx/libkernel/KernelErrors.hpp"
|
|
#include "prx/libkernel/include/Api.hpp"
|
|
#include "SceTypes.hpp"
|
|
#include <atomic>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <thread>
|
|
|
|
static constexpr int SCE_OK = 0;
|
|
static constexpr int GUEST_ESRCH = 3;
|
|
static constexpr std::size_t REUSED_SLOT_ROUNDS = 64;
|
|
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
static void* APS5_VABI Finish(void*) {
|
|
return reinterpret_cast<void*>(std::uintptr_t{0x1234});
|
|
}
|
|
|
|
static void* APS5_VABI WaitForRelease(void* arg) {
|
|
auto* release = static_cast<std::atomic<bool>*>(arg);
|
|
while (!release->load()) std::this_thread::yield();
|
|
return nullptr;
|
|
}
|
|
|
|
int main() {
|
|
Pthread thread = nullptr;
|
|
void* result = nullptr;
|
|
Require(scePthreadCreate(&thread, nullptr, Finish, nullptr, "second-join") == SCE_OK);
|
|
Require(scePthreadJoin(thread, &result) == SCE_OK);
|
|
Require(result == reinterpret_cast<void*>(std::uintptr_t{0x1234}));
|
|
|
|
result = reinterpret_cast<void*>(std::uintptr_t{0x55});
|
|
Require(scePthreadJoin(thread, &result) == SCE_KERNEL_ERROR_ESRCH);
|
|
Require(result == reinterpret_cast<void*>(std::uintptr_t{0x55}));
|
|
Require(scePthreadDetach(thread) == SCE_KERNEL_ERROR_ESRCH);
|
|
Require(pthread_join_nid_postfix(thread, &result) == GUEST_ESRCH);
|
|
Require(result == reinterpret_cast<void*>(std::uintptr_t{0x55}));
|
|
|
|
for (std::size_t round = 0; round < REUSED_SLOT_ROUNDS; ++round) {
|
|
thread = nullptr;
|
|
result = nullptr;
|
|
Require(scePthreadCreate(&thread, nullptr, Finish, nullptr, "reused-slot") == SCE_OK);
|
|
Require(scePthreadJoin(thread, &result) == SCE_OK);
|
|
Require(result == reinterpret_cast<void*>(std::uintptr_t{0x1234}));
|
|
Require(scePthreadJoin(thread, nullptr) == SCE_KERNEL_ERROR_ESRCH);
|
|
}
|
|
|
|
static std::atomic<bool> release{false};
|
|
Pthread detached = nullptr;
|
|
Require(scePthreadCreate(&detached, nullptr, WaitForRelease, &release, "detached") == SCE_OK);
|
|
Require(scePthreadDetach(detached) == SCE_OK);
|
|
result = reinterpret_cast<void*>(std::uintptr_t{0x55});
|
|
Require(scePthreadJoin(detached, &result) == SCE_KERNEL_ERROR_EINVAL);
|
|
Require(result == reinterpret_cast<void*>(std::uintptr_t{0x55}));
|
|
Require(scePthreadDetach(detached) == SCE_KERNEL_ERROR_EINVAL);
|
|
release = true;
|
|
|
|
Pthread named = nullptr;
|
|
char name[64] = {};
|
|
Require(scePthreadCreate(&named, nullptr, Finish, nullptr, "0123456789abcdefghijklmnopqrstu") == SCE_OK);
|
|
Require(scePthreadGetname(named, name) == SCE_OK && std::strcmp(name, "0123456789abcdefghijklmnopqrstu") == 0);
|
|
Require(scePthreadJoin(named, nullptr) == SCE_OK);
|
|
Pthread untouched = reinterpret_cast<Pthread>(std::uintptr_t{0x77});
|
|
Require(scePthreadCreate(&untouched, nullptr, Finish, nullptr, "0123456789abcdefghijklmnopqrstuv") == SCE_KERNEL_ERROR_ENAMETOOLONG);
|
|
Require(untouched == reinterpret_cast<Pthread>(std::uintptr_t{0x77}));
|
|
Pthread unnamed = nullptr;
|
|
std::memset(name, 'x', sizeof(name));
|
|
Require(scePthreadCreate(&unnamed, nullptr, Finish, nullptr, nullptr) == SCE_OK);
|
|
Require(scePthreadGetname(unnamed, name) == SCE_OK && name[0] == 0);
|
|
Require(scePthreadJoin(unnamed, nullptr) == SCE_OK);
|
|
}
|