|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |