Fix a bug reported by EDK940 "The main thread has not LeaveCriticalSection when be...
[people/mcb30/edk2.git] / edk2 / Nt32Pkg / TimerDxe / Timer.c
index 97ea733..d994441 100644 (file)
@@ -115,9 +115,12 @@ Returns:
   if (!mCancelTimerThread) {\r
   \r
     //\r
-    //  Suspend the main thread until we are done\r
+    // Suspend the main thread until we are done.\r
+    // Enter the critical section before suspending\r
+    // and leave the critical section after resuming\r
+    // to avoid deadlock between main and timer thread.\r
     //\r
-\r
+    gWinNt->EnterCriticalSection (&mNtCriticalSection);\r
     gWinNt->SuspendThread (mNtMainThreadHandle);\r
 \r
     //\r
@@ -127,6 +130,7 @@ Returns:
     //\r
     if (mCancelTimerThread) {\r
       gWinNt->ResumeThread (mNtMainThreadHandle);\r
+      gWinNt->LeaveCriticalSection (&mNtCriticalSection);\r
       gWinNt->timeKillEvent (wTimerID);\r
       mMMTimerThreadID = 0;\r
       return ;\r
@@ -138,6 +142,7 @@ Returns:
       //  Resume the main thread\r
       //\r
       gWinNt->ResumeThread (mNtMainThreadHandle);\r
+      gWinNt->LeaveCriticalSection (&mNtCriticalSection);\r
 \r
       //\r
       //  Wait for interrupts to be enabled.\r
@@ -151,6 +156,7 @@ Returns:
       //\r
       //  Suspend the main thread until we are done\r
       //\r
+      gWinNt->EnterCriticalSection (&mNtCriticalSection);\r
       gWinNt->SuspendThread (mNtMainThreadHandle);\r
       mCpu->GetInterruptState (mCpu, &InterruptState);\r
     }\r
@@ -174,9 +180,7 @@ Returns:
       //  expired since the last call is 10,000 times the number\r
       //  of ms.  (or 100ns units)\r
       //\r
-      gWinNt->EnterCriticalSection (&mNtCriticalSection);\r
       CallbackFunction = mTimerNotifyFunction;\r
-      gWinNt->LeaveCriticalSection (&mNtCriticalSection);\r
 \r
       //\r
       // Only invoke the callback function if a Non-NULL handler has been\r
@@ -194,6 +198,7 @@ Returns:
     //  Resume the main thread\r
     //\r
     gWinNt->ResumeThread (mNtMainThreadHandle);\r
+    gWinNt->LeaveCriticalSection (&mNtCriticalSection);\r
   } else {\r
     gWinNt->timeKillEvent (wTimerID);\r
     mMMTimerThreadID = 0;\r