Repository navigation
Expand file tree
/
Copy pathRwlock.cpp
More file actions
116 lines (95 loc) · 4.23 KB
/
Copy pathRwlock.cpp
File metadata and controls
116 lines (95 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include "../include/Pthread.hpp"
#include "../include/Rwlock.hpp"
#include "Common.hpp"
#include <atomic>
#include <stdexcept>
#include <string>
namespace {
constexpr int GUEST_REALTIME_CLOCK = 0;
constexpr int PROCESS_PRIVATE = 0;
int toPosix(int result) {
if (result == 0)
return 0;
const auto error = static_cast<std::uint32_t>(result);
if ((error & 0xffff0000u) != 0x80020000u)
throw std::runtime_error("Unexpected SCE rwlock error");
return static_cast<int>(error & 0xffffu);
}
void initializeStatic(PthreadRwlock* rwlock, const char* funcName) {
if (!rwlock) throw std::runtime_error(std::string(funcName) + ": null rwlock");
std::atomic_ref<PthreadRwlock> slot(*rwlock);
PthreadRwlock current = slot.load(std::memory_order_acquire);
if (current != nullptr) return;
auto* created = new PthreadRwlockPrivate();
if (!slot.compare_exchange_strong(current, created, std::memory_order_acq_rel, std::memory_order_acquire))
delete created;
}
}
extern "C" {
int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock);
int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock) {
if (!rwlock) throw std::runtime_error("pthread_rwlock_destroy: null rwlock");
if (*rwlock == nullptr) return 0;
return toPosix(scePthreadRwlockDestroy(rwlock));
}
int APS5_VABI pthread_rwlock_init_nid_postfix(PthreadRwlock* rwlock, const PthreadRwlockattr* attr) {
return toPosix(scePthreadRwlockInit(rwlock, attr, nullptr));
}
int APS5_VABI pthread_rwlockattr_destroy_nid_postfix(PthreadRwlockattr* attr) {
return toPosix(scePthreadRwlockattrDestroy(attr));
}
int APS5_VABI pthread_rwlockattr_init_nid_postfix(PthreadRwlockattr* attr) {
return toPosix(scePthreadRwlockattrInit(attr));
}
int APS5_VABI pthread_rwlockattr_getpshared_nid_postfix(const PthreadRwlockattr* attr, int* pshared) {
if (!attr || !*attr) throw std::runtime_error("pthread_rwlockattr_getpshared: null attr");
if (!pshared) throw std::runtime_error("pthread_rwlockattr_getpshared: null pshared");
*pshared = PROCESS_PRIVATE;
return 0;
}
int APS5_VABI pthread_rwlockattr_setpshared_nid_postfix(PthreadRwlockattr* attr, int pshared) {
if (pshared != PROCESS_PRIVATE) return PosixThread::GUEST_EINVAL;
if (!attr || !*attr) throw std::runtime_error("pthread_rwlockattr_setpshared: null attr");
return 0;
}
int APS5_VABI pthread_rwlock_rdlock_nid_postfix(PthreadRwlock* rwlock) {
initializeStatic(rwlock, __func__);
return toPosix(scePthreadRwlockRdlock(rwlock));
}
int APS5_VABI pthread_rwlock_timedrdlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime) {
if (!abstime) return pthread_rwlock_rdlock_nid_postfix(rwlock);
initializeStatic(rwlock, __func__);
if (scePthreadRwlockTryrdlock(rwlock) == 0) return 0;
KernelUseconds usec = 0;
if (!PosixThread::RelativeMicroseconds(GUEST_REALTIME_CLOCK, abstime, &usec)) return PosixThread::GUEST_EINVAL;
return toPosix(scePthreadRwlockTimedrdlock(rwlock, usec));
}
int APS5_VABI pthread_rwlock_timedwrlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime) {
if (!abstime) return pthread_rwlock_wrlock_nid_postfix(rwlock);
initializeStatic(rwlock, __func__);
if (scePthreadRwlockTrywrlock(rwlock) == 0) return 0;
KernelUseconds usec = 0;
if (!PosixThread::RelativeMicroseconds(GUEST_REALTIME_CLOCK, abstime, &usec)) return PosixThread::GUEST_EINVAL;
return toPosix(scePthreadRwlockTimedwrlock(rwlock, usec));
}
int APS5_VABI pthread_rwlock_tryrdlock_nid_postfix(PthreadRwlock* rwlock) {
initializeStatic(rwlock, __func__);
return toPosix(scePthreadRwlockTryrdlock(rwlock));
}
int APS5_VABI pthread_rwlock_trywrlock_nid_postfix(PthreadRwlock* rwlock) {
initializeStatic(rwlock, __func__);
return toPosix(scePthreadRwlockTrywrlock(rwlock));
}
int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock) {
initializeStatic(rwlock, __func__);
return toPosix(scePthreadRwlockUnlock(rwlock));
}
int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock) {
initializeStatic(rwlock, __func__);
return toPosix(scePthreadRwlockWrlock(rwlock));
}
}