This patch for RFC. I think it solves some longstanding suspend/resume issues we have had.
MH.
From 5b4cff54f026917d234718976e791717ece474c4 Mon Sep 17 00:00:00 2001
From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
Date: Thu, 28 Apr 2022 13:52:40 +0100
Subject: [PATCH] Add extra sync release step for late callbacks.
Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx>
---
src/xenbus/sync.c | 42 ++++++++++++++++++++++++++++++++++++------
1 file changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
index 615eca8..8f25ea4 100644
--- a/src/xenbus/sync.c
+++ b/src/xenbus/sync.c
@@ -82,7 +82,8 @@ static UCHAR __Section[PAGE_SIZE];
typedef struct _SYNC_PROCESSOR {
KDPC Dpc;
BOOLEAN DisableInterrupts;
- BOOLEAN Exit;
+ BOOLEAN ExitLate;
+ BOOLEAN ExitFinal;
} SYNC_PROCESSOR, *PSYNC_PROCESSOR;
typedef struct _SYNC_CONTEXT {
@@ -143,6 +144,7 @@ SyncWorker(
ULONG Index;
PSYNC_PROCESSOR Processor;
PROCESSOR_NUMBER ProcNumber;
+ ULONG Sequence;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(_Context);
@@ -160,9 +162,7 @@ SyncWorker(
InterlockedIncrement(&Context->CompletionCount);
for (;;) {
- ULONG Sequence;
-
- if (Processor->Exit) {
+ if (Processor->ExitLate) {
if (Context->Late != NULL)
Context->Late(Context->Argument, Index);
@@ -242,10 +242,18 @@ SyncWorker(
}
}
- Trace("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
+ InterlockedIncrement(&Context->CompletionCount);
+
+ while(!Processor->ExitFinal) {
+ _mm_pause();
+ KeMemoryBarrier();
+ }
+
InterlockedIncrement(&Context->CompletionCount);
ASSERT(!InterruptsDisabled);
+
+ Trace("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
}
__drv_maxIRQL(DISPATCH_LEVEL)
@@ -443,13 +451,35 @@ SyncRelease(
if (Context->Late != NULL)
Context->Late(Context->Argument, SyncOwner);
+ /* First wait to make sure all late completion callbacks are done before spinning released. */
+ Context->Sequence++;
+ Context->CompletionCount = 0;
+
+ KeMemoryBarrier();
+
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PSYNC_PROCESSOR Processor = &Context->Processor[Index];
+
+ Processor->ExitLate = TRUE;
+ }
+
+ InterlockedIncrement(&Context->CompletionCount);
+
+ while (Context->CompletionCount < Context->ProcessorCount) {
+ _mm_pause();
+ KeMemoryBarrier();
+ }
+
+ /* Second wait to make sure all spinning DPCs release before proceed. */
Context->Sequence++;
Context->CompletionCount = 0;
+ KeMemoryBarrier();
+
for (Index = 0; Index < Context->ProcessorCount; Index++) {
PSYNC_PROCESSOR Processor = &Context->Processor[Index];
- Processor->Exit = TRUE;
+ Processor->ExitFinal = TRUE;
}
KeMemoryBarrier();
--
2.25.0.windows.1