include/mgba-util/platform/psp2/threading.h (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#ifndef SCE_THREADING_H
7#define SCE_THREADING_H
8
9#include <psp2/kernel/threadmgr.h>
10
11typedef SceUID Thread;
12typedef SceUID Mutex;
13typedef struct {
14 Mutex mutex;
15 SceUID semaphore;
16 int waiting;
17} Condition;
18#define THREAD_ENTRY int
19typedef THREAD_ENTRY (*ThreadEntry)(void*);
20typedef int ThreadLocal;
21
22static inline int MutexInit(Mutex* mutex) {
23 Mutex id = sceKernelCreateMutex("mutex", 0, 0, 0);
24 if (id < 0) {
25 return id;
26 }
27 *mutex = id;
28 return 0;
29}
30
31static inline int MutexDeinit(Mutex* mutex) {
32 return sceKernelDeleteMutex(*mutex);
33}
34
35static inline int MutexLock(Mutex* mutex) {
36 return sceKernelLockMutex(*mutex, 1, 0);
37}
38
39static inline int MutexTryLock(Mutex* mutex) {
40 return sceKernelTryLockMutex(*mutex, 1);
41}
42
43static inline int MutexUnlock(Mutex* mutex) {
44 return sceKernelUnlockMutex(*mutex, 1);
45}
46
47static inline int ConditionInit(Condition* cond) {
48 int res = MutexInit(&cond->mutex);
49 if (res < 0) {
50 return res;
51 }
52 cond->semaphore = sceKernelCreateSema("SceCondSema", 0, 0, 1, 0);
53 if (cond->semaphore < 0) {
54 MutexDeinit(&cond->mutex);
55 res = cond->semaphore;
56 }
57 cond->waiting = 0;
58 return res;
59}
60
61static inline int ConditionDeinit(Condition* cond) {
62 MutexDeinit(&cond->mutex);
63 return sceKernelDeleteSema(cond->semaphore);
64}
65
66static inline int ConditionWait(Condition* cond, Mutex* mutex) {
67 int ret = MutexLock(&cond->mutex);
68 if (ret < 0) {
69 return ret;
70 }
71 ++cond->waiting;
72 MutexUnlock(mutex);
73 MutexUnlock(&cond->mutex);
74 ret = sceKernelWaitSema(cond->semaphore, 1, 0);
75 if (ret < 0) {
76 printf("Premature wakeup: %08X", ret);
77 }
78 MutexLock(mutex);
79 return ret;
80}
81
82static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
83 int ret = MutexLock(&cond->mutex);
84 if (ret < 0) {
85 return ret;
86 }
87 ++cond->waiting;
88 MutexUnlock(mutex);
89 MutexUnlock(&cond->mutex);
90 SceUInt timeout = 0;
91 if (timeoutMs > 0) {
92 timeout = timeoutMs;
93 }
94 ret = sceKernelWaitSema(cond->semaphore, 1, &timeout);
95 if (ret < 0) {
96 printf("Premature wakeup: %08X", ret);
97 }
98 MutexLock(mutex);
99 return ret;
100}
101
102static inline int ConditionWake(Condition* cond) {
103 MutexLock(&cond->mutex);
104 if (cond->waiting) {
105 --cond->waiting;
106 sceKernelSignalSema(cond->semaphore, 1);
107 }
108 MutexUnlock(&cond->mutex);
109 return 0;
110}
111
112struct SceThreadEntryArgs {
113 void* context;
114 ThreadEntry entry;
115};
116
117static inline int _sceThreadEntry(SceSize args, void* argp) {
118 UNUSED(args);
119 struct SceThreadEntryArgs* arg = argp;
120 return arg->entry(arg->context);
121}
122
123static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) {
124 Thread id = sceKernelCreateThread("SceThread", _sceThreadEntry, 0x10000100, 0x10000, 0, 0, 0);
125 if (id < 0) {
126 *thread = 0;
127 return id;
128 }
129 *thread = id;
130 struct SceThreadEntryArgs args = { context, entry };
131 sceKernelStartThread(id, sizeof(args), &args);
132 return 0;
133}
134
135static inline int ThreadJoin(Thread* thread) {
136 int res = sceKernelWaitThreadEnd(*thread, 0, 0);
137 if (res < 0) {
138 return res;
139 }
140 return sceKernelDeleteThread(*thread);
141}
142
143static inline int ThreadSetName(const char* name) {
144 UNUSED(name);
145 return -1;
146}
147
148static inline void ThreadLocalInitKey(ThreadLocal* key) {
149 static int base = 0x90;
150 *key = __atomic_fetch_add(&base, 1, __ATOMIC_SEQ_CST);
151}
152
153static inline void ThreadLocalSetKey(ThreadLocal key, void* value) {
154 void** tls = sceKernelGetTLSAddr(key);
155 *tls = value;
156}
157
158static inline void* ThreadLocalGetValue(ThreadLocal key) {
159 void** tls = sceKernelGetTLSAddr(key);
160 return *tls;
161}
162#endif