src/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*);
20
21static inline int MutexInit(Mutex* mutex) {
22 Mutex id = sceKernelCreateMutex("mutex", 0, 0, 0);
23 if (id < 0) {
24 return id;
25 }
26 *mutex = id;
27 return 0;
28}
29
30static inline int MutexDeinit(Mutex* mutex) {
31 return sceKernelDeleteMutex(*mutex);
32}
33
34static inline int MutexLock(Mutex* mutex) {
35 return sceKernelLockMutex(*mutex, 1, 0);
36}
37
38static inline int MutexTryLock(Mutex* mutex) {
39 return sceKernelTryLockMutex(*mutex, 1);
40}
41
42static inline int MutexUnlock(Mutex* mutex) {
43 return sceKernelUnlockMutex(*mutex, 1);
44}
45
46static inline int ConditionInit(Condition* cond) {
47 int res = MutexInit(&cond->mutex);
48 if (res < 0) {
49 return res;
50 }
51 cond->semaphore = sceKernelCreateSema("SceCondSema", 0, 0, 1, 0);
52 if (cond->semaphore < 0) {
53 MutexDeinit(&cond->mutex);
54 res = cond->semaphore;
55 }
56 cond->waiting = 0;
57 return res;
58}
59
60static inline int ConditionDeinit(Condition* cond) {
61 MutexDeinit(&cond->mutex);
62 return sceKernelDeleteSema(cond->semaphore);
63}
64
65static inline int ConditionWait(Condition* cond, Mutex* mutex) {
66 int ret = MutexLock(&cond->mutex);
67 if (ret < 0) {
68 return ret;
69 }
70 ++cond->waiting;
71 MutexUnlock(mutex);
72 MutexUnlock(&cond->mutex);
73 ret = sceKernelWaitSema(cond->semaphore, 1, 0);
74 if (ret < 0) {
75 printf("Premature wakeup: %08X", ret);
76 }
77 MutexLock(mutex);
78 return ret;
79}
80
81static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
82 int ret = MutexLock(&cond->mutex);
83 if (ret < 0) {
84 return ret;
85 }
86 ++cond->waiting;
87 MutexUnlock(mutex);
88 MutexUnlock(&cond->mutex);
89 SceUInt timeout = 0;
90 if (timeoutMs > 0) {
91 timeout = timeoutMs;
92 }
93 ret = sceKernelWaitSema(cond->semaphore, 1, &timeout);
94 if (ret < 0) {
95 printf("Premature wakeup: %08X", ret);
96 }
97 MutexLock(mutex);
98 return ret;
99}
100
101static inline int ConditionWake(Condition* cond) {
102 MutexLock(&cond->mutex);
103 if (cond->waiting) {
104 --cond->waiting;
105 sceKernelSignalSema(cond->semaphore, 1);
106 }
107 MutexUnlock(&cond->mutex);
108 return 0;
109}
110
111struct SceThreadEntryArgs {
112 void* context;
113 ThreadEntry entry;
114};
115
116static inline int _sceThreadEntry(SceSize args, void* argp) {
117 UNUSED(args);
118 struct SceThreadEntryArgs* arg = argp;
119 return arg->entry(arg->context);
120}
121
122static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) {
123 Thread id = sceKernelCreateThread("SceThread", _sceThreadEntry, 0x40, 0x10000, 0, 0x70000, 0);
124 if (id < 0) {
125 *thread = 0;
126 return id;
127 }
128 *thread = id;
129 struct SceThreadEntryArgs args = { context, entry };
130 sceKernelStartThread(id, sizeof(args), &args);
131 return 0;
132}
133
134static inline int ThreadJoin(Thread thread) {
135 return sceKernelWaitThreadEnd(thread, 0, 0);
136}
137
138static inline int ThreadSetName(const char* name) {
139 UNUSED(name);
140 return -1;
141}
142#endif