[3DS] Support latest libctru
[pcsx_rearmed.git] / frontend / 3ds / pthread.h
1
2 #ifndef _3DS_PTHREAD_WRAP__
3 #define _3DS_PTHREAD_WRAP__
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8
9 #include "3ds_utils.h"
10
11 #define CTR_PTHREAD_STACK_SIZE 0x10000
12 #define FALSE 0
13
14 typedef struct {
15   uint32_t semaphore;
16   LightLock lock;
17   uint32_t waiting;
18 } cond_t;
19
20 #if !defined(PTHREAD_SCOPE_PROCESS)
21 /* An earlier version of devkitARM does not define the pthread types. Can remove in r54+. */
22
23 typedef uint32_t pthread_t;
24 typedef int pthread_attr_t;
25
26 typedef LightLock pthread_mutex_t;
27 typedef int pthread_mutexattr_t;
28
29 typedef uint32_t pthread_cond_t;
30 typedef int pthread_condattr_t;
31
32 #endif
33
34 static inline int pthread_create(pthread_t *thread,
35       const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
36 {
37    int procnum = -2; // use default cpu
38    bool isNew3DS;
39    APT_CheckNew3DS(&isNew3DS);
40
41    if (isNew3DS)
42      procnum = 2;
43
44    *thread = threadCreate(start_routine, arg, CTR_PTHREAD_STACK_SIZE, 0x25, procnum, FALSE);
45    return 0;
46 }
47
48
49 static inline int pthread_join(pthread_t thread, void **retval)
50 {
51    (void)retval;
52
53    if(threadJoin(thread, INT64_MAX))
54       return -1;
55
56    threadFree(thread);
57
58    return 0;
59 }
60
61
62 static inline void pthread_exit(void *retval)
63 {   
64    (void)retval;
65
66    threadExit(0);
67 }
68
69 static inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) {
70   LightLock_Init(mutex);
71   return 0;
72 }
73
74 static inline int pthread_mutex_lock(pthread_mutex_t *mutex) {
75   LightLock_Lock(mutex);
76   return 0;
77 }
78
79 static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) {
80   LightLock_Unlock(mutex);
81   return 0;
82 }
83
84 static inline int pthread_mutex_destroy(pthread_mutex_t *mutex) {
85   return 0;
86 }
87
88 static inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) {
89   cond_t *cond_data = calloc(1, sizeof(cond_t));
90   if (!cond_data)
91     goto error;
92
93   if (svcCreateSemaphore(&cond_data->semaphore, 0, 1))
94     goto error;
95
96   LightLock_Init(&cond_data->lock);
97   cond_data->waiting = 0;
98   *cond = cond_data;
99   return 0;
100
101  error:
102   svcCloseHandle(cond_data->semaphore);
103   if (cond_data)
104     free(cond_data);
105   return -1;
106 }
107
108 static inline int pthread_cond_signal(pthread_cond_t *cond) {
109   int32_t count;
110   cond_t *cond_data = (cond_t *)*cond;
111   LightLock_Lock(&cond_data->lock);
112   if (cond_data->waiting) {
113     cond_data->waiting--;
114     svcReleaseSemaphore(&count, cond_data->semaphore, 1);
115   }
116   LightLock_Unlock(&cond_data->lock);
117   return 0;
118 }
119
120 static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *lock) {
121   cond_t *cond_data = (cond_t *)*cond;
122   LightLock_Lock(&cond_data->lock);
123   cond_data->waiting++;
124   LightLock_Unlock(lock);
125   LightLock_Unlock(&cond_data->lock);
126   svcWaitSynchronization(cond_data->semaphore, INT64_MAX);
127   LightLock_Lock(lock);
128   return 0;
129 }
130
131 static inline int pthread_cond_destroy(pthread_cond_t *cond) {
132   if (*cond) {
133     cond_t *cond_data = (cond_t *)*cond;
134
135     svcCloseHandle(cond_data->semaphore);
136     free(*cond);
137   }
138   *cond = 0;
139   return 0;
140 }
141
142
143 #endif //_3DS_PTHREAD_WRAP__
144