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;