[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH xenbus 5/7] Re-work the code in sync.c to provide per-CPU 'early' and 'late' callbacks...



From: Paul Durrant <pdurrant@xxxxxxxxxx>

... and then use these to drive the XENBUS_SUSPEND callbacks, rather than them
being called directly from SuspendTrigger().

Since the clients of the XENBUS_SUSPEND interface only expect one invocation
of each callback, rather then one per-CPU, they are only invoked from the
sync.c callback for CPU 0. A subsequent patch will introduce a function that
must be called from the 'early' callback for each CPU.

NOTE: The call to KeGetCurrentProcessorNumberEx() made in SyncRelease() is
      relocated to __SyncRelease(), as that is the place where the CPU index
      is actually used.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xenbus/suspend.c | 106 ++++++++++++++++++++++++++++---------------
 src/xenbus/sync.c    |  45 +++++++++++++++---
 src/xenbus/sync.h    |  10 +++-
 3 files changed, 118 insertions(+), 43 deletions(-)

diff --git a/src/xenbus/suspend.c b/src/xenbus/suspend.c
index 5667e8446176..77752b00d490 100644
--- a/src/xenbus/suspend.c
+++ b/src/xenbus/suspend.c
@@ -51,6 +51,7 @@ struct _XENBUS_SUSPEND_CONTEXT {
     PXENBUS_FDO                 Fdo;
     KSPIN_LOCK                  Lock;
     LONG                        References;
+    BOOLEAN                     Success;
     ULONG                       Count;
     LIST_ENTRY                  EarlyList;
     LIST_ENTRY                  LateList;
@@ -180,6 +181,73 @@ __SuspendLogTimers(
               PerformanceFrequency.LowPart);
 }
 
