public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Ruiyu Ni <ruiyu.ni@intel.com>
To: edk2-devel@lists.01.org
Cc: Hao Wu <hao.a.wu@intel.com>, Andrew Fish <afish@intel.com>
Subject: [PATCH 06/12] EmulatorPkg/Win: Add timer and interrupt support
Date: Thu, 23 Aug 2018 17:52:09 +0800	[thread overview]
Message-ID: <20180823095215.274248-7-ruiyu.ni@intel.com> (raw)
In-Reply-To: <20180823095215.274248-1-ruiyu.ni@intel.com>

Now the firmware can boot to Shell and count down 5 seconds to
command prompt.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
 EmulatorPkg/Win/Host/WinThunk.c | 194 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 194 insertions(+)

diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
index 69a61258f3..ffe71aef9a 100644
--- a/EmulatorPkg/Win/Host/WinThunk.c
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -205,12 +205,193 @@ SecFree (
   return TRUE;
 }
 
+
+
+//
+// Define a global that we can use to shut down the NT timer thread when
+// the timer is canceled.
+//
+BOOLEAN                 mCancelTimerThread = FALSE;
+
+//
+// The notification function to call on every timer interrupt
+//
+EMU_SET_TIMER_CALLBACK  *mTimerNotifyFunction = NULL;
+
+//
+// The thread handle for this driver
+//
+HANDLE                  mNtMainThreadHandle;
+
+//
+// The timer value from the last timer interrupt
+//
+UINT32                  mNtLastTick;
+
+//
+// Critical section used to update varibles shared between the main thread and
+// the timer interrupt thread.
+//
+CRITICAL_SECTION        mNtCriticalSection;
+
+//
+// Worker Functions
+//
+UINT                    mMMTimerThreadID = 0;
+
+volatile BOOLEAN        mInterruptEnabled = FALSE;
+
+VOID
+CALLBACK
+MMTimerThread (
+  UINT  wTimerID,
+  UINT  msg,
+  DWORD dwUser,
+  DWORD dw1,
+  DWORD dw2
+)
+{
+  UINT32            CurrentTick;
+  UINT32            Delta;
+
+  if (!mCancelTimerThread) {
+
+    //
+    // Suspend the main thread until we are done.
+    // Enter the critical section before suspending
+    // and leave the critical section after resuming
+    // to avoid deadlock between main and timer thread.
+    //
+    EnterCriticalSection (&mNtCriticalSection);
+    SuspendThread (mNtMainThreadHandle);
+
+    //
+    // If the timer thread is being canceled, then bail immediately.
+    // We check again here because there's a small window of time from when
+    // this thread was kicked off and when we suspended the main thread above.
+    //
+    if (mCancelTimerThread) {
+      ResumeThread (mNtMainThreadHandle);
+      LeaveCriticalSection (&mNtCriticalSection);
+      timeKillEvent (wTimerID);
+      mMMTimerThreadID = 0;
+      return;
+    }
+
+    while (!mInterruptEnabled) {
+      //
+      //  Resume the main thread
+      //
+      ResumeThread (mNtMainThreadHandle);
+      LeaveCriticalSection (&mNtCriticalSection);
+
+      //
+      //  Wait for interrupts to be enabled.
+      //
+      while (!mInterruptEnabled) {
+        Sleep (1);
+      }
+
+      //
+      //  Suspend the main thread until we are done
+      //
+      EnterCriticalSection (&mNtCriticalSection);
+      SuspendThread (mNtMainThreadHandle);
+    }
+
+    //
+    //  Get the current system tick
+    //
+    CurrentTick = GetTickCount ();
+    Delta = CurrentTick - mNtLastTick;
+    mNtLastTick = CurrentTick;
+
+    //
+    //  If delay was more then 1 second, ignore it (probably debugging case)
+    //
+    if (Delta < 1000) {
+
+      //
+      // Only invoke the callback function if a Non-NULL handler has been
+      // registered. Assume all other handlers are legal.
+      //
+      if (mTimerNotifyFunction != NULL) {
+        mTimerNotifyFunction (Delta);
+      }
+    }
+
+    //
+    //  Resume the main thread
+    //
+    ResumeThread (mNtMainThreadHandle);
+    LeaveCriticalSection (&mNtCriticalSection);
+  } else {
+    timeKillEvent (wTimerID);
+    mMMTimerThreadID = 0;
+  }
+
+}
+
 VOID
 SecSetTimer (
   IN  UINT64                  TimerPeriod,
   IN  EMU_SET_TIMER_CALLBACK  Callback
 )
 {
+  //
+// If TimerPeriod is 0, then the timer thread should be canceled
+//
+  if (TimerPeriod == 0) {
+    //
+    // Cancel the timer thread
+    //
+    EnterCriticalSection (&mNtCriticalSection);
+
+    mCancelTimerThread = TRUE;
+
+    LeaveCriticalSection (&mNtCriticalSection);
+
+    //
+    // Wait for the timer thread to exit
+    //
+
+    if (mMMTimerThreadID != 0) {
+      timeKillEvent (mMMTimerThreadID);
+      mMMTimerThreadID = 0;
+    }
+  } else {
+    //
+    // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
+    //
+    EnterCriticalSection (&mNtCriticalSection);
+
+    mCancelTimerThread = FALSE;
+
+    LeaveCriticalSection (&mNtCriticalSection);
+
+    //
+    //  Get the starting tick location if we are just starting the timer thread
+    //
+    mNtLastTick = GetTickCount ();
+
+    if (mMMTimerThreadID) {
+      timeKillEvent (mMMTimerThreadID);
+    }
+
+    SetThreadPriority (
+      GetCurrentThread (),
+      THREAD_PRIORITY_HIGHEST
+    );
+
+    mMMTimerThreadID = timeSetEvent (
+      (UINT)TimerPeriod,
+      0,
+      MMTimerThread,
+      (DWORD_PTR)NULL,
+      TIME_PERIODIC | TIME_KILL_SYNCHRONOUS | TIME_CALLBACK_FUNCTION
+    );
+  }
+  mTimerNotifyFunction = Callback;
 }
 
 VOID
@@ -218,6 +399,17 @@ SecInitializeThunk (
   VOID
 )
 {
+  InitializeCriticalSection (&mNtCriticalSection);
+
+  DuplicateHandle (
+    GetCurrentProcess (),
+    GetCurrentThread (),
+    GetCurrentProcess (),
+    &mNtMainThreadHandle,
+    0,
+    FALSE,
+    DUPLICATE_SAME_ACCESS
+  );
 }
 
 VOID
@@ -225,6 +417,7 @@ SecEnableInterrupt (
   VOID
   )
 {
+  mInterruptEnabled = TRUE;
 }
 
 
@@ -233,6 +426,7 @@ SecDisableInterrupt (
   VOID
   )
 {
+  mInterruptEnabled = FALSE;
 }
 
 
-- 
2.16.1.windows.1



  parent reply	other threads:[~2018-08-23  9:51 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-23  9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
2018-08-23  9:52 ` [PATCH 01/12] EmulatorPkg/ThunkProtocolList: Fix VS build failure Ruiyu Ni
2018-08-23  9:52 ` [PATCH 02/12] EmulatorPkg/Win: Add Windows host support Ruiyu Ni
2018-08-23  9:52 ` [PATCH 03/12] EmulatorPkg/Win: Enable source level debugging Ruiyu Ni
2018-08-23  9:52 ` [PATCH 04/12] EmulatorPkg/Win: Enable native OS console as firmware console Ruiyu Ni
2018-08-23  9:52 ` [PATCH 05/12] EmulatorPkg/Win: Add input/output support Ruiyu Ni
2018-08-23  9:52 ` Ruiyu Ni [this message]
2018-08-23  9:52 ` [PATCH 07/12] EmulatorPkg/Win: Add RTC support Ruiyu Ni
2018-08-23  9:52 ` [PATCH 08/12] EmulatorPkg/Win: Add SimpleFileSystem support Ruiyu Ni
2018-08-23  9:52 ` [PATCH 09/12] EmulatorPkg/Win: Add BlockIo support Ruiyu Ni
2018-08-23  9:52 ` [PATCH 10/12] EmulatorPkg/PlatformBds: Signal EndOfDxe in platform BDS Ruiyu Ni
2018-08-23  9:52 ` [PATCH 11/12] EmulatorPkg/EmuFileSystem: Fix a bug that causes Close() assertion Ruiyu Ni
2018-08-23  9:52 ` [PATCH 12/12] EmulatorPkg/DSC: Remove FS mapping to EDK Shell bin directory Ruiyu Ni
2018-08-23  9:56 ` [PATCH 00/12] Add WinHost support in EmulatorPkg Ni, Ruiyu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180823095215.274248-7-ruiyu.ni@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox