all repos — mgba @ f836a67863e66499c812c8d963d37ff56ad10638

mGBA Game Boy Advance Emulator

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