mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 12:05:06 +00:00
The SCE name moves from a libkernel_sys stub to libkernel. Kinds MutexType::ErrorCheck (1) to MutexType::Adaptive (4) are the mutex types FreeBSD 11 libthr's pthread_mutexattr_setkind_np stores, and are set through scePthreadMutexattrSettype, which maps the same values onto those types. Other kinds and a null or uninitialized attribute throw, as their console answer is not known. guest_kernel_sys_pthread_np_kind round-trips kinds 2, 3, 4 and 1 through pthread_mutexattr_gettype, checks that kind 1 makes a second lock return EDEADLK and kind 2 lets it succeed, and checks the throws for kinds 0, 5 and -1 (the type unchanged) and for a destroyed or null attribute.
116 lines
5.0 KiB
C++
116 lines
5.0 KiB
C++
#include "SceTypes.hpp"
|
|
#include <cstdio>
|
|
#include <exception>
|
|
#include <initializer_list>
|
|
#include <stdexcept>
|
|
#include <string_view>
|
|
|
|
extern "C" {
|
|
int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadMutexattr* attr);
|
|
int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex);
|
|
int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex);
|
|
int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex);
|
|
int APS5_VABI pthread_mutexattr_init_nid_postfix(PthreadMutexattr* attr);
|
|
int APS5_VABI pthread_mutexattr_destroy_nid_postfix(PthreadMutexattr* attr);
|
|
int APS5_VABI pthread_mutexattr_gettype_nid_postfix(const PthreadMutexattr* attr, int* type);
|
|
int APS5_VABI scePthreadMutexattrSetkind(PthreadMutexattr* attr, int kind);
|
|
int APS5_VABI pthread_rwlock_init_nid_postfix(PthreadRwlock* rwlock, const PthreadRwlockattr* attr);
|
|
int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock);
|
|
int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock);
|
|
int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock);
|
|
int APS5_VABI pthread_rwlockattr_init_nid_postfix(PthreadRwlockattr* attr);
|
|
int APS5_VABI pthread_rwlockattr_destroy_nid_postfix(PthreadRwlockattr* attr);
|
|
int APS5_VABI pthread_rwlockattr_settype_np_nid_postfix(PthreadRwlockattr* attr, int type);
|
|
int APS5_VABI scePthreadRwlockattrSettype(PthreadRwlockattr* attr, int type);
|
|
}
|
|
|
|
namespace {
|
|
|
|
constexpr int GUEST_EDEADLK = 11;
|
|
constexpr int KIND_ERRORCHECK = 1;
|
|
constexpr int KIND_RECURSIVE = 2;
|
|
constexpr int KIND_NORMAL = 3;
|
|
constexpr int KIND_ADAPTIVE = 4;
|
|
|
|
int failures = 0;
|
|
|
|
template<typename TCall>
|
|
void Case(const char* name, TCall call) {
|
|
try {
|
|
if (call()) return;
|
|
std::printf("%s: wrong answer\n", name);
|
|
} catch (const std::exception& error) {
|
|
std::printf("%s: %s\n", name, error.what());
|
|
}
|
|
++failures;
|
|
}
|
|
|
|
template<typename TException, typename TCall>
|
|
bool Throws(TCall call) {
|
|
try {
|
|
static_cast<void>(call());
|
|
} catch (const TException&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool HasKind(const PthreadMutexattr* attr, int kind) {
|
|
int type = -1;
|
|
return pthread_mutexattr_gettype_nid_postfix(attr, &type) == 0 && type == kind;
|
|
}
|
|
|
|
bool LocksTwice(const PthreadMutexattr* attr, int secondLock) {
|
|
PthreadMutex mutex = nullptr;
|
|
if (pthread_mutex_init_nid_postfix(&mutex, attr) != 0) return false;
|
|
const bool locked = pthread_mutex_lock_nid_postfix(&mutex) == 0 && pthread_mutex_lock_nid_postfix(&mutex) == secondLock;
|
|
if (secondLock == 0) pthread_mutex_unlock_nid_postfix(&mutex);
|
|
return locked && pthread_mutex_unlock_nid_postfix(&mutex) == 0 && pthread_mutex_destroy_nid_postfix(&mutex) == 0;
|
|
}
|
|
|
|
void TestKind() {
|
|
Case("scePthreadMutexattrSetkind", [] {
|
|
PthreadMutexattr attr = nullptr;
|
|
if (pthread_mutexattr_init_nid_postfix(&attr) != 0) return false;
|
|
for (const int kind : {KIND_RECURSIVE, KIND_NORMAL, KIND_ADAPTIVE, KIND_ERRORCHECK}) {
|
|
if (scePthreadMutexattrSetkind(&attr, kind) != 0 || !HasKind(&attr, kind)) return false;
|
|
}
|
|
if (!LocksTwice(&attr, GUEST_EDEADLK)) return false;
|
|
if (scePthreadMutexattrSetkind(&attr, KIND_RECURSIVE) != 0 || !LocksTwice(&attr, 0)) return false;
|
|
for (const int kind : {0, 5, -1}) {
|
|
if (!Throws<std::invalid_argument>([&] { return scePthreadMutexattrSetkind(&attr, kind); }) || !HasKind(&attr, KIND_RECURSIVE)) return false;
|
|
}
|
|
if (pthread_mutexattr_destroy_nid_postfix(&attr) != 0) return false;
|
|
return Throws<std::invalid_argument>([&] { return scePthreadMutexattrSetkind(&attr, KIND_NORMAL); }) &&
|
|
Throws<std::invalid_argument>([] { return scePthreadMutexattrSetkind(nullptr, KIND_NORMAL); });
|
|
});
|
|
}
|
|
|
|
void TestRwlockattr() {
|
|
Case("pthread_rwlockattr_settype_np", [] {
|
|
PthreadRwlockattr attr = nullptr;
|
|
if (pthread_rwlockattr_init_nid_postfix(&attr) != 0) return false;
|
|
for (const int type : {0, 1, 2}) {
|
|
if (pthread_rwlockattr_settype_np_nid_postfix(&attr, type) != 0 || scePthreadRwlockattrSettype(&attr, type) != 0) return false;
|
|
PthreadRwlock rwlock = nullptr;
|
|
if (pthread_rwlock_init_nid_postfix(&rwlock, &attr) != 0) return false;
|
|
const bool usable = pthread_rwlock_wrlock_nid_postfix(&rwlock) == 0 && pthread_rwlock_unlock_nid_postfix(&rwlock) == 0;
|
|
if (!usable || pthread_rwlock_destroy_nid_postfix(&rwlock) != 0) return false;
|
|
}
|
|
if (pthread_rwlockattr_destroy_nid_postfix(&attr) != 0) return false;
|
|
return Throws<std::runtime_error>([&] { return pthread_rwlockattr_settype_np_nid_postfix(&attr, 1); }) &&
|
|
Throws<std::runtime_error>([] { return pthread_rwlockattr_settype_np_nid_postfix(nullptr, 1); });
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
const std::string_view mode = argc > 1 ? argv[1] : "";
|
|
if (mode == "rwlockattr") TestRwlockattr();
|
|
else if (mode == "kind") TestKind();
|
|
else return 2;
|
|
if (failures == 0) std::printf("all cases passed\n");
|
|
return failures == 0 ? 0 : 1;
|
|
}
|