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
21 return (UINTN
)pthread_mutex_lock ((pthread_mutex_t
*)Mutex
);
30 return (UINTN
)pthread_mutex_unlock ((pthread_mutex_t
*)Mutex
);
39 return (UINTN
)pthread_mutex_trylock ((pthread_mutex_t
*)Mutex
);
47 pthread_mutex_t
*Mutex
;
50 Mutex
= malloc (sizeof (pthread_mutex_t
));
51 err
= pthread_mutex_init (Mutex
, NULL
);
65 return pthread_mutex_destroy ((pthread_mutex_t
*)Mutex
);
71 // Can't store this data on PthreadCreate stack so we need a global
73 pthread_mutex_t Mutex
;
74 THREAD_THUNK_THREAD_ENTRY Start
;
77 THREAD_MANGLE mThreadMangle
= {
78 PTHREAD_MUTEX_INITIALIZER
,
87 THREAD_THUNK_THREAD_ENTRY Start
;
90 // Save global on the stack before we unlock
91 Start
= mThreadMangle
.Start
;
92 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
94 // Mask all signals to the APs
95 sigfillset (&SigMask
);
96 pthread_sigmask (SIG_BLOCK
, &SigMask
, NULL
);
99 // We have to start the thread in SEC as we need to follow
100 // OS X calling conventions. We can then call back into
101 // to the callers Start.
103 // This is a great example of how all problems in computer
104 // science can be solved by adding another level of indirection
106 return (VOID
*)ReverseGasketUint64 ((UINTN
)Start
, (UINTN
)Context
);
113 IN THREAD_THUNK_THREAD_ENTRY Start
,
118 BOOLEAN EnabledOnEntry
;
121 // Threads inherit interrupt state so disable interrupts before we start thread
123 if (SecInterruptEanbled ()) {
124 SecDisableInterrupt ();
125 EnabledOnEntry
= TRUE
;
127 EnabledOnEntry
= FALSE
;
130 // Acquire lock for global, SecFakePthreadStart runs in a different thread.
131 pthread_mutex_lock (&mThreadMangle
.Mutex
);
132 mThreadMangle
.Start
= Start
;
134 err
= pthread_create (Thread
, Attribute
, SecFakePthreadStart
, Context
);
136 // Thread failed to launch so release the lock;
137 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
140 if (EnabledOnEntry
) {
141 // Restore interrupt state
142 SecEnableInterrupt ();
153 pthread_exit (ValuePtr
);
162 // POSIX currently allows pthread_t to be a structure or arithmetic type.
163 // Check out sys/types.h to make sure this will work if you are porting.
164 // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
165 return (UINTN
)pthread_self ();
168 EMU_THREAD_THUNK_PROTOCOL gPthreadThunk
= {
169 GasketPthreadMutexLock
,
170 GasketPthreadMutexUnLock
,
171 GasketPthreadMutexTryLock
,
172 GasketPthreadMutexInit
,
173 GasketPthreadMutexDestroy
,
181 IN EMU_IO_THUNK_PROTOCOL
*This
184 if (This
->Instance
!= 0) {
185 // Only single instance is supported
186 return EFI_NOT_FOUND
;
189 if (This
->ConfigString
[0] == L
'0') {
190 // If AP count is zero no need for threads
191 return EFI_NOT_FOUND
;
194 This
->Interface
= &gPthreadThunk
;
201 IN EMU_IO_THUNK_PROTOCOL
*This
207 EMU_IO_THUNK_PROTOCOL gPthreadThunkIo
= {
208 &gEmuThreadThunkProtocolGuid
,