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