Merge pull request #61 from frangarcj/master
[pcsx_rearmed.git] / frontend / vita / pthread.h
CommitLineData
1a5fd794 1/* Copyright (C) 2010-2016 The RetroArch team
f901d0cd 2 *
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (psp_pthread.h).
5 * ---------------------------------------------------------------------------------------
6 *
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/* FIXME: unfinished on PSP, mutexes and condition variables basically a stub. */
24#ifndef _PSP_PTHREAD_WRAP__
25#define _PSP_PTHREAD_WRAP__
26
27#ifdef VITA
28#include <psp2/kernel/threadmgr.h>
1a5fd794 29#include <sys/time.h>
f901d0cd 30#else
31#include <pspkernel.h>
32#include <pspthreadman.h>
33#include <pspthreadman_kernel.h>
34#endif
35#include <stdio.h>
36#include <retro_inline.h>
37
1a5fd794 38#define STACKSIZE (8 * 1024)
f901d0cd 39
40typedef SceUID pthread_t;
41typedef SceUID pthread_mutex_t;
42typedef void* pthread_mutexattr_t;
43typedef int pthread_attr_t;
1a5fd794 44
45typedef struct
46{
47 SceUID mutex;
48 SceUID sema;
49 int waiting;
50} pthread_cond_t;
51
f901d0cd 52typedef SceUID pthread_condattr_t;
53
54/* Use pointer values to create unique names for threads/mutexes */
55char name_buffer[256];
56
57typedef void* (*sthreadEntry)(void *argp);
58
59typedef struct
60{
61 void* arg;
62 sthreadEntry start_routine;
63} sthread_args_struct;
64
65
66static int psp_thread_wrap(SceSize args, void *argp)
67{
68 sthread_args_struct* sthread_args = (sthread_args_struct*)argp;
69
70 return (int)sthread_args->start_routine(sthread_args->arg);
71}
72
73static INLINE int pthread_create(pthread_t *thread,
74 const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
75{
1a5fd794 76 sprintf(name_buffer, "0x%08X", (unsigned int) thread);
f901d0cd 77
f901d0cd 78#ifdef VITA
1a5fd794 79 *thread = sceKernelCreateThread(name_buffer, psp_thread_wrap,
80 0x10000100, 0x10000, 0, 0, NULL);
81#else
82 *thread = sceKernelCreateThread(name_buffer,
83 psp_thread_wrap, 0x20, STACKSIZE, 0, NULL);
f901d0cd 84#endif
f901d0cd 85
86 sthread_args_struct sthread_args;
87 sthread_args.arg = arg;
88 sthread_args.start_routine = start_routine;
89
90 return sceKernelStartThread(*thread, sizeof(sthread_args), &sthread_args);
91}
92
93static INLINE int pthread_mutex_init(pthread_mutex_t *mutex,
94 const pthread_mutexattr_t *attr)
95{
1a5fd794 96 sprintf(name_buffer, "0x%08X", (unsigned int) mutex);
f901d0cd 97
98#ifdef VITA
1a5fd794 99 *mutex = sceKernelCreateMutex(name_buffer, 0, 0, 0);
100 if(*mutex<0)
101 return *mutex;
102 return 0;
f901d0cd 103#else
104 return *mutex = sceKernelCreateSema(name_buffer, 0, 1, 1, NULL);
105#endif
106}
107
108static INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex)
109{
110#ifdef VITA
111 return sceKernelDeleteMutex(*mutex);
112#else
113 return sceKernelDeleteSema(*mutex);
114#endif
115}
116
117static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex)
118{
119#ifdef VITA
1a5fd794 120 int ret = sceKernelLockMutex(*mutex, 1, 0);
121 return ret;
122
f901d0cd 123#else
124 /* FIXME: stub */
125 return 1;
126#endif
127}
128
129static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex)
130{
131#ifdef VITA
1a5fd794 132 int ret = sceKernelUnlockMutex(*mutex, 1);
133 return ret;
f901d0cd 134#else
135 /* FIXME: stub */
136 return 1;
137#endif
138}
139
140
141static INLINE int pthread_join(pthread_t thread, void **retval)
142{
f901d0cd 143#ifdef VITA
1a5fd794 144 int res = sceKernelWaitThreadEnd(thread, 0, 0);
145 if (res < 0)
146 return res;
147 return sceKernelDeleteThread(thread);
f901d0cd 148#else
1a5fd794 149 SceUInt timeout = (SceUInt)-1;
f901d0cd 150 sceKernelWaitThreadEnd(thread, &timeout);
151 exit_status = sceKernelGetThreadExitStatus(thread);
f901d0cd 152 sceKernelDeleteThread(thread);
153 return exit_status;
1a5fd794 154#endif
f901d0cd 155}
156
157static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex)
158{
159#ifdef VITA
160 return sceKernelTryLockMutex(*mutex, 1 /* not sure about this last param */);
161#else
162 /* FIXME: stub */
163 return 1;
164#endif
165}
166
167static INLINE int pthread_cond_wait(pthread_cond_t *cond,
168 pthread_mutex_t *mutex)
169{
1a5fd794 170#ifdef VITA
171 int ret = pthread_mutex_lock(&cond->mutex);
172 if (ret < 0)
173 return ret;
174 ++cond->waiting;
175 pthread_mutex_unlock(mutex);
176 pthread_mutex_unlock(&cond->mutex);
177
178 ret = sceKernelWaitSema(cond->sema, 1, 0);
179 if (ret < 0)
180 sceClibPrintf("Premature wakeup: %08X", ret);
181 pthread_mutex_lock(mutex);
182 return ret;
183#else
184 /* FIXME: stub */
f901d0cd 185 sceKernelDelayThread(10000);
186 return 1;
1a5fd794 187#endif
f901d0cd 188}
189
190static INLINE int pthread_cond_timedwait(pthread_cond_t *cond,
191 pthread_mutex_t *mutex, const struct timespec *abstime)
192{
1a5fd794 193#ifdef VITA
194 int ret = pthread_mutex_lock(&cond->mutex);
195 if (ret < 0)
196 return ret;
197 ++cond->waiting;
198 pthread_mutex_unlock(mutex);
199 pthread_mutex_unlock(&cond->mutex);
200
201 SceUInt timeout = 0;
202
203 timeout = abstime->tv_sec;
204 timeout += abstime->tv_nsec / 1.0e6;
205
206 ret = sceKernelWaitSema(cond->sema, 1, &timeout);
207 if (ret < 0)
208 sceClibPrintf("Premature wakeup: %08X", ret);
209 pthread_mutex_lock(mutex);
210 return ret;
211
212#else
213 /* FIXME: stub */
f901d0cd 214 return 1;
1a5fd794 215#endif
f901d0cd 216}
217
218static INLINE int pthread_cond_init(pthread_cond_t *cond,
219 const pthread_condattr_t *attr)
220{
1a5fd794 221#ifdef VITA
222
223 pthread_mutex_init(&cond->mutex,NULL);
224 if(cond->mutex<0){
225 return cond->mutex;
226 }
227 sprintf(name_buffer, "0x%08X", (unsigned int) cond);
228 //cond->sema = sceKernelCreateCond(name_buffer, 0, cond->mutex, 0);
229 cond->sema = sceKernelCreateSema(name_buffer, 0, 0, 1, 0);
230 if(cond->sema<0){
231 pthread_mutex_destroy(&cond->mutex);
232 return cond->sema;
233 }
234
235 cond->waiting = 0;
236
237
238 return 0;
239
240
241#else
242 /* FIXME: stub */
f901d0cd 243 return 1;
1a5fd794 244#endif
f901d0cd 245}
246
247static INLINE int pthread_cond_signal(pthread_cond_t *cond)
248{
1a5fd794 249#ifdef VITA
250 pthread_mutex_lock(&cond->mutex);
251 if (cond->waiting)
252 {
253 --cond->waiting;
254 sceKernelSignalSema(cond->sema, 1);
255 }
256 pthread_mutex_unlock(&cond->mutex);
257 return 0;
258#else
259 /* FIXME: stub */
f901d0cd 260 return 1;
1a5fd794 261#endif
f901d0cd 262}
263
264static INLINE int pthread_cond_broadcast(pthread_cond_t *cond)
265{
1a5fd794 266 /* FIXME: stub */
f901d0cd 267 return 1;
268}
269
270static INLINE int pthread_cond_destroy(pthread_cond_t *cond)
271{
1a5fd794 272#ifdef VITA
273 int ret = sceKernelDeleteSema(cond->sema);
274 if(ret < 0)
275 return ret;
276
277 return sceKernelDeleteMutex(cond->mutex);
278#else
279 /* FIXME: stub */
280 return 1;
281#endif
f901d0cd 282}
283
284
285static INLINE int pthread_detach(pthread_t thread)
286{
1a5fd794 287 return 0;
f901d0cd 288}
289
290static INLINE void pthread_exit(void *retval)
291{
1a5fd794 292#ifdef VITA
293 sceKernelExitDeleteThread(sceKernelGetThreadId());
294#endif
295}
296
297static INLINE pthread_t pthread_self(void)
298{
299 /* zero 20-mar-2016: untested */
300 return sceKernelGetThreadId();
301}
302
303static INLINE int pthread_equal(pthread_t t1, pthread_t t2)
304{
305 return t1 == t2;
f901d0cd 306}
307
308#endif //_PSP_PTHREAD_WRAP__