EmulatorPkg: Add IsSigTermSignaled mechanism.

When Host app receiving SigTerm signal, the background threads may not
receive the same. This IsSigTermSignaled can be used for background
threads to do the graceful termination.

Change-Id: I77374ad2a88b5a015ab8564560cbd95f4bd7ae5d
Hsd-es-id: <HSD-ES bug/ise id>
Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
diff --git a/EmulatorPkg/Include/Library/EmuSignalLib.h b/EmulatorPkg/Include/Library/EmuSignalLib.h
index e4f6f36..25d6666 100644
--- a/EmulatorPkg/Include/Library/EmuSignalLib.h
+++ b/EmulatorPkg/Include/Library/EmuSignalLib.h
@@ -47,4 +47,27 @@
   IN      UINTN                       SignalNumber
   );
 
+/**
+  Get IsSigTermSignaled value.
+
+  @retval        Value             current IsSigTermSignaled value.
+
+**/
+UINT32
+EFIAPI
+EmuGetIsSigTermSignaled (
+  VOID
+  );
+
+/**
+  Set IsSigTermSignaled value.
+
+  @param[in]        Value             desired IsSigTermSignaled value.
+
+**/
+VOID
+EFIAPI
+EmuSetIsSigTermSignaled (
+  IN      UINT32                       value
+  );
 #endif
diff --git a/EmulatorPkg/Include/Protocol/EmuSignal.h b/EmulatorPkg/Include/Protocol/EmuSignal.h
index 0af1c67..114749e 100644
--- a/EmulatorPkg/Include/Protocol/EmuSignal.h
+++ b/EmulatorPkg/Include/Protocol/EmuSignal.h
@@ -87,10 +87,34 @@
   IN      UINTN                       SignalNumber
   );
 
+/**
+  Get IsSigTermSignaled value.
+
+  @retval IsSigTermSignaled value
+
+**/
+typedef
+UINT32
+(EFIAPI *EMU_GET_IS_SIGTERM_SIGNALED)(
+  VOID
+  );
+
+/**
+  Set IsSigTermSignaled value.
+  @param[in]  value for IsSigTermSignaled
+
+**/
+typedef
+VOID
+(EFIAPI *EMU_SET_IS_SIGTERM_SIGNALED)(
+  IN      UINT32                       value
+  );
 
 struct _EMU_SIGNAL_THUNK_PROTOCOL {
   EMU_SIGNAL_REGISTER_SIGNAL_HANDLER                          RegisterSignalHandler;
   EMU_SIGNAL_UNREGISTER_SIGNAL_HANDLER                        UnregisterSignalHandler;
+  EMU_GET_IS_SIGTERM_SIGNALED                                 GetIsSigTermSignaled;
+  EMU_SET_IS_SIGTERM_SIGNALED                                 SetIsSigTermSignaled;
 };
 
 #endif
diff --git a/EmulatorPkg/Library/DxeEmuSignalLib/DxeEmuSignalLib.c b/EmulatorPkg/Library/DxeEmuSignalLib/DxeEmuSignalLib.c
index 54d7d5d..b69e915 100644
--- a/EmulatorPkg/Library/DxeEmuSignalLib/DxeEmuSignalLib.c
+++ b/EmulatorPkg/Library/DxeEmuSignalLib/DxeEmuSignalLib.c
@@ -110,3 +110,41 @@
   ASSERT (gEmuSignal != NULL);
   return gEmuSignal->UnregisterSignalHandler (SignalNumber);
 }
