2 POSIX Pthreads to emulate APs and implement threads
4 Copyright (c) 2011, Apple Inc. All rights reserved.
5 Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
22 return (UINTN
)pthread_mutex_lock ((pthread_mutex_t
*)Mutex
);
33 return (UINTN
)pthread_mutex_unlock ((pthread_mutex_t
*)Mutex
);
43 return (UINTN
)pthread_mutex_trylock ((pthread_mutex_t
*)Mutex
);
52 pthread_mutex_t
*Mutex
;
55 Mutex
= malloc (sizeof (pthread_mutex_t
));
56 err
= pthread_mutex_init (Mutex
, NULL
);
71 return pthread_mutex_destroy ((pthread_mutex_t
*)Mutex
);
77 // Can't store this data on PthreadCreate stack so we need a global
79 pthread_mutex_t Mutex
;
80 THREAD_THUNK_THREAD_ENTRY Start
;
83 THREAD_MANGLE mThreadMangle
= {
84 PTHREAD_MUTEX_INITIALIZER
,
93 THREAD_THUNK_THREAD_ENTRY Start
;
96 // Save global on the stack before we unlock
97 Start
= mThreadMangle
.Start
;
98 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
100 // Mask all signals to the APs
101 sigfillset (&SigMask
);
102 pthread_sigmask (SIG_BLOCK
, &SigMask
, NULL
);
105 // We have to start the thread in SEC as we need to follow
106 // OS X calling conventions. We can then call back into
107 // to the callers Start.
109 // This is a great example of how all problems in computer
110 // science can be solved by adding another level of indirection
112 return (VOID
*)ReverseGasketUint64 ((UINTN
)Start
, (UINTN
)Context
);
119 IN THREAD_THUNK_THREAD_ENTRY Start
,
124 BOOLEAN EnabledOnEntry
;
127 // Threads inherit interrupt state so disable interrupts before we start thread
129 if (SecInterruptEanbled ()) {
130 SecDisableInterrupt ();
131 EnabledOnEntry
= TRUE
;
133 EnabledOnEntry
= FALSE
;
136 // Aquire lock for global, SecFakePthreadStart runs in a different thread.
137 pthread_mutex_lock (&mThreadMangle
.Mutex
);
138 mThreadMangle
.Start
= Start
;
140 err
= pthread_create (Thread
, Attribute
, SecFakePthreadStart
, Context
);
142 // Thread failed to launch so release the lock;
143 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
146 if (EnabledOnEntry
) {
147 // Restore interrupt state
148 SecEnableInterrupt ();
160 pthread_exit (ValuePtr
);
170 // POSIX currently allows pthread_t to be a structure or arithmetic type.
171 // Check out sys/types.h to make sure this will work if you are porting.
172 // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
173 return (UINTN
)pthread_self ();
177 EMU_THREAD_THUNK_PROTOCOL gPthreadThunk
= {
178 GasketPthreadMutexLock
,
179 GasketPthreadMutexUnLock
,
180 GasketPthreadMutexTryLock
,
181 GasketPthreadMutexInit
,
182 GasketPthreadMutexDestroy
,
191 IN EMU_IO_THUNK_PROTOCOL
*This
194 if (This
->Instance
!= 0) {
195 // Only single instance is supported
196 return EFI_NOT_FOUND
;
199 if (This
->ConfigString
[0] == L
'0') {
200 // If AP count is zero no need for threads
201 return EFI_NOT_FOUND
;
204 This
->Interface
= &gPthreadThunk
;
212 IN EMU_IO_THUNK_PROTOCOL
*This
219 EMU_IO_THUNK_PROTOCOL gPthreadThunkIo
= {
220 &gEmuThreadThunkProtocolGuid
,