+static VOID
+SuspendEarly(
+    IN  PVOID               Argument,
+    IN  ULONG               Cpu
+    )
+{
+    PXENBUS_SUSPEND_CONTEXT Context = Argument;
+    PLIST_ENTRY             ListEntry;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "SUSPEND: EARLY (%u)\n", Cpu);
+
+    if (!Context->Success || Cpu != 0)
+        return;
+
+    //
+    // No lock is required here as the VM is single-threaded with interrupts
+    // disabled.
+    //
+
+    Context->Count++;
+
+    HypercallPopulate();
+
+    UnplugDevices();
+
+    for (ListEntry = Context->EarlyList.Flink;
+         ListEntry != &Context->EarlyList;
+         ListEntry = ListEntry->Flink) {
+        PXENBUS_SUSPEND_CALLBACK  Callback;
+
+        Callback = CONTAINING_RECORD(ListEntry,
+                                     XENBUS_SUSPEND_CALLBACK,
+                                     ListEntry);
+        Callback->Function(Callback->Argument);
+    }
+}
+
+static VOID
+SuspendLate(
+    IN  PVOID               Argument,
+    IN  ULONG               Cpu
+    )
+{
+    PXENBUS_SUSPEND_CONTEXT Context = Argument;
+    PLIST_ENTRY             ListEntry;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "SUSPEND: LATE (%u)\n", Cpu);
+
+    if (!Context->Success || Cpu != 0)
+        return;
+
+    // No lock is required here as the VM is single-threaded
+
+    for (ListEntry = Context->LateList.Flink;
+         ListEntry != &Context->LateList;
+         ListEntry = ListEntry->Flink) {
+        PXENBUS_SUSPEND_CALLBACK  Callback;
+
+        Callback = CONTAINING_RECORD(ListEntry,
+                                     XENBUS_SUSPEND_CALLBACK,
+                                     ListEntry);
+        Callback->Function(Callback->Argument);
+    }
+}
+
 NTSTATUS
 #pragma prefast(suppress:28167) // Function changes IRQL
 SuspendTrigger(
@@ -195,7 +263,7 @@ SuspendTrigger(
     LogPrintf(LOG_LEVEL_INFO,
               "SUSPEND: ====>\n");
 
-    SyncCapture();
+    SyncCapture(Context, SuspendEarly, SuspendLate);
     SyncDisableInterrupts();
 
     __SuspendLogTimers("PRE-SUSPEND");
@@ -209,43 +277,9 @@ SuspendTrigger(
 
     __SuspendLogTimers("POST-SUSPEND");
 
-    if (NT_SUCCESS(status)) {
-        PLIST_ENTRY ListEntry;
-
-        Context->Count++;
-
-        HypercallPopulate();
-
-        UnplugDevices();
-
-        for (ListEntry = Context->EarlyList.Flink;
-             ListEntry != &Context->EarlyList;
-             ListEntry = ListEntry->Flink) {
-            PXENBUS_SUSPEND_CALLBACK  Callback;
-
-            Callback = CONTAINING_RECORD(ListEntry, XENBUS_SUSPEND_CALLBACK, 
ListEntry);
-            Callback->Function(Callback->Argument);
-        }
-    }
+    Context->Success = NT_SUCCESS(status) ? TRUE : FALSE;
 
     SyncEnableInterrupts();
-
-    // No lock is required here as the VM is single-threaded until
-    // SyncRelease() is called.
-
-    if (NT_SUCCESS(status)) {
-        PLIST_ENTRY ListEntry;
-
-        for (ListEntry = Context->LateList.Flink;
-             ListEntry != &Context->LateList;
-             ListEntry = ListEntry->Flink) {
-            PXENBUS_SUSPEND_CALLBACK  Callback;
-
-            Callback = CONTAINING_RECORD(ListEntry, XENBUS_SUSPEND_CALLBACK, 
ListEntry);
-            Callback->Function(Callback->Argument);
-        }
-    }
-
     SyncRelease();
 
     LogPrintf(LOG_LEVEL_INFO, "SUSPEND: <====\n");
diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
index 661aabe54a0d..615eca84c460 100644
--- a/src/xenbus/sync.c
+++ b/src/xenbus/sync.c
@@ -86,6 +86,9 @@ typedef struct  _SYNC_PROCESSOR {
 } SYNC_PROCESSOR, *PSYNC_PROCESSOR;
 
 typedef struct  _SYNC_CONTEXT {
+    PVOID               Argument;
+    SYNC_CALLBACK       Early;
+    SYNC_CALLBACK       Late;
     ULONG               Sequence;
     LONG                ProcessorCount;
     LONG                CompletionCount;
@@ -108,10 +111,13 @@ __SyncAcquire(
 
 static FORCEINLINE VOID
 __SyncRelease(
-    IN  LONG    Index
+    VOID
     )
 {
-    LONG        Old;
+    LONG    Old;
+    LONG    Index;
+
+    Index = KeGetCurrentProcessorNumberEx(NULL);
 
     Old = InterlockedExchange(&SyncOwner, -1);
     ASSERT3U(Old, ==, Index);
@@ -145,6 +151,9 @@ SyncWorker(
 
     InterruptsDisabled = FALSE;
     Index = KeGetCurrentProcessorNumberEx(&ProcNumber);
+
+    ASSERT(SyncOwner >= 0 && Index != (ULONG)SyncOwner);
+
     Processor = &Context->Processor[Index];
 
     Trace("====> (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
@@ -153,8 +162,12 @@ SyncWorker(
     for (;;) {
         ULONG   Sequence;
 
-        if (Processor->Exit)
+        if (Processor->Exit) {
+            if (Context->Late != NULL)
+                Context->Late(Context->Argument, Index);
+
             break;
+        }
 
         if (Processor->DisableInterrupts == InterruptsDisabled) {
             _mm_pause();
@@ -210,6 +223,9 @@ SyncWorker(
         } else {
             InterruptsDisabled = FALSE;
 
+            if (Context->Early != NULL)
+                Context->Early(Context->Argument, Index);
+
             _enable();
 
 #pragma prefast(suppress:28138) // Use constant rather than variable
@@ -236,7 +252,9 @@ __drv_maxIRQL(DISPATCH_LEVEL)
 __drv_raisesIRQL(DISPATCH_LEVEL)
 VOID
 SyncCapture(
-    VOID
+    IN  PVOID           Argument OPTIONAL,
+    IN  SYNC_CALLBACK   Early OPTIONAL,
+    IN  SYNC_CALLBACK   Late OPTIONAL
     )
 {
     PSYNC_CONTEXT       Context = SyncContext;
@@ -257,6 +275,10 @@ SyncCapture(
 
     ASSERT(IsZeroMemory(Context, PAGE_SIZE));
 
+    Context->Argument = Argument;
+    Context->Early = Early;
+    Context->Late = Late;
+
     Context->Sequence++;
     Context->CompletionCount = 0;
 
@@ -304,6 +326,8 @@ SyncDisableInterrupts(
 
     Trace("====>\n");
 
+    ASSERT(SyncOwner >= 0);
+
     Context->Sequence++;
     Context->CompletionCount = 0;
 
@@ -368,6 +392,11 @@ SyncEnableInterrupts(
     KIRQL           Irql;
     LONG            Index;
 
+    ASSERT(SyncOwner >= 0);
+
+    if (Context->Early != NULL)
+        Context->Early(Context->Argument, SyncOwner);
+
     _enable();
 
     Irql = KeGetCurrentIrql();
@@ -409,6 +438,11 @@ SyncRelease(
 
     Trace("====>\n");
 
+    ASSERT(SyncOwner >= 0);
+
+    if (Context->Late != NULL)
+        Context->Late(Context->Argument, SyncOwner);
+
     Context->Sequence++;
     Context->CompletionCount = 0;
 
@@ -429,8 +463,7 @@ SyncRelease(
 
     RtlZeroMemory(Context, PAGE_SIZE);
 
-    Index = KeGetCurrentProcessorNumberEx(NULL);
-    __SyncRelease(Index);
+    __SyncRelease();
 
     Trace("<====\n");
 }
diff --git a/src/xenbus/sync.h b/src/xenbus/sync.h
index affbf0f9f0d5..c4b172107513 100644
--- a/src/xenbus/sync.h
+++ b/src/xenbus/sync.h
@@ -34,12 +34,20 @@
 
 #include <ntddk.h>
 
+typedef VOID
+(*SYNC_CALLBACK)(
+    IN  PVOID   Arguement,
+    IN  ULONG   Cpu
+    );
+
 extern
 __drv_maxIRQL(DISPATCH_LEVEL)
 __drv_raisesIRQL(DISPATCH_LEVEL)
 VOID
 SyncCapture(
-    VOID
+    IN  PVOID           Argument OPTIONAL,
+    IN  SYNC_CALLBACK   Early OPTIONAL,
+    IN  SYNC_CALLBACK   Late OPTIONAL
     );
 
 extern
-- 
2.17.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.