]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmulatorPkg/CpuRuntimeDxe/MpService.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / MpService.c
index 792d0e4eb07d95bfc03216bd14bd47e8e02c6563..42f94ada27f483a670c81c486e3a224f76dd75f3 100644 (file)
 \r
 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
 Portitions Copyright (c) 2011, Apple Inc. All rights reserved.\r
-This program and the accompanying materials are licensed and made available under\r
-the terms and conditions of the BSD License that accompanies this distribution.\r
-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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 \r
 **/\r
@@ -111,8 +105,31 @@ GetNextBlockedNumber (
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
+ * Calculated and stalled the interval time by BSP to check whether\r
+ * the APs have finished.\r
+ *\r
+ * @param[in]  Timeout    The time limit in microseconds for\r
+ *                        APs to return from Procedure.\r
+ *\r
+ * @retval     StallTime  Time of execution stall.\r
+**/\r
+UINTN\r
+CalculateAndStallInterval (\r
+  IN UINTN                  Timeout\r
+  )\r
+{\r
+  UINTN                 StallTime;\r
 \r
+  if (Timeout < gPollInterval && Timeout != 0) {\r
+    StallTime = Timeout;\r
+  } else {\r
+    StallTime = gPollInterval;\r
+  }\r
+  gBS->Stall (StallTime);\r
 \r
+  return StallTime;\r
+}\r
 \r
 /**\r
   This service retrieves the number of logical processor in the platform\r
@@ -378,7 +395,7 @@ CpuMpServicesStartupAllAps (
   UINTN                 NextNumber;\r
   PROCESSOR_STATE       APInitialState;\r
   PROCESSOR_STATE       ProcessorState;\r
-  INTN                  Timeout;\r
+  UINTN                 Timeout;\r
 \r
 \r
   if (!IsBSP ()) {\r
@@ -397,6 +414,24 @@ CpuMpServicesStartupAllAps (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
+  for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {\r
+    ProcessorData = &gMPSystem.ProcessorData[Number];\r
+    if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+      // Skip BSP\r
+      continue;\r
+    }\r
+\r
+    if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+      // Skip Disabled processors\r
+      continue;\r
+    }\r
+    gThread->MutexLock(ProcessorData->StateLock);\r
+    if (ProcessorData->State != CPU_STATE_IDLE) {\r
+      gThread->MutexUnlock (ProcessorData->StateLock);\r
+      return EFI_NOT_READY;\r
+    }\r
+    gThread->MutexUnlock(ProcessorData->StateLock);\r
+  }\r
 \r
   if (FailedCpuList != NULL) {\r
     gMPSystem.FailedList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
@@ -437,18 +472,14 @@ CpuMpServicesStartupAllAps (
     // state 1 by 1, until the previous 1 finished its task\r
     // if not "SingleThread", all APs are put to ready state from the beginning\r
     //\r
-    if (ProcessorData->State == CPU_STATE_IDLE) {\r
-      gMPSystem.StartCount++;\r
-\r
-      gThread->MutexLock (&ProcessorData->StateLock);\r
-      ProcessorData->State = APInitialState;\r
-      gThread->MutexUnlock (&ProcessorData->StateLock);\r
+    gThread->MutexLock(ProcessorData->StateLock);\r
+    ASSERT (ProcessorData->State == CPU_STATE_IDLE);\r
+    ProcessorData->State = APInitialState;\r
+    gThread->MutexUnlock (ProcessorData->StateLock);\r
 \r
-      if (SingleThread) {\r
-        APInitialState = CPU_STATE_BLOCKED;\r
-      }\r
-    } else {\r
-      return EFI_NOT_READY;\r
+    gMPSystem.StartCount++;\r
+    if (SingleThread) {\r
+      APInitialState = CPU_STATE_BLOCKED;\r
     }\r
   }\r
 \r
@@ -465,7 +496,13 @@ CpuMpServicesStartupAllAps (
         continue;\r
       }\r
 \r
-      SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
+      gThread->MutexLock (ProcessorData->StateLock);\r
+      ProcessorState = ProcessorData->State;\r
+      gThread->MutexUnlock (ProcessorData->StateLock);\r
+\r
+      if (ProcessorState == CPU_STATE_READY) {\r
+        SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
+      }\r
     }\r
 \r
     //\r
@@ -512,11 +549,16 @@ CpuMpServicesStartupAllAps (
         if (SingleThread) {\r
           Status = GetNextBlockedNumber (&NextNumber);\r
           if (!EFI_ERROR (Status)) {\r
+            gThread->MutexLock (gMPSystem.ProcessorData[NextNumber].StateLock);\r
             gMPSystem.ProcessorData[NextNumber].State = CPU_STATE_READY;\r
+            gThread->MutexUnlock (gMPSystem.ProcessorData[NextNumber].StateLock);\r
           }\r
         }\r
 \r
+        gThread->MutexLock (ProcessorData->StateLock);\r
         ProcessorData->State = CPU_STATE_IDLE;\r
+        gThread->MutexUnlock (ProcessorData->StateLock);\r
+\r
         break;\r
 \r
       default:\r
@@ -529,13 +571,12 @@ CpuMpServicesStartupAllAps (
       goto Done;\r
     }\r
 \r
-    if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
+    if ((TimeoutInMicroseconds != 0) && (Timeout == 0)) {\r
       Status = EFI_TIMEOUT;\r
       goto Done;\r
     }\r
 \r
-    gBS->Stall (gPollInterval);\r
-    Timeout -= gPollInterval;\r
+    Timeout -= CalculateAndStallInterval (Timeout);\r
   }\r
 \r
 Done:\r
@@ -648,7 +689,7 @@ CpuMpServicesStartupThisAP (
   OUT BOOLEAN                   *Finished               OPTIONAL\r
   )\r
 {\r
-  INTN            Timeout;\r
+  UINTN            Timeout;\r
 \r
   if (!IsBSP ()) {\r
     return EFI_DEVICE_ERROR;\r
@@ -666,9 +707,16 @@ CpuMpServicesStartupThisAP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if ((gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  gThread->MutexLock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
   if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+    gThread->MutexUnlock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
     return EFI_NOT_READY;\r
   }\r
+  gThread->MutexUnlock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
 \r
   if ((WaitEvent != NULL)  && gReadToBoot) {\r
     return EFI_UNSUPPORTED;\r
@@ -694,21 +742,20 @@ CpuMpServicesStartupThisAP (
 \r
   // Blocking\r
   while (TRUE) {\r
-    gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+    gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
     if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {\r
       gMPSystem.ProcessorData[ProcessorNumber].State = CPU_STATE_IDLE;\r
-      gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+      gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
       break;\r
     }\r
 \r
-    gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+    gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
 \r
-    if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
+    if ((TimeoutInMicroseconds != 0) && (Timeout == 0)) {\r
       return EFI_TIMEOUT;\r
     }\r
 \r
-    gBS->Stall (gPollInterval);\r
-    Timeout -= gPollInterval;\r
+    Timeout -= CalculateAndStallInterval (Timeout);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -784,9 +831,12 @@ CpuMpServicesSwitchBSP (
   }\r
   ASSERT (Index != gMPSystem.NumberOfProcessors);\r
 \r
+  gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
   if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+    gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
     return EFI_NOT_READY;\r
   }\r
+  gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
 \r
   // Skip for now as we need switch a bunch of stack stuff around and it's complex\r
   // May not be worth it?\r
@@ -856,11 +906,12 @@ CpuMpServicesEnableDisableAP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
   if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+    gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
     return EFI_UNSUPPORTED;\r
   }\r
-\r
-  gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+  gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
 \r
   if (EnableAP) {\r
     if ((gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0 ) {\r
@@ -879,8 +930,6 @@ CpuMpServicesEnableDisableAP (
     gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag |= (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT);\r
   }\r
 \r
-  gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -971,13 +1020,12 @@ CpuCheckAllAPsStatus (
   BOOLEAN               Found;\r
 \r
   if (gMPSystem.TimeoutActive) {\r
-    gMPSystem.Timeout -= gPollInterval;\r
+    gMPSystem.Timeout -= CalculateAndStallInterval (gMPSystem.Timeout);\r
   }\r
 \r
-  ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
-\r
   for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
-    if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+    ProcessorData = &gMPSystem.ProcessorData[ProcessorNumber];\r
+    if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
      // Skip BSP\r
       continue;\r
     }\r
@@ -992,33 +1040,31 @@ CpuCheckAllAPsStatus (
     // context. Meaning deadlock. Which is a bad thing.\r
     // So, try lock it. If we can get it, cool, do our thing.\r
     // otherwise, just dump out & try again on the next iteration.\r
-    Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+    Status = gThread->MutexTryLock (ProcessorData->StateLock);\r
     if (EFI_ERROR(Status)) {\r
       return;\r
     }\r
-    ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
-    gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+    ProcessorState = ProcessorData->State;\r
+    gThread->MutexUnlock (ProcessorData->StateLock);\r
 \r
     switch (ProcessorState) {\r
-    case CPU_STATE_READY:\r
-      SetApProcedure (ProcessorData, gMPSystem.Procedure, gMPSystem.ProcedureArgument);\r
-      break;\r
-\r
     case CPU_STATE_FINISHED:\r
       if (gMPSystem.SingleThread) {\r
         Status = GetNextBlockedNumber (&NextNumber);\r
         if (!EFI_ERROR (Status)) {\r
           NextData = &gMPSystem.ProcessorData[NextNumber];\r
 \r
-          gThread->MutexLock (&NextData->ProcedureLock);\r
+          gThread->MutexLock (NextData->StateLock);\r
           NextData->State = CPU_STATE_READY;\r
-          gThread->MutexUnlock (&NextData->ProcedureLock);\r
+          gThread->MutexUnlock (NextData->StateLock);\r
 \r
           SetApProcedure (NextData, gMPSystem.Procedure, gMPSystem.ProcedureArgument);\r
         }\r
       }\r
 \r
-      gMPSystem.ProcessorData[ProcessorNumber].State = CPU_STATE_IDLE;\r
+      gThread->MutexLock (ProcessorData->StateLock);\r
+      ProcessorData->State = CPU_STATE_IDLE;\r
+      gThread->MutexUnlock (ProcessorData->StateLock);\r
       gMPSystem.FinishCount++;\r
       break;\r
 \r
@@ -1027,13 +1073,14 @@ CpuCheckAllAPsStatus (
     }\r
   }\r
 \r
-  if (gMPSystem.TimeoutActive && gMPSystem.Timeout < 0) {\r
+  if (gMPSystem.TimeoutActive && gMPSystem.Timeout == 0) {\r
     //\r
     // Timeout\r
     //\r
     if (gMPSystem.FailedList != NULL) {\r
       for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
-        if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+        ProcessorData = &gMPSystem.ProcessorData[ProcessorNumber];\r
+        if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
          // Skip BSP\r
           continue;\r
         }\r
@@ -1044,12 +1091,12 @@ CpuCheckAllAPsStatus (
         }\r
 \r
         // Mark the\r
-        Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+        Status = gThread->MutexTryLock (ProcessorData->StateLock);\r
         if (EFI_ERROR(Status)) {\r
           return;\r
         }\r
-        ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
-        gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+        ProcessorState = ProcessorData->State;\r
+        gThread->MutexUnlock (ProcessorData->StateLock);\r
 \r
         if (ProcessorState != CPU_STATE_IDLE) {\r
           // If we are retrying make sure we don't double count\r