+
+/**
+  Get IsSigTermSignaled value.
+
+  @retval        Value             current IsSigTermSignaled value.
+
+**/
+UINT32
+EFIAPI
+EmuGetIsSigTermSignaled (
+  VOID
+  )
+{
+  UINT32           value;
+
+  ASSERT (gEmuSignal != NULL);
+  value = gEmuSignal->GetIsSigTermSignaled();
+
+  return value;
+}
+
+/**
+  Set IsSigTermSignaled value.
+
+  @param[in]        Value             desired IsSigTermSignaled value.
+
+**/
+VOID
+EFIAPI
+EmuSetIsSigTermSignaled (
+  IN      UINT32                       value
+  )
+{
+  ASSERT (gEmuSignal != NULL);
+  gEmuSignal->SetIsSigTermSignaled(value);
+
+  return;
+}
\ No newline at end of file
diff --git a/EmulatorPkg/Unix/Host/Arm/Gasket.c b/EmulatorPkg/Unix/Host/Arm/Gasket.c
index 83da57a..9fcb8bb 100644
--- a/EmulatorPkg/Unix/Host/Arm/Gasket.c
+++ b/EmulatorPkg/Unix/Host/Arm/Gasket.c
@@ -964,3 +964,21 @@
 {
   return SignalClose (This);
 }
+
+UINT32
+EFIAPI
+GasketGetIsSigTermSignaled (
+  VOID
+  )
+{
+  return GetIsSigTermSignaled ();
+}
+
+VOID
+EFIAPI
+GasketSetIsSigTermSignaled (
+  IN      UINT32   value
+  )
+{
+  return SetIsSigTermSignaled (value);
+}
diff --git a/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h b/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
index 89e6f6f..07152e0 100644
--- a/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
+++ b/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
@@ -1168,4 +1168,28 @@
   IN  EMU_IO_THUNK_PROTOCOL  *This
   );
 
+/**
+  Get IsSigTermSignaled value.
+
+  @retval        Value             current IsSigTermSignaled value.
+
+**/
+UINT32
+EFIAPI
+GetIsSigTermSignaled (
+  VOID
+  );
+
+/**
+  Set IsSigTermSignaled value.
+
+  @param[in]        Value             desired IsSigTermSignaled value.
+
+**/
+VOID
+EFIAPI
+SetIsSigTermSignaled (
+  IN      UINT32   value
+  );
+
 #endif
diff --git a/EmulatorPkg/Unix/Host/Gasket.h b/EmulatorPkg/Unix/Host/Gasket.h
index 930a99d..50f40fc 100644
--- a/EmulatorPkg/Unix/Host/Gasket.h
+++ b/EmulatorPkg/Unix/Host/Gasket.h
@@ -700,4 +700,28 @@
   IN  EMU_IO_THUNK_PROTOCOL  *This

   );

 

+/**

+  Get IsSigTermSignaled value.

+

+  @retval        value             current IsSigTermSignaled value.

+

+**/

+UINT32

+EFIAPI

+GasketGetIsSigTermSignaled (

+  VOID

+  );

+

+/**

+  Set IsSigTermSignaled value.

+

+  @param[in]        value             desired IsSigTermSignaled value.

+

+**/

+VOID

+EFIAPI

+GasketSetIsSigTermSignaled (

+  IN      UINT32    value

+  );

+

 #endif

diff --git a/EmulatorPkg/Unix/Host/Ia32/Gasket.S b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
index 2418632..dd850c1 100644
--- a/EmulatorPkg/Unix/Host/Ia32/Gasket.S
+++ b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
@@ -1567,4 +1567,28 @@
   leave

   ret

 

+ASM_GLOBAL ASM_PFX(GasketGetIsSigTermSignaled)

+ASM_PFX(GasketGetIsSigTermSignaled):

+  pushl %ebp

+  movl  %esp, %ebp

+  subl  $24, %esp      // sub extra 16 from the stack for alignment

+  and   $-16, %esp    // stack needs to end in 0xFFFFFFF0 before call

 

+  call    ASM_PFX(GetIsSigTermSignaled)

+

+  leave

+  ret

+

+ASM_GLOBAL ASM_PFX(GasketSetIsSigTermSignaled)

+ASM_PFX(GasketSetIsSigTermSignaled):

+  pushl %ebp

+  movl  %esp, %ebp

+  subl  $24, %esp      // sub extra 16 from the stack for alignment

+  and   $-16, %esp    // stack needs to end in 0xFFFFFFF0 before call

+  movl  8(%ebp), %eax

+  movl  %eax, (%esp)

+

+  call    ASM_PFX(SetIsSigTermSignaled)

+

+  leave

+  ret

