2 POSIX Pthreads to emulate APs and implement threads
4 Copyright (c) 2011, Apple Inc. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 return (UINTN
)pthread_mutex_lock ((pthread_mutex_t
*)Mutex
);
37 return (UINTN
)pthread_mutex_unlock ((pthread_mutex_t
*)Mutex
);
47 return (UINTN
)pthread_mutex_trylock ((pthread_mutex_t
*)Mutex
);
56 pthread_mutex_t
*Mutex
;
59 Mutex
= malloc (sizeof (pthread_mutex_t
));
60 err
= pthread_mutex_init (Mutex
, NULL
);
75 return pthread_mutex_destroy ((pthread_mutex_t
*)Mutex
);
81 // Can't store this data on PthreadCreate stack so we need a global
83 pthread_mutex_t Mutex
;
84 PTREAD_THUNK_THEAD_ENTRY Start
;
87 THREAD_MANGLE mThreadMangle
= {
88 PTHREAD_MUTEX_INITIALIZER
,
97 PTREAD_THUNK_THEAD_ENTRY Start
;
100 // Save global on the stack before we unlock
101 Start
= mThreadMangle
.Start
;
102 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
104 // Mask all signals to the APs
105 sigfillset (&SigMask
);
106 pthread_sigmask (SIG_BLOCK
, &SigMask
, NULL
);
109 // We have to start the thread in SEC as we need to follow
110 // OS X calling conventions. We can then call back into
111 // to the callers Start.
113 // This is a great example of how all problems in computer
114 // science can be solved by adding another level of indirection
116 return (VOID
*)ReverseGasketUint64 ((CALL_BACK
)Start
, (UINTN
)Context
);
123 IN PTREAD_THUNK_THEAD_ENTRY Start
,
128 BOOLEAN EnabledOnEntry
;
131 // Threads inherit interrupt state so disable interrupts before we start thread
133 if (SecInterruptEanbled ()) {
134 SecDisableInterrupt ();
135 EnabledOnEntry
= TRUE
;
137 EnabledOnEntry
= FALSE
;
140 // Aquire lock for global, SecFakePthreadStart runs in a different thread.
141 pthread_mutex_lock (&mThreadMangle
.Mutex
);
142 mThreadMangle
.Start
= Start
;
144 err
= pthread_create (Thread
, Attribute
, SecFakePthreadStart
, Context
);
146 // Thread failed to launch so release the lock;
147 pthread_mutex_unlock (&mThreadMangle
.Mutex
);
150 if (EnabledOnEntry
) {
151 // Restore interrupt state
152 SecEnableInterrupt ();
164 pthread_exit (ValuePtr
);
174 // POSIX currently allows pthread_t to be a structure or arithmetic type.
175 // Check out sys/types.h to make sure this will work if you are porting.
176 // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
177 return (UINTN
)pthread_self ();
181 EMU_PTREAD_THUNK_PROTOCOL gPthreadThunk
= {
182 GasketPthreadMutexLock
,
183 GasketPthreadMutexUnLock
,
184 GasketPthreadMutexTryLock
,
185 GasketPthreadMutexInit
,
186 GasketPthreadMutexDestroy
,
195 IN EMU_IO_THUNK_PROTOCOL
*This
198 if (This
->Instance
!= 0) {
199 // Only single instance is supported
200 return EFI_NOT_FOUND
;
203 if (This
->ConfigString
[0] == L
'0') {
204 // If AP count is zero no need for threads
205 return EFI_NOT_FOUND
;
208 This
->Interface
= &gPthreadThunk
;
216 IN EMU_IO_THUNK_PROTOCOL
*This
223 EMU_IO_THUNK_PROTOCOL gPthreadThunkIo
= {
224 &gEmuPthreadThunkProtocolGuid
,