PS2SDK
PS2 Homebrew Libraries
tls-helper.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #include <ps2_osal.h>
12 
13 #ifdef F___keysUsed
14 int *__keysUsed;
15 #else
16 extern int *__keysUsed;
17 #endif
18 
19 #ifdef F___maxTlsValues
20 int __maxTlsValues;
21 #else
22 extern int __maxTlsValues;
23 #endif
24 
25 #ifdef F___globalTlsLock
26 pte_osMutexHandle __globalTlsLock;
27 #else
28 extern pte_osMutexHandle __globalTlsLock;
29 #endif
30 
31 /* Structure used to emulate TLS on non-POSIX threads.
32  * This limits us to one non-POSIX thread that can
33  * call pthread functions. */
34 #ifdef F___globalTls
35 void *__globalTls;
36 #else
37 extern void *__globalTls;
38 #endif
39 
40 #ifdef F_pteTlsGlobalInit
41 pte_osResult pteTlsGlobalInit(int maxEntries)
42 {
43  int i;
44  pte_osResult result;
45 
46  pte_osMutexCreate(&__globalTlsLock);
47  __keysUsed = (int *)malloc(maxEntries * sizeof(int));
48 
49  if (__keysUsed != NULL) {
50  for (i = 0; i < maxEntries; i++) {
51  __keysUsed[i] = 0;
52  }
53 
54  __maxTlsValues = maxEntries;
55  result = PTE_OS_OK;
56  } else {
57  result = PTE_OS_NO_RESOURCES;
58  }
59 
60  return result;
61 }
62 #endif
63 
64 #ifdef F_pteTlsThreadInit
65 void *pteTlsThreadInit(void)
66 {
67  void **pTlsStruct;
68  int i;
69 
70  pTlsStruct = (void **)malloc(__maxTlsValues * sizeof(void *));
71 
72  // PTE library assumes that keys are initialized to zero
73  for (i = 0; i < __maxTlsValues; i++) {
74  pTlsStruct[i] = 0;
75  }
76 
77  return (void *)pTlsStruct;
78 }
79 #endif
80 
81 #ifdef F___pteTlsAlloc
82 pte_osResult __pteTlsAlloc(unsigned int *pKey)
83 {
84  int i;
85  pte_osResult result = PTE_OS_NO_RESOURCES;
86 
87  pte_osMutexLock(__globalTlsLock);
88 
89  for (i = 0; i < __maxTlsValues; i++) {
90  if (__keysUsed[i] == 0) {
91  __keysUsed[i] = 1;
92 
93  *pKey = i + 1;
94  result = PTE_OS_OK;
95  break;
96  }
97  }
98 
99  pte_osMutexUnlock(__globalTlsLock);
100  return result;
101 }
102 #else
103 pte_osResult __pteTlsAlloc(unsigned int *pKey);
104 #endif
105 
106 #ifdef F_pteTlsGetValue
107 void *pteTlsGetValue(void *pTlsThreadStruct, unsigned int index)
108 {
109  void **pTls = (void **)pTlsThreadStruct;
110 
111  if (__keysUsed[index - 1] && pTls != NULL) {
112  return pTls[index - 1];
113  } else {
114  return NULL;
115  }
116 }
117 #else
118 void *pteTlsGetValue(void *pTlsThreadStruct, unsigned int index);
119 #endif
120 
121 #ifdef F___pteTlsSetValue
122 pte_osResult __pteTlsSetValue(void *pTlsThreadStruct, unsigned int index, void *value)
123 {
124  pte_osResult result;
125  void **pTls = (void **)pTlsThreadStruct;
126 
127  if (pTls != NULL) {
128  pTls[index - 1] = value;
129  result = PTE_OS_OK;
130  } else {
131  result = PTE_OS_INVALID_PARAM;
132  }
133 
134  return result;
135 }
136 #else
137 pte_osResult __pteTlsSetValue(void *pTlsThreadStruct, unsigned int index, void *value);
138 #endif
139 
140 #ifdef F___getTlsStructFromThread
141 void *__getTlsStructFromThread(s32 thid)
142 {
143  struct OsalThreadInfo *threadInfo = &__threadInfo[thid];
144  void *pTls;
145 
146  /* If we were called from a pthread, use the TLS allocated when the thread
147  * was created. Otherwise, we were called from a non-pthread, so use the
148  * "global". This is a pretty bad hack, but necessary due to lack of TLS on PS2.
149  */
150  if (threadInfo->tlsPtr) {
151  pTls = threadInfo->tlsPtr;
152  } else {
153  pTls = __globalTls;
154  }
155 
156  return pTls;
157 }
158 #else
159 void *__getTlsStructFromThread(s32 thid);
160 #endif
161 
162 #ifdef F_pteTlsFree
163 pte_osResult pteTlsFree(unsigned int index)
164 {
165  pte_osResult result;
166 
167  if (__keysUsed != NULL) {
168  pte_osMutexLock(__globalTlsLock);
169  __keysUsed[index - 1] = 0;
170  pte_osMutexUnlock(__globalTlsLock);
171 
172  result = PTE_OS_OK;
173  } else {
174  result = PTE_OS_GENERAL_FAILURE;
175  }
176 
177  return result;
178 }
179 #else
180 pte_osResult pteTlsFree(unsigned int index);
181 #endif
182 
183 #ifdef F_pteTlsThreadDestroy
184 void pteTlsThreadDestroy(void *pTlsThreadStruct)
185 {
186  free(pTlsThreadStruct);
187 }
188 #endif
189 
190 #ifdef F_pteTlsGlobalDestroy
191 void pteTlsGlobalDestroy(void)
192 {
193  pte_osMutexDelete(__globalTlsLock);
194  free(__keysUsed);
195 }
196 #endif
197 
198 #ifdef F_pte_osTlsSetValue
199 pte_osResult pte_osTlsSetValue(unsigned int key, void * value)
200 {
201  void *pTls;
202 
203  pTls = __getTlsStructFromThread(GetThreadId());
204 
205  return __pteTlsSetValue(pTls, key, value);
206 }
207 #endif
208 
209 #ifdef F_pte_osTlsGetValue
210 void * pte_osTlsGetValue(unsigned int index)
211 {
212  void *pTls;
213 
214  pTls = __getTlsStructFromThread(GetThreadId());
215 
216  return (void *) pteTlsGetValue(pTls, index);
217 
218 }
219 #endif
220 
221 #ifdef F_pte_osTlsAlloc
222 pte_osResult pte_osTlsAlloc(unsigned int *pKey)
223 {
224  __getTlsStructFromThread(GetThreadId());
225 
226  return __pteTlsAlloc(pKey);
227 
228 }
229 #endif
230 
231 #ifdef F_pte_osTlsFree
232 pte_osResult pte_osTlsFree(unsigned int index)
233 {
234  return pteTlsFree(index);
235 }
236 #endif
OsalThreadInfo
Definition: ps2_osal.h:39