win-pvdrivers

changeset 128:9ebc64a86e57

Added in some locking for AddWatch, RemWatch, and WatchThreadFunc.
Still crashes when disabling xennet though.
author James Harper <james.harper@bendigoit.com.au>
date Thu Jan 17 12:47:04 2008 +1100 (2008-01-17)
parents 0b87815a2ee7
children cf3c845b4ae4
files xenpci/sources xenpci/xenbus.c xenpci/xenpci.h
line diff
     1.1 --- a/xenpci/sources	Thu Jan 17 00:18:18 2008 +1100
     1.2 +++ b/xenpci/sources	Thu Jan 17 12:47:04 2008 +1100
     1.3 @@ -1,7 +1,7 @@
     1.4  TARGETNAME=XENPCI
     1.5  TARGETTYPE=DRIVER
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7 -VERSION=0.5.0.28
     1.8 +VERSION=0.5.0.30
     1.9  KMDF_VERSION=1
    1.10  MSC_WARNING_LEVEL=/W4
    1.11  INF_NAME=xenpci
     2.1 --- a/xenpci/xenbus.c	Thu Jan 17 00:18:18 2008 +1100
     2.2 +++ b/xenpci/xenbus.c	Thu Jan 17 12:47:04 2008 +1100
     2.3 @@ -303,11 +303,17 @@ XenBus_Init(WDFDEVICE Device)
     2.4      
     2.5    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
     2.6  
     2.7 +  KeInitializeSpinLock(&xpdd->WatchLock);
     2.8 +
     2.9    xpdd->xen_store_evtchn = EvtChn_GetXenStorePort(Device);
    2.10    xpdd->xen_store_interface = EvtChn_GetXenStoreRingAddr(Device);
    2.11  
    2.12    for (i = 0; i < MAX_WATCH_ENTRIES; i++)
    2.13 +  {
    2.14      xpdd->XenBus_WatchEntries[i].Active = 0;
    2.15 +    xpdd->XenBus_WatchEntries[i].Running = 0;
    2.16 +    KeInitializeEvent(&xpdd->XenBus_WatchEntries[i].CompleteEvent, SynchronizationEvent, FALSE);  
    2.17 +  }
    2.18  
    2.19    KeInitializeEvent(&xpdd->XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
    2.20    KeInitializeEvent(&xpdd->XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
    2.21 @@ -544,6 +550,7 @@ XenBus_WatchThreadProc(PVOID StartContex
    2.22    PXENBUS_WATCH_ENTRY entry;
    2.23    WDFDEVICE Device = StartContext;
    2.24    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
    2.25 +  KIRQL OldIrql;
    2.26  
    2.27    for(;;)
    2.28    {
    2.29 @@ -558,27 +565,20 @@ XenBus_WatchThreadProc(PVOID StartContex
    2.30        xpdd->XenBus_WatchRingReadIndex = 
    2.31          (xpdd->XenBus_WatchRingReadIndex + 1) % WATCH_RING_SIZE;
    2.32        index = atoi(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token);
    2.33 -      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
    2.34 -      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
    2.35  
    2.36        entry = &xpdd->XenBus_WatchEntries[index];
    2.37 -      if (!entry->Active)
    2.38 +      KeAcquireSpinLock(&xpdd->WatchLock, &OldIrql);
    2.39 +      if (!entry->Active || !entry->ServiceRoutine)
    2.40        {
    2.41 -        KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n",
    2.42 -        xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
    2.43 -        xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
    2.44 +        KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
    2.45          continue;
    2.46        }
    2.47 +      entry->Running = 1;
    2.48 +      KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
    2.49        entry->Count++;
    2.50 -      if (!entry->ServiceRoutine)
    2.51 -      {
    2.52 -        KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n",
    2.53 -          xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
    2.54 -          xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
    2.55 -        continue;
    2.56 -      }
    2.57 -      //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
    2.58        entry->ServiceRoutine(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
    2.59 +      entry->Running = 0;
    2.60 +      KeSetEvent(&entry->CompleteEvent, 1, FALSE);
    2.61      }
    2.62    }
    2.63  }    
    2.64 @@ -599,11 +599,14 @@ XenBus_AddWatch(
    2.65    char Token[20];
    2.66    struct write_req req[2];
    2.67    PXENBUS_WATCH_ENTRY w_entry;
    2.68 +  KIRQL OldIrql;
    2.69  
    2.70    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.71  
    2.72    ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
    2.73  
    2.74 +  KeAcquireSpinLock(&xpdd->WatchLock, &OldIrql);
    2.75 +
    2.76    for (i = 0; i < MAX_WATCH_ENTRIES; i++)
    2.77      if (xpdd->XenBus_WatchEntries[i].Active == 0)
    2.78        break;
    2.79 @@ -611,10 +614,12 @@ XenBus_AddWatch(
    2.80    if (i == MAX_WATCH_ENTRIES)
    2.81    {
    2.82      KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
    2.83 +    KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
    2.84      return NULL;
    2.85    }
    2.86  
    2.87    /* must init watchentry before starting watch */
    2.88 +  
    2.89    w_entry = &xpdd->XenBus_WatchEntries[i];
    2.90    strncpy(w_entry->Path, Path, ARRAY_SIZE(w_entry->Path));
    2.91    w_entry->ServiceRoutine = ServiceRoutine;
    2.92 @@ -622,6 +627,8 @@ XenBus_AddWatch(
    2.93    w_entry->Count = 0;
    2.94    w_entry->Active = 1;
    2.95  
    2.96 +  KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
    2.97 +
    2.98    req[0].data = Path;
    2.99    req[0].len = strlen(Path) + 1;
   2.100  
   2.101 @@ -660,9 +667,12 @@ XenBus_RemWatch(
   2.102    int i;
   2.103    char Token[20];
   2.104    struct write_req req[2];
   2.105 +  KIRQL OldIrql;
   2.106  
   2.107    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.108  
   2.109 +  KeAcquireSpinLock(&xpdd->WatchLock, &OldIrql);
   2.110 +
   2.111    // check that Path < 128 chars
   2.112  
   2.113    for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
   2.114 @@ -675,10 +685,21 @@ XenBus_RemWatch(
   2.115  
   2.116    if (i == MAX_WATCH_ENTRIES)
   2.117    {
   2.118 +    KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
   2.119      KdPrint((__DRIVER_NAME "     Watch not set - can't remove\n"));
   2.120      return NULL;
   2.121    }
   2.122  
   2.123 +  while (xpdd->XenBus_WatchEntries[i].Running)
   2.124 +  {
   2.125 +    KeWaitForSingleObject(&xpdd->XenBus_WatchEntries[i].CompleteEvent, Executive, KernelMode, FALSE, NULL);
   2.126 +  }
   2.127 +
   2.128 +  xpdd->XenBus_WatchEntries[i].Active = 0;
   2.129 +  xpdd->XenBus_WatchEntries[i].Path[0] = 0;
   2.130 +
   2.131 +  KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
   2.132 +
   2.133    req[0].data = Path;
   2.134    req[0].len = strlen(Path) + 1;
   2.135  
   2.136 @@ -690,11 +711,14 @@ XenBus_RemWatch(
   2.137  
   2.138    msg = errmsg(rep);
   2.139    if (msg)
   2.140 +  {
   2.141 +    KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
   2.142      return msg;
   2.143 +  }
   2.144  
   2.145    ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   2.146  
   2.147 -  xpdd->XenBus_WatchEntries[i].Active = 0;
   2.148 +  KeReleaseSpinLock(&xpdd->WatchLock, OldIrql);
   2.149  
   2.150    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.151  
     3.1 --- a/xenpci/xenpci.h	Thu Jan 17 00:18:18 2008 +1100
     3.2 +++ b/xenpci/xenpci.h	Thu Jan 17 12:47:04 2008 +1100
     3.3 @@ -90,6 +90,8 @@ typedef struct _XENBUS_WATCH_ENTRY {
     3.4    PVOID ServiceContext;
     3.5    int Count;
     3.6    int Active;
     3.7 +  int Running;
     3.8 +  KEVENT CompleteEvent;
     3.9  } XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
    3.10  
    3.11  #define NR_EVENTS 1024
    3.12 @@ -139,6 +141,7 @@ typedef struct {
    3.13    int nr_live_reqs;
    3.14    XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
    3.15  
    3.16 +  KSPIN_LOCK WatchLock;
    3.17  } XENPCI_DEVICE_DATA, *PXENPCI_DEVICE_DATA;
    3.18  
    3.19  WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_DEVICE_DATA, GetDeviceData);