-/*++ @file
- POSIX Pthreads to emulate APs and implement threads
-
-Copyright (c) 2011, Apple Inc. All rights reserved.
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
-
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-
-**/
-
-#include "Host.h"
-#include <pthread.h>
-
-
-UINTN
-EFIAPI
-PthreadMutexLock (
- IN VOID *Mutex
- )
-{
- return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex);
-}
-
-
-
-UINTN
-EFIAPI
-PthreadMutexUnLock (
- IN VOID *Mutex
- )
-{
- return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex);
-}
-
-
-UINTN
-EFIAPI
-PthreadMutexTryLock (
- IN VOID *Mutex
- )
-{
- return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex);
-}
-
-
-VOID *
-PthreadMutexInit (
- IN VOID
- )
-{
- pthread_mutex_t *Mutex;
- int err;
-
- Mutex = malloc (sizeof (pthread_mutex_t));
- err = pthread_mutex_init (Mutex, NULL);
- if (err == 0) {
- return Mutex;
- }
-
- return NULL;
-}
-
-
-UINTN
-PthreadMutexDestroy (
- IN VOID *Mutex
- )
-{
- if (Mutex != NULL) {
- return pthread_mutex_destroy ((pthread_mutex_t *)Mutex);
- }
-
- return -1;
-}
-
-// Can't store this data on PthreadCreate stack so we need a global
-typedef struct {
- pthread_mutex_t Mutex;
- THREAD_THUNK_THREAD_ENTRY Start;
-} THREAD_MANGLE;
-
-THREAD_MANGLE mThreadMangle = {
- PTHREAD_MUTEX_INITIALIZER,
- NULL
-};
-
-VOID *
-SecFakePthreadStart (
- VOID *Context
- )
-{
- THREAD_THUNK_THREAD_ENTRY Start;
- sigset_t SigMask;
-
- // Save global on the stack before we unlock
- Start = mThreadMangle.Start;
- pthread_mutex_unlock (&mThreadMangle.Mutex);
-
- // Mask all signals to the APs
- sigfillset (&SigMask);
- pthread_sigmask (SIG_BLOCK, &SigMask, NULL);
-
- //
- // We have to start the thread in SEC as we need to follow
- // OS X calling conventions. We can then call back into
- // to the callers Start.
- //
- // This is a great example of how all problems in computer
- // science can be solved by adding another level of indirection
- //
- return (VOID *)ReverseGasketUint64 ((CALL_BACK)Start, (UINTN)Context);
-}
-
-UINTN
-PthreadCreate (
- IN VOID *Thread,
- IN VOID *Attribute,
- IN THREAD_THUNK_THREAD_ENTRY Start,
- IN VOID *Context
- )
-{
- int err;
- BOOLEAN EnabledOnEntry;
-
- //
- // Threads inherit interrupt state so disable interrupts before we start thread
- //
- if (SecInterruptEanbled ()) {
- SecDisableInterrupt ();
- EnabledOnEntry = TRUE;
- } else {
- EnabledOnEntry = FALSE;
- }
-
- // Aquire lock for global, SecFakePthreadStart runs in a different thread.
- pthread_mutex_lock (&mThreadMangle.Mutex);
- mThreadMangle.Start = Start;
-
- err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context);
- if (err != 0) {
- // Thread failed to launch so release the lock;
- pthread_mutex_unlock (&mThreadMangle.Mutex);
- }
-
- if (EnabledOnEntry) {
- // Restore interrupt state
- SecEnableInterrupt ();
- }
-
- return err;
-}
-
-
-VOID
-PthreadExit (
- IN VOID *ValuePtr
- )
-{
- pthread_exit (ValuePtr);
- return;
-}
-
-
-UINTN
-PthreadSelf (
- VOID
- )
-{
- // POSIX currently allows pthread_t to be a structure or arithmetic type.
- // Check out sys/types.h to make sure this will work if you are porting.
- // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
- return (UINTN)pthread_self ();
-}
-
-
-EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = {
- GasketPthreadMutexLock,
- GasketPthreadMutexUnLock,
- GasketPthreadMutexTryLock,
- GasketPthreadMutexInit,
- GasketPthreadMutexDestroy,
- GasketPthreadCreate,
- GasketPthreadExit,
- GasketPthreadSelf
-};
-
-
-EFI_STATUS
-PthreadOpen (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- if (This->Instance != 0) {
- // Only single instance is supported
- return EFI_NOT_FOUND;
- }
-
- if (This->ConfigString[0] == L'0') {
- // If AP count is zero no need for threads
- return EFI_NOT_FOUND;
- }
-
- This->Interface = &gPthreadThunk;
-
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-PthreadClose (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- return EFI_SUCCESS;
-}
-
-
-EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = {
- &gEmuThreadThunkProtocolGuid,
- NULL,
- NULL,
- 0,
- GasketPthreadOpen,
- GasketPthreadClose,
- NULL
-};
-
-
+/*++ @file\r
+ POSIX Pthreads to emulate APs and implement threads\r
+\r
+Copyright (c) 2011, Apple Inc. All rights reserved.\r
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "Host.h"\r
+#include <pthread.h>\r
+\r
+\r
+UINTN\r
+EFIAPI\r
+PthreadMutexLock (\r
+ IN VOID *Mutex\r
+ )\r
+{\r
+ return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex);\r
+}\r
+\r
+\r
+\r
+UINTN\r
+EFIAPI\r
+PthreadMutexUnLock (\r
+ IN VOID *Mutex\r
+ )\r
+{\r
+ return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex);\r
+}\r
+\r
+\r
+UINTN\r
+EFIAPI\r
+PthreadMutexTryLock (\r
+ IN VOID *Mutex\r
+ )\r
+{\r
+ return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex);\r
+}\r
+\r
+\r
+VOID *\r
+PthreadMutexInit (\r
+ IN VOID\r
+ )\r
+{\r
+ pthread_mutex_t *Mutex;\r
+ int err;\r
+\r
+ Mutex = malloc (sizeof (pthread_mutex_t));\r
+ err = pthread_mutex_init (Mutex, NULL);\r
+ if (err == 0) {\r
+ return Mutex;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+UINTN\r
+PthreadMutexDestroy (\r
+ IN VOID *Mutex\r
+ )\r
+{\r
+ if (Mutex != NULL) {\r
+ return pthread_mutex_destroy ((pthread_mutex_t *)Mutex);\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+// Can't store this data on PthreadCreate stack so we need a global\r
+typedef struct {\r
+ pthread_mutex_t Mutex;\r
+ THREAD_THUNK_THREAD_ENTRY Start;\r
+} THREAD_MANGLE;\r
+\r
+THREAD_MANGLE mThreadMangle = {\r
+ PTHREAD_MUTEX_INITIALIZER,\r
+ NULL\r
+};\r
+\r
+VOID *\r
+SecFakePthreadStart (\r
+ VOID *Context\r
+ )\r
+{\r
+ THREAD_THUNK_THREAD_ENTRY Start;\r
+ sigset_t SigMask;\r
+\r
+ // Save global on the stack before we unlock\r
+ Start = mThreadMangle.Start;\r
+ pthread_mutex_unlock (&mThreadMangle.Mutex);\r
+\r
+ // Mask all signals to the APs\r
+ sigfillset (&SigMask);\r
+ pthread_sigmask (SIG_BLOCK, &SigMask, NULL);\r
+\r
+ //\r
+ // We have to start the thread in SEC as we need to follow\r
+ // OS X calling conventions. We can then call back into\r
+ // to the callers Start.\r
+ //\r
+ // This is a great example of how all problems in computer\r
+ // science can be solved by adding another level of indirection\r
+ //\r
+ return (VOID *)ReverseGasketUint64 ((CALL_BACK)Start, (UINTN)Context);\r
+}\r
+\r
+UINTN\r
+PthreadCreate (\r
+ IN VOID *Thread,\r
+ IN VOID *Attribute,\r
+ IN THREAD_THUNK_THREAD_ENTRY Start,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ int err;\r
+ BOOLEAN EnabledOnEntry;\r
+\r
+ //\r
+ // Threads inherit interrupt state so disable interrupts before we start thread\r
+ //\r
+ if (SecInterruptEanbled ()) {\r
+ SecDisableInterrupt ();\r
+ EnabledOnEntry = TRUE;\r
+ } else {\r
+ EnabledOnEntry = FALSE;\r
+ }\r
+\r
+ // Aquire lock for global, SecFakePthreadStart runs in a different thread.\r
+ pthread_mutex_lock (&mThreadMangle.Mutex);\r
+ mThreadMangle.Start = Start;\r
+\r
+ err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context);\r
+ if (err != 0) {\r
+ // Thread failed to launch so release the lock;\r
+ pthread_mutex_unlock (&mThreadMangle.Mutex);\r
+ }\r
+\r
+ if (EnabledOnEntry) {\r
+ // Restore interrupt state\r
+ SecEnableInterrupt ();\r
+ }\r
+\r
+ return err;\r
+}\r
+\r
+\r
+VOID\r
+PthreadExit (\r
+ IN VOID *ValuePtr\r
+ )\r
+{\r
+ pthread_exit (ValuePtr);\r
+ return;\r
+}\r
+\r
+\r
+UINTN\r
+PthreadSelf (\r
+ VOID\r
+ )\r
+{\r
+ // POSIX currently allows pthread_t to be a structure or arithmetic type.\r
+ // Check out sys/types.h to make sure this will work if you are porting.\r
+ // On OS X (Darwin) pthread_t is a pointer to a structure so this code works.\r
+ return (UINTN)pthread_self ();\r
+}\r
+\r
+\r
+EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = {\r
+ GasketPthreadMutexLock,\r
+ GasketPthreadMutexUnLock,\r
+ GasketPthreadMutexTryLock,\r
+ GasketPthreadMutexInit,\r
+ GasketPthreadMutexDestroy,\r
+ GasketPthreadCreate,\r
+ GasketPthreadExit,\r
+ GasketPthreadSelf\r
+};\r
+\r
+\r
+EFI_STATUS\r
+PthreadOpen (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ if (This->Instance != 0) {\r
+ // Only single instance is supported\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (This->ConfigString[0] == L'0') {\r
+ // If AP count is zero no need for threads\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ This->Interface = &gPthreadThunk;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PthreadClose (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = {\r
+ &gEmuThreadThunkProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ GasketPthreadOpen,\r
+ GasketPthreadClose,\r
+ NULL\r
+};\r
+\r
+\r