all repos — mgba @ 60577e83948647d36a2e6a8b4ec8f8556df3f72f

mGBA Game Boy Advance Emulator

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*);
 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, 0x10000100, 0x10000, 0, 0, 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	int res = sceKernelWaitThreadEnd(thread, 0, 0);
136	if (res < 0) {
137		return res;
138	}
139	return sceKernelDeleteThread(thread);
140}
141
142static inline int ThreadSetName(const char* name) {
143	UNUSED(name);
144	return -1;
145}
146#endif