[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 |