From: Paul Durrant Date: Thu, 5 May 2022 18:12:40 +0000 (+0100) Subject: Separate running the 'late' SYNC_CALLBACKs from exitting the DPC X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=cad43e506e2c2f20dcf5e45e8a8420ca4dd23a3f;p=pvdrivers%2Fwin%2Fxenbus.git Separate running the 'late' SYNC_CALLBACKs from exitting the DPC This patch introduces a new dedicated request to ensure that *all* callbacks have been completed before *any* CPU exits the DPC, thereby allowing threads to be scheduled or other DPCs to run. Signed-off-by: Paul Durrant --- diff --git a/src/xenbus/suspend.c b/src/xenbus/suspend.c index 6a4a42e..3dca5d6 100644 --- a/src/xenbus/suspend.c +++ b/src/xenbus/suspend.c @@ -286,6 +286,7 @@ SuspendTrigger( SyncRunEarly(); SyncEnableInterrupts(); + SyncRunLate(); SyncRelease(); Context->Success = FALSE; diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c index 07cc94d..b666570 100644 --- a/src/xenbus/sync.c +++ b/src/xenbus/sync.c @@ -84,6 +84,7 @@ typedef enum _SYNC_REQUEST { SYNC_REQUEST_DISABLE_INTERRUPTS, SYNC_REQUEST_RUN_EARLY, SYNC_REQUEST_ENABLE_INTERRUPTS, + SYNC_REQUEST_RUN_LATE, SYNC_REQUEST_EXIT, } SYNC_REQUEST; @@ -208,6 +209,19 @@ __SyncProcessorEnableInterrupts( InterlockedIncrement(&Context->CompletionCount); } +static FORCEINLINE VOID +__SyncProcessorRunLate( + IN ULONG Index + ) +{ + PSYNC_CONTEXT Context = SyncContext; + + if (Context->Late != NULL) + Context->Late(Context->Argument, Index); + + InterlockedIncrement(&Context->CompletionCount); +} + static FORCEINLINE VOID __SyncWait( VOID @@ -255,12 +269,8 @@ SyncWorker( for (;;) { KeMemoryBarrier(); - if (Context->Request == SYNC_REQUEST_EXIT) { - if (Context->Late != NULL) - Context->Late(Context->Argument, Index); - + if (Context->Request == SYNC_REQUEST_EXIT) break; - } if (Context->Request == Request) { _mm_pause(); @@ -276,6 +286,8 @@ SyncWorker( __SyncProcessorRunEarly(Index); } else if (Context->Request == SYNC_REQUEST_ENABLE_INTERRUPTS) { __SyncProcessorEnableInterrupts(); + } else if (Context->Request == SYNC_REQUEST_RUN_LATE) { + __SyncProcessorRunLate(Index); } Request = Context->Request; @@ -419,6 +431,27 @@ SyncEnableInterrupts( Trace("<====\n"); } +__drv_requiresIRQL(DISPATCH_LEVEL) +VOID +SyncRunLate( + ) +{ + PSYNC_CONTEXT Context = SyncContext; + + ASSERT(SyncOwner >= 0); + + Context->CompletionCount = 0; + KeMemoryBarrier(); + + __SyncProcessorRunLate(SyncOwner); + + Context->Request = SYNC_REQUEST_RUN_LATE; + KeMemoryBarrier(); + + __SyncWait(); +} + + __drv_requiresIRQL(DISPATCH_LEVEL) VOID #pragma prefast(suppress:28167) // Function changes IRQL @@ -432,9 +465,6 @@ SyncRelease( ASSERT(SyncOwner >= 0); - if (Context->Late != NULL) - Context->Late(Context->Argument, SyncOwner); - Context->CompletionCount = 0; KeMemoryBarrier(); diff --git a/src/xenbus/sync.h b/src/xenbus/sync.h index 12ba406..e64d114 100644 --- a/src/xenbus/sync.h +++ b/src/xenbus/sync.h @@ -73,6 +73,13 @@ SyncEnableInterrupts( VOID ); +extern +__drv_requiresIRQL(DISPATCH_LEVEL) +VOID +SyncRunLate( + VOID + ); + extern __drv_requiresIRQL(DISPATCH_LEVEL) VOID