]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Unix/Host/Pthreads.c
EmulatorPkg/Unix: Fix various typos
[mirror_edk2.git] / EmulatorPkg / Unix / Host / Pthreads.c
CommitLineData
79e4f2a5
RN
1/*++ @file\r
2 POSIX Pthreads to emulate APs and implement threads\r
3\r
4Copyright (c) 2011, Apple Inc. All rights reserved.\r
538d8aaa 5Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>\r
79e4f2a5 6\r
e3ba31da 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
79e4f2a5
RN
8\r
9\r
10**/\r
11\r
12#include "Host.h"\r
13#include <pthread.h>\r
14\r
15\r
16UINTN\r
17EFIAPI\r
18PthreadMutexLock (\r
19 IN VOID *Mutex\r
20 )\r
21{\r
22 return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex);\r
23}\r
24\r
25\r
26\r
27UINTN\r
28EFIAPI\r
29PthreadMutexUnLock (\r
30 IN VOID *Mutex\r
31 )\r
32{\r
33 return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex);\r
34}\r
35\r
36\r
37UINTN\r
38EFIAPI\r
39PthreadMutexTryLock (\r
40 IN VOID *Mutex\r
41 )\r
42{\r
43 return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex);\r
44}\r
45\r
46\r
47VOID *\r
48PthreadMutexInit (\r
49 IN VOID\r
50 )\r
51{\r
52 pthread_mutex_t *Mutex;\r
53 int err;\r
54\r
55 Mutex = malloc (sizeof (pthread_mutex_t));\r
56 err = pthread_mutex_init (Mutex, NULL);\r
57 if (err == 0) {\r
58 return Mutex;\r
59 }\r
60\r
61 return NULL;\r
62}\r
63\r
64\r
65UINTN\r
66PthreadMutexDestroy (\r
67 IN VOID *Mutex\r
68 )\r
69{\r
70 if (Mutex != NULL) {\r
71 return pthread_mutex_destroy ((pthread_mutex_t *)Mutex);\r
72 }\r
73\r
74 return -1;\r
75}\r
76\r
77// Can't store this data on PthreadCreate stack so we need a global\r
78typedef struct {\r
79 pthread_mutex_t Mutex;\r
80 THREAD_THUNK_THREAD_ENTRY Start;\r
81} THREAD_MANGLE;\r
82\r
83THREAD_MANGLE mThreadMangle = {\r
84 PTHREAD_MUTEX_INITIALIZER,\r
85 NULL\r
86};\r
87\r
88VOID *\r
89SecFakePthreadStart (\r
90 VOID *Context\r
91 )\r
92{\r
93 THREAD_THUNK_THREAD_ENTRY Start;\r
94 sigset_t SigMask;\r
95\r
96 // Save global on the stack before we unlock\r
97 Start = mThreadMangle.Start;\r
98 pthread_mutex_unlock (&mThreadMangle.Mutex);\r
99\r
100 // Mask all signals to the APs\r
101 sigfillset (&SigMask);\r
102 pthread_sigmask (SIG_BLOCK, &SigMask, NULL);\r
103\r
104 //\r
105 // We have to start the thread in SEC as we need to follow\r
106 // OS X calling conventions. We can then call back into\r
107 // to the callers Start.\r
108 //\r
109 // This is a great example of how all problems in computer\r
110 // science can be solved by adding another level of indirection\r
111 //\r
538d8aaa 112 return (VOID *)ReverseGasketUint64 ((UINTN)Start, (UINTN)Context);\r
79e4f2a5
RN
113}\r
114\r
115UINTN\r
116PthreadCreate (\r
117 IN VOID *Thread,\r
118 IN VOID *Attribute,\r
119 IN THREAD_THUNK_THREAD_ENTRY Start,\r
120 IN VOID *Context\r
121 )\r
122{\r
123 int err;\r
124 BOOLEAN EnabledOnEntry;\r
125\r
126 //\r
127 // Threads inherit interrupt state so disable interrupts before we start thread\r
128 //\r
129 if (SecInterruptEanbled ()) {\r
130 SecDisableInterrupt ();\r
131 EnabledOnEntry = TRUE;\r
132 } else {\r
133 EnabledOnEntry = FALSE;\r
134 }\r
135\r
26cfe2c6 136 // Acquire lock for global, SecFakePthreadStart runs in a different thread.\r
79e4f2a5
RN
137 pthread_mutex_lock (&mThreadMangle.Mutex);\r
138 mThreadMangle.Start = Start;\r
139\r
140 err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context);\r
141 if (err != 0) {\r
142 // Thread failed to launch so release the lock;\r
143 pthread_mutex_unlock (&mThreadMangle.Mutex);\r
144 }\r
145\r
146 if (EnabledOnEntry) {\r
147 // Restore interrupt state\r
148 SecEnableInterrupt ();\r
149 }\r
150\r
151 return err;\r
152}\r
153\r
154\r
155VOID\r
156PthreadExit (\r
157 IN VOID *ValuePtr\r
158 )\r
159{\r
160 pthread_exit (ValuePtr);\r
161 return;\r
162}\r
163\r
164\r
165UINTN\r
166PthreadSelf (\r
167 VOID\r
168 )\r
169{\r
170 // POSIX currently allows pthread_t to be a structure or arithmetic type.\r
171 // Check out sys/types.h to make sure this will work if you are porting.\r
172 // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.\r
173 return (UINTN)pthread_self ();\r
174}\r
175\r
176\r
177EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = {\r
178 GasketPthreadMutexLock,\r
179 GasketPthreadMutexUnLock,\r
180 GasketPthreadMutexTryLock,\r
181 GasketPthreadMutexInit,\r
182 GasketPthreadMutexDestroy,\r
183 GasketPthreadCreate,\r
184 GasketPthreadExit,\r
185 GasketPthreadSelf\r
186};\r
187\r
188\r
189EFI_STATUS\r
190PthreadOpen (\r
191 IN EMU_IO_THUNK_PROTOCOL *This\r
192 )\r
193{\r
194 if (This->Instance != 0) {\r
195 // Only single instance is supported\r
196 return EFI_NOT_FOUND;\r
197 }\r
198\r
199 if (This->ConfigString[0] == L'0') {\r
200 // If AP count is zero no need for threads\r
201 return EFI_NOT_FOUND;\r
202 }\r
203\r
204 This->Interface = &gPthreadThunk;\r
205\r
206 return EFI_SUCCESS;\r
207}\r
208\r
209\r
210EFI_STATUS\r
211PthreadClose (\r
212 IN EMU_IO_THUNK_PROTOCOL *This\r
213 )\r
214{\r
215 return EFI_SUCCESS;\r
216}\r
217\r
218\r
219EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = {\r
220 &gEmuThreadThunkProtocolGuid,\r
221 NULL,\r
222 NULL,\r
223 0,\r
224 GasketPthreadOpen,\r
225 GasketPthreadClose,\r
226 NULL\r
227};\r
228\r
229\r