win-pvdrivers
changeset 1062:5775fb8612ab
Ensure only one event is outstanding at any given time
author | James Harper <james.harper@bendigoit.com.au> |
---|---|
date | Tue Oct 01 18:47:25 2013 +1000 (2013-10-01) |
parents | df3ee58e8b4f |
children | fe04dbceb0b2 |
files | xenvbd_filter/xenvbd_filter.c xenvbd_filter/xenvbd_filter.h |
line diff
1.1 --- a/xenvbd_filter/xenvbd_filter.c Tue Oct 01 18:46:50 2013 +1000 1.2 +++ b/xenvbd_filter/xenvbd_filter.c Tue Oct 01 18:47:25 2013 +1000 1.3 @@ -25,7 +25,7 @@ DRIVER_INITIALIZE DriverEntry; 1.4 1.5 static EVT_WDF_DRIVER_UNLOAD XenVbd_EvtDriverUnload; 1.6 static EVT_WDF_DRIVER_DEVICE_ADD XenVbd_EvtDeviceAdd; 1.7 -static EVT_WDF_REQUEST_COMPLETION_ROUTINE XenVbd_SendRequestComplete; 1.8 +static EVT_WDF_REQUEST_COMPLETION_ROUTINE XenVbd_SendEventComplete; 1.9 static EVT_WDF_DEVICE_D0_ENTRY XenVbd_EvtDeviceD0Entry; 1.10 static EVT_WDF_DEVICE_D0_EXIT XenVbd_EvtDeviceD0Exit; 1.11 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE; 1.12 @@ -152,13 +152,14 @@ XenVbd_StartRing(PXENVBD_DEVICE_DATA xvd 1.13 } 1.14 1.15 static VOID 1.16 -XenVbd_SendRequestComplete(WDFREQUEST request, WDFIOTARGET target, PWDF_REQUEST_COMPLETION_PARAMS params, WDFCONTEXT context) { 1.17 +XenVbd_SendEventComplete(WDFREQUEST request, WDFIOTARGET target, PWDF_REQUEST_COMPLETION_PARAMS params, WDFCONTEXT context) { 1.18 + WDFDEVICE device = WdfIoTargetGetDevice(target); 1.19 + PXENVBD_FILTER_DATA xvfd = GetXvfd(device); 1.20 NTSTATUS status; 1.21 PSCSI_REQUEST_BLOCK srb = context; 1.22 LARGE_INTEGER systemtime; 1.23 ULONGLONG elapsed; 1.24 1.25 - UNREFERENCED_PARAMETER(target); 1.26 UNREFERENCED_PARAMETER(params); 1.27 UNREFERENCED_PARAMETER(context); 1.28 1.29 @@ -174,6 +175,20 @@ XenVbd_SendRequestComplete(WDFREQUEST re 1.30 } 1.31 ExFreePoolWithTag(context, XENVBD_POOL_TAG); 1.32 WdfObjectDelete(request); 1.33 + 1.34 + for (;;) { 1.35 + if (InterlockedCompareExchange(&xvfd->event_state, 0, 1) == 1) { 1.36 + /* no pending event, and we cleared outstanding flag */ 1.37 + break; 1.38 + } 1.39 + if (InterlockedCompareExchange(&xvfd->event_state, 1, 2) == 2) { 1.40 + /* there was a pending event, and we set the flag back to outstanding */ 1.41 + //FUNCTION_MSG("sending pended event\n"); 1.42 + XenVbd_SendEvent(device); 1.43 + break; 1.44 + } 1.45 + /* event_state changed while we were looking at it, go round again */ 1.46 + } 1.47 } 1.48 1.49 static VOID 1.50 @@ -223,7 +238,7 @@ XenVbd_SendEvent(WDFDEVICE device) { 1.51 stack.Parameters.Scsi.Srb = srb; 1.52 1.53 WdfRequestWdmFormatUsingStackLocation(request, &stack); 1.54 - WdfRequestSetCompletionRoutine(request, XenVbd_SendRequestComplete, buf); 1.55 + WdfRequestSetCompletionRoutine(request, XenVbd_SendEventComplete, buf); 1.56 1.57 WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, 0); //WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE); 1.58 if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { 1.59 @@ -234,8 +249,21 @@ XenVbd_SendEvent(WDFDEVICE device) { 1.60 static VOID 1.61 XenVbd_EvtDpcEvent(WDFDPC dpc) { 1.62 WDFDEVICE device = WdfDpcGetParentObject(dpc); 1.63 + PXENVBD_FILTER_DATA xvfd = GetXvfd(device); 1.64 1.65 - XenVbd_SendEvent(device); 1.66 + for (;;) { 1.67 + if (InterlockedCompareExchange(&xvfd->event_state, 1, 0) == 0) { 1.68 + /* was no event outstanding, now there is */ 1.69 + XenVbd_SendEvent(device); 1.70 + break; 1.71 + } 1.72 + if (InterlockedCompareExchange(&xvfd->event_state, 2, 1) != 0) { 1.73 + //FUNCTION_MSG("event already in progress\n"); 1.74 + /* event was outstanding. either we set the need new event flag or it was already set */ 1.75 + break; 1.76 + } 1.77 + /* event_state changed while we were looking at it, go around again */ 1.78 + } 1.79 } 1.80 1.81 static VOID
2.1 --- a/xenvbd_filter/xenvbd_filter.h Tue Oct 01 18:46:50 2013 +1000 2.2 +++ b/xenvbd_filter/xenvbd_filter.h Tue Oct 01 18:47:25 2013 +1000 2.3 @@ -59,6 +59,8 @@ typedef struct { 2.4 WDFDPC dpc; 2.5 WDFQUEUE io_queue; 2.6 BOOLEAN hibernate_flag; 2.7 + /* event state 0 = no event outstanding, 1 = event outstanding, 2 = need event */ 2.8 + LONG event_state; 2.9 2.10 XENVBD_DEVICE_DATA xvdd; 2.11 } XENVBD_FILTER_DATA, *PXENVBD_FILTER_DATA;