diff --git a/EmulatorPkg/Unix/Host/Signal.c b/EmulatorPkg/Unix/Host/Signal.c
index a048b24..7cd7160 100644
--- a/EmulatorPkg/Unix/Host/Signal.c
+++ b/EmulatorPkg/Unix/Host/Signal.c
@@ -13,6 +13,9 @@
 STATIC EMU_SIGNAL_HANDLER  mSigSegvHandler = NULL;
 STATIC EMU_SIGNAL_HANDLER  mSigTermHandler = NULL;
 
+UINT32  mIsSigTermSignaled = 0;
+VOID    *mMutex = NULL;
+
 /**
   Converts from emulator thunk signal numbers to UNIX signal numbers. Emulator
   thunk signal numbers exist so that the only place platform-specific UNIX
@@ -261,9 +264,74 @@
   return EFI_SUCCESS;
 }
 
+UINTN
+EFIAPI
+PthreadMutexLock (
+  IN VOID  *Mutex
+  );
+
+UINTN
+EFIAPI
+PthreadMutexUnLock (
+  IN VOID  *Mutex
+  );
+
+VOID *
+PthreadMutexInit (
+  IN VOID
+  );
+
+/**
+  Get IsSigTermSignaled value.
+
+  @retval        Value             current IsSigTermSignaled value.
+
+**/
+UINT32
+EFIAPI
+GetIsSigTermSignaled (
+  VOID
+  )
+{
+  UINT32           value;
+
+  if (mMutex == NULL) {
+    mMutex = PthreadMutexInit();
+  }
+  PthreadMutexLock(mMutex);
+  value = mIsSigTermSignaled;
+  PthreadMutexUnLock(mMutex);
+
+  return value;
+}
+
+/**
+  Set IsSigTermSignaled value.
+
+  @param[in]        Value             desired IsSigTermSignaled value.
+
+**/
+VOID
+EFIAPI
+SetIsSigTermSignaled (
+  IN      UINT32   value
+  )
+{
+  if (mMutex == NULL) {
+    mMutex = PthreadMutexInit();
+  }
+  PthreadMutexLock(mMutex);
+  mIsSigTermSignaled = value;
+  PthreadMutexUnLock(mMutex);
+
+  return;
+}
+
 EMU_SIGNAL_THUNK_PROTOCOL  gEmuSignalThunk = {
   GasketRegisterSignalHandler,
-  GasketUnregisterSignalHandler
+  GasketUnregisterSignalHandler,
+  GasketGetIsSigTermSignaled,
+  GasketSetIsSigTermSignaled
 };
 
 EFI_STATUS
diff --git a/EmulatorPkg/Unix/Host/X64/Gasket.S b/EmulatorPkg/Unix/Host/X64/Gasket.S
index ae1126c..e0d23e3 100644
--- a/EmulatorPkg/Unix/Host/X64/Gasket.S
+++ b/EmulatorPkg/Unix/Host/X64/Gasket.S
@@ -1712,4 +1712,35 @@
   popq    %rbp

   ret

 

+ASM_GLOBAL ASM_PFX(GasketGetIsSigTermSignaled)

+ASM_PFX(GasketGetIsSigTermSignaled):

+  pushq   %rbp            // stack frame is for the debugger

+  movq    %rsp, %rbp

 

+  pushq   %rsi          // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI

+  pushq   %rdi

+

+

+  call    ASM_PFX(GetIsSigTermSignaled)

+

+  popq    %rdi          // restore state

+  popq    %rsi

+  popq    %rbp

+  ret

+

+ASM_GLOBAL ASM_PFX(GasketSetIsSigTermSignaled)

+ASM_PFX(GasketSetIsSigTermSignaled):

+  pushq   %rbp            // stack frame is for the debugger

+  movq    %rsp, %rbp

+

+  pushq   %rsi          // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI

+  pushq   %rdi

+

+  movq    %rcx, %rdi    // Swizzle args

+

+  call    ASM_PFX(SetIsSigTermSignaled)

+

+  popq    %rdi          // restore state

+  popq    %rsi

+  popq    %rbp

+  ret