[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH xenbus] Use a slab allocator to back XENBUS_CACHE memory



Rather than using non-paged pool and suffering the overhead of a header on
every object, use a slab allocator.

The slab allocator allocates and frees whole pages, and there is only one
control structure per-slab.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenbus/cache.c           | 659 +++++++++++++++++++++----------------------
 vs2015/xenbus/xenbus.vcxproj |   2 +-
 vs2017/xenbus/xenbus.vcxproj |   2 +-
 3 files changed, 317 insertions(+), 346 deletions(-)

diff --git a/src/xenbus/cache.c b/src/xenbus/cache.c
index 433468a..da1597a 100644
--- a/src/xenbus/cache.c
+++ b/src/xenbus/cache.c
@@ -46,20 +46,29 @@ RtlRandomEx (
     __inout PULONG Seed
     );
 
-typedef struct _XENBUS_CACHE_OBJECT_HEADER {
-    ULONG       Magic;
-
-#define XENBUS_CACHE_OBJECT_HEADER_MAGIC 'EJBO'
-
-    LIST_ENTRY  ListEntry;
-} XENBUS_CACHE_OBJECT_HEADER, *PXENBUS_CACHE_OBJECT_HEADER;
-
 #define XENBUS_CACHE_MAGAZINE_SLOTS   6
 
 typedef struct _XENBUS_CACHE_MAGAZINE {
     PVOID   Slot[XENBUS_CACHE_MAGAZINE_SLOTS];
 } XENBUS_CACHE_MAGAZINE, *PXENBUS_CACHE_MAGAZINE;
 
+
+#define XENBUS_CACHE_SLAB_MAGIC 'BALS'
+
+typedef struct _XENBUS_CACHE_SLAB {
+    ULONG           Magic;
+    LIST_ENTRY      ListEntry;
+    ULONG           Size;
+    ULONG           Count;
+    ULONG           Allocated;
+    UCHAR           Buffer[1];
+} XENBUS_CACHE_SLAB, *PXENBUS_CACHE_SLAB;
+
+#define BITS_PER_ULONG (sizeof (ULONG) * 8)
+#define MINIMUM_OBJECT_SIZE (PAGE_SIZE / BITS_PER_ULONG)
+
+C_ASSERT(sizeof (XENBUS_CACHE_SLAB) <= MINIMUM_OBJECT_SIZE);
+
 #define MAXNAMELEN  128
 
 struct _XENBUS_CACHE {
@@ -72,11 +81,8 @@ struct _XENBUS_CACHE {
     VOID                    (*AcquireLock)(PVOID);
     VOID                    (*ReleaseLock)(PVOID);
     PVOID                   Argument;
-    LIST_ENTRY              GetList;
-    LONG                    GetCount;
-    PLIST_ENTRY             PutList;
-    LONG                    PutCount;
-    LONG                    ListCount;
+    LIST_ENTRY              SlabList;
+    ULONG                   Count;
     PXENBUS_CACHE_MAGAZINE  Magazine;
     ULONG                   MagazineCount;
 };
@@ -87,7 +93,6 @@ struct _XENBUS_CACHE_CONTEXT {
     LONG                    References;
     XENBUS_DEBUG_INTERFACE  DebugInterface;
     PXENBUS_DEBUG_CALLBACK  DebugCallback;
-    PXENBUS_THREAD          MonitorThread;
     LIST_ENTRY              List;
 };
 
@@ -109,364 +114,415 @@ __CacheFree(
     __FreePoolWithTag(Buffer, CACHE_TAG);
 }
 
-static VOID
-CacheSwizzle(
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__CacheAcquireLock(
     IN  PXENBUS_CACHE   Cache
     )
 {
-    PLIST_ENTRY         List;
-
-    List = InterlockedExchangePointer(&Cache->PutList, NULL);
-
-    // Not really a doubly-linked list; it's actually a singly-linked
-    // list via the Flink field.
-    while (List != NULL) {
-        PLIST_ENTRY                 Next;
-        PXENBUS_CACHE_OBJECT_HEADER Header;
-
-        Next = List->Flink;
-        List->Flink = NULL;
-        ASSERT3P(List->Blink, ==, NULL);
+    Cache->AcquireLock(Cache->Argument);
+}
 
-        Header = CONTAINING_RECORD(List,
-                                   XENBUS_CACHE_OBJECT_HEADER,
-                                   ListEntry);
-        ASSERT3U(Header->Magic, ==, XENBUS_CACHE_OBJECT_HEADER_MAGIC);
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__CacheReleaseLock(
+    IN  PXENBUS_CACHE   Cache
+    )
+{
+    Cache->ReleaseLock(Cache->Argument);
+}
 
-        InsertTailList(&Cache->GetList, &Header->ListEntry);
+static FORCEINLINE NTSTATUS
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__CacheCtor(
+    IN  PXENBUS_CACHE   Cache,
+    IN  PVOID           Object
+    )
+{
+    return Cache->Ctor(Cache->Argument, Object);
+}
 
-        List = Next;
-    }
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__CacheDtor(
+    IN  PXENBUS_CACHE   Cache,
+    IN  PVOID           Object
+    )
+{
+    Cache->Dtor(Cache->Argument, Object);
 }
 
 static PVOID
-CacheCreateObject(
-    IN  PXENBUS_CACHE           Cache
+CacheGetObjectFromMagazine(
+    IN  PXENBUS_CACHE_MAGAZINE  Magazine
     )
 {
-    PXENBUS_CACHE_OBJECT_HEADER Header;
-    PVOID                       Object;
-    NTSTATUS                    status;
-
-    Header = __CacheAllocate(sizeof (XENBUS_CACHE_OBJECT_HEADER) +
-                             Cache->Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Header == NULL)
-        goto fail1;
-
-    Header->Magic = XENBUS_CACHE_OBJECT_HEADER_MAGIC;
-
-    Object = Header + 1;
-
-    status = Cache->Ctor(Cache->Argument, Object);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    return Object;
-
-fail2:
-    Error("fail2\n");
+    ULONG                       Index;
 
-    Header->Magic = 0;
+    for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
+        PVOID   Object;
 
-    ASSERT(IsZeroMemory(Header, sizeof (XENBUS_CACHE_OBJECT_HEADER)));
-    __CacheFree(Header);
+        if (Magazine->Slot[Index] != NULL) {
+            Object = Magazine->Slot[Index];
+            Magazine->Slot[Index] = NULL;
 
-fail1:
-    Error("fail1 (%08x)\n", status);
+            return Object;
+        }
+    }
 
-    return NULL;    
+    return NULL;
 }
 
-static FORCEINLINE
-__drv_savesIRQL
-__drv_raisesIRQL(DISPATCH_LEVEL)
-KIRQL
-__CacheAcquireLock(
-    IN  PXENBUS_CACHE   Cache
+static NTSTATUS
+CachePutObjectToMagazine(
+    IN  PXENBUS_CACHE_MAGAZINE  Magazine,
+    IN  PVOID                   Object
     )
 {
-    KIRQL               Irql;
+    ULONG                       Index;
 
-    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-    Cache->AcquireLock(Cache->Argument);
-
-    return Irql;
-}
+    for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
+        if (Magazine->Slot[Index] == NULL) {
+            Magazine->Slot[Index] = Object;
+            return STATUS_SUCCESS;
+        }
+    }
 
-static FORCEINLINE VOID
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__CacheReleaseLock(
-    IN  PXENBUS_CACHE               Cache,
-    IN  __drv_restoresIRQL KIRQL    Irql
-    )
-{
-    Cache->ReleaseLock(Cache->Argument);
-    KeLowerIrql(Irql);
+    return STATUS_UNSUCCESSFUL;
 }
 
-static PVOID
-CacheGetObjectFromList(
-    IN  PXENBUS_CACHE           Cache,
-    IN  BOOLEAN                 Locked
+// Must be called with lock held
+static PXENBUS_CACHE_SLAB
+CacheCreateSlab(
+    IN  PXENBUS_CACHE   Cache
     )
 {
-    LONG                        Count;
-    PLIST_ENTRY                 ListEntry;
-    PXENBUS_CACHE_OBJECT_HEADER Header;
-    PVOID                       Object;
-    KIRQL                       Irql = PASSIVE_LEVEL;
-    NTSTATUS                    status;
-
-    Count = InterlockedDecrement(&Cache->ListCount);
+    ULONG               Size;
+    PXENBUS_CACHE_SLAB  Slab;
+    ULONG               NumberOfBytes;
+    LARGE_INTEGER       LowAddress;
+    LARGE_INTEGER       HighAddress;
+    LARGE_INTEGER       Boundary;
+    LONG                Index;
+    NTSTATUS            status;
+
+    Size = __max(Cache->Size, MINIMUM_OBJECT_SIZE);
+    Size = P2ROUNDUP(Size, sizeof (ULONG_PTR));
+
+    NumberOfBytes = P2ROUNDUP(FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer) +
+                              Size,
+                              PAGE_SIZE);
+
+    LowAddress.QuadPart = 0ull;
+    HighAddress.QuadPart = ~0ull;
+    Boundary.QuadPart = 0ull;
+
+    Slab = MmAllocateContiguousMemorySpecifyCacheNode((SIZE_T)NumberOfBytes,
+                                                      LowAddress,
+                                                      HighAddress,
+                                                      Boundary,
+                                                      MmCached,
+                                                      MM_ANY_NODE_OK);
 
     status = STATUS_NO_MEMORY;
-    if (Count < 0)
+    if (Slab == NULL)
         goto fail1;
 
-    if (!Locked)
-        Irql = __CacheAcquireLock(Cache);
+    RtlZeroMemory(Slab, NumberOfBytes);
 
-    if (IsListEmpty(&Cache->GetList))
-        CacheSwizzle(Cache);
+    Slab->Magic = XENBUS_CACHE_SLAB_MAGIC;
+    Slab->Size = Size;
+    Slab->Count = (NumberOfBytes -
+                   FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer)) /
+                  Size;
+    ASSERT(Slab->Count != 0);
 
-    ListEntry = RemoveHeadList(&Cache->GetList);
-    ASSERT(ListEntry != &Cache->GetList);
+    for (Index = 0; Index < (LONG)Slab->Count; Index++) {
+        PVOID Object = (PVOID)&Slab->Buffer[Index * Size];
 
-    if (!Locked)
-        __CacheReleaseLock(Cache, Irql);
+        status = __CacheCtor(Cache, Object);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
 
-    RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+    InsertHeadList(&Cache->SlabList, &Slab->ListEntry);
+    Cache->Count += Slab->Count;
 
-    Header = CONTAINING_RECORD(ListEntry,
-                               XENBUS_CACHE_OBJECT_HEADER,
-                               ListEntry);
-    ASSERT3U(Header->Magic, ==, XENBUS_CACHE_OBJECT_HEADER_MAGIC);
+    return Slab;
 
-    Object = Header + 1;
+fail2:
+    while (--Index >= 0) {
+        PVOID Object = (PVOID)&Slab->Buffer[Index * Size];
 
-    return Object;
+        __CacheDtor(Cache, Object);
+    }
+
+    MmFreeContiguousMemory(Slab);
 
 fail1:
-    (VOID) InterlockedIncrement(&Cache->ListCount);
+    Error("fail1 (%08x)\n", status);
 
-    return NULL;    
+    return NULL;
 }
 
-static VOID
-CachePutObjectToList(
-    IN  PXENBUS_CACHE           Cache,
-    IN  PVOID                   Object,
-    IN  BOOLEAN                 Locked
+// Must be called with lock held
+static NTSTATUS
+CacheDestroySlab(
+    IN  PXENBUS_CACHE       Cache,
+    IN  PXENBUS_CACHE_SLAB  Slab
     )
 {
-    PXENBUS_CACHE_OBJECT_HEADER Header;
-    PLIST_ENTRY                 Old;
-    PLIST_ENTRY                 New;
-
-    ASSERT(Object != NULL);
+    LONG                    Index;
 
-    Header = Object;
-    --Header;
-    ASSERT3U(Header->Magic, ==, XENBUS_CACHE_OBJECT_HEADER_MAGIC);
+    // This may not have been previously tested under lock
+    if (Slab->Allocated != 0)
+        return STATUS_UNSUCCESSFUL;
 
-    ASSERT(IsZeroMemory(&Header->ListEntry, sizeof (LIST_ENTRY)));
+    ASSERT3U(Cache->Count, >=, Slab->Count);
+    Cache->Count -= Slab->Count;
+    RemoveEntryList(&Slab->ListEntry);
 
-    if (!Locked) {
-        New = &Header->ListEntry;
+    Index = Slab->Count;
+    while (--Index >= 0) {
+        PVOID Object = (PVOID)&Slab->Buffer[Index * Slab->Size];
 
-        do {
-            Old = Cache->PutList;
-            New->Flink = Old;
-        } while (InterlockedCompareExchangePointer(&Cache->PutList,
-                                                   New,
-                                                   Old) != Old);
-    } else {
-        InsertTailList(&Cache->GetList, &Header->ListEntry);
+        __CacheDtor(Cache, Object);
     }
 
-    KeMemoryBarrier();
+    MmFreeContiguousMemory(Slab);
 
-    (VOID) InterlockedIncrement(&Cache->ListCount);
+    return STATUS_SUCCESS;
 }
 
+// Must be called with lock held
 static PVOID
-CacheGetObjectFromMagazine(
-    IN  PXENBUS_CACHE       Cache,
-    IN  ULONG               Index
+CacheGetObjectFromSlab(
+    IN  PXENBUS_CACHE_SLAB  Slab
     )
 {
-    PXENBUS_CACHE_MAGAZINE  Magazine;
+    ULONG                   Free;
+    ULONG                   Index;
+    ULONG                   Set;
 
-    ASSERT3U(Index, <, Cache->MagazineCount);
-    Magazine = &Cache->Magazine[Index];
+    Free = ~Slab->Allocated;
+    if (!_BitScanForward(&Index, Free) || Index >= Slab->Count)
+        return NULL;
 
-    for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
-        PVOID   Object;
+    Set = InterlockedBitTestAndSet((LONG *)&Slab->Allocated, Index);
+    ASSERT(!Set);
 
-        if (Magazine->Slot[Index] != NULL) {
-            Object = Magazine->Slot[Index];
-            Magazine->Slot[Index] = NULL;
-
-            return Object;
-        }
-    }
-
-    return NULL;
+    return (PVOID)&Slab->Buffer[Index * Slab->Size];
 }
 
-static BOOLEAN
-CachePutObjectToMagazine(
-    IN  PXENBUS_CACHE       Cache,
-    IN  ULONG               Index,
+// May be called with or without lock held
+static VOID
+CachePutObjectToSlab(
+    IN  PXENBUS_CACHE_SLAB  Slab,
     IN  PVOID               Object
     )
 {
-    PXENBUS_CACHE_MAGAZINE  Magazine;
+    ULONG                   Index;
 
-    ASSERT3U(Index, <, Cache->MagazineCount);
-    Magazine = &Cache->Magazine[Index];
+    Index = (ULONG)((PUCHAR)Object - &Slab->Buffer[0]) / Slab->Size;
+    BUG_ON(Index >= Slab->Count);
 
-    for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
-        if (Magazine->Slot[Index] == NULL) {
-            Magazine->Slot[Index] = Object;
-            return TRUE;
-        }
-    }
-
-    return FALSE;
+    (VOID) InterlockedBitTestAndReset((LONG *)&Slab->Allocated, Index);
 }
 
 static PVOID
 CacheGet(
-    IN  PINTERFACE      Interface,
-    IN  PXENBUS_CACHE   Cache,
-    IN  BOOLEAN         Locked
+    IN  PINTERFACE          Interface,
+    IN  PXENBUS_CACHE       Cache,
+    IN  BOOLEAN             Locked
     )
 {
-    KIRQL               Irql;
-    ULONG               Index;
-    PVOID               Object;
+    KIRQL                   Irql;
+    ULONG                   Index;
+    PXENBUS_CACHE_MAGAZINE  Magazine;
+    PVOID                   Object;
+    PLIST_ENTRY             ListEntry;
 
     UNREFERENCED_PARAMETER(Interface);
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
     Index = KeGetCurrentProcessorNumberEx(NULL);
 
-    Object = CacheGetObjectFromMagazine(Cache, Index);
-    if (Object != NULL)
-        goto done;
+    ASSERT3U(Index, <, Cache->MagazineCount);
+    Magazine = &Cache->Magazine[Index];
 
-    Object = CacheGetObjectFromList(Cache, Locked);
+    Object = CacheGetObjectFromMagazine(Magazine);
     if (Object != NULL)
         goto done;
 
-    Object = CacheCreateObject(Cache);
+    if (!Locked)
+        __CacheAcquireLock(Cache);
+
+    for (ListEntry = Cache->SlabList.Flink;
+         ListEntry != &Cache->SlabList;
+         ListEntry = ListEntry->Flink) {
+        PXENBUS_CACHE_SLAB  Slab;
+
+        Slab = CONTAINING_RECORD(ListEntry, XENBUS_CACHE_SLAB, ListEntry);
+
+        Object = CacheGetObjectFromSlab(Slab);
+        if (Object != NULL)
+            break;
+    }
+
+    if (Object == NULL) {
+        PXENBUS_CACHE_SLAB  Slab;
+
+        Slab = CacheCreateSlab(Cache);
+        if (Slab != NULL)
+            Object = CacheGetObjectFromSlab(Slab);
+    }
+
+    if (!Locked)
+        __CacheReleaseLock(Cache);
 
 done:
     KeLowerIrql(Irql);
 
-    (VOID) InterlockedIncrement(&Cache->GetCount);
-
     return Object;
 }
 
 static VOID
 CachePut(
-    IN  PINTERFACE      Interface,
-    IN  PXENBUS_CACHE   Cache,
-    IN  PVOID           Object,
-    IN  BOOLEAN         Locked
+    IN  PINTERFACE          Interface,
+    IN  PXENBUS_CACHE       Cache,
+    IN  PVOID               Object,
+    IN  BOOLEAN             Locked
     )
 {
-    KIRQL               Irql;
-    ULONG               Index;
+    KIRQL                   Irql;
+    ULONG                   Index;
+    PXENBUS_CACHE_MAGAZINE  Magazine;
+    PXENBUS_CACHE_SLAB      Slab;
+    NTSTATUS                status;
 
     UNREFERENCED_PARAMETER(Interface);
 
-    (VOID) InterlockedIncrement(&Cache->PutCount);
-
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
     Index = KeGetCurrentProcessorNumberEx(NULL);
 
-    if (CachePutObjectToMagazine(Cache, Index, Object))
+    ASSERT3U(Index, <, Cache->MagazineCount);
+    Magazine = &Cache->Magazine[Index];
+
+    status = CachePutObjectToMagazine(Magazine, Object);
+
+    if (NT_SUCCESS(status))
         goto done;
 
-    CachePutObjectToList(Cache, Object, Locked);
+    Slab = (PXENBUS_CACHE_SLAB)PAGE_ALIGN(Object);
+    ASSERT3U(Slab->Magic, ==, XENBUS_CACHE_SLAB_MAGIC);
+
+    CachePutObjectToSlab(Slab, Object);
+
+    if (Slab->Allocated != 0)
+        goto done;
+
+    if (!Locked)
+        __CacheAcquireLock(Cache);
+
+    (VOID) CacheDestroySlab(Cache, Slab);
+
+    if (!Locked)
+        __CacheReleaseLock(Cache);
 
 done:
     KeLowerIrql(Irql);
 }
 
-static FORCEINLINE VOID
-CacheFlushMagazines(
+static FORCEINLINE NTSTATUS
+__CacheFill(
     IN  PXENBUS_CACHE   Cache
     )
 {
-    ULONG               Index;
+    KIRQL               Irql;
+    NTSTATUS            status;
 
-    for (Index = 0; Index < Cache->MagazineCount; Index++) {
-        PVOID   Object;
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __CacheAcquireLock(Cache);
+
+    while (Cache->Count < Cache->Reservation) {
+        PXENBUS_CACHE_SLAB  Slab;
+
+        Slab = CacheCreateSlab(Cache);
 
-        while ((Object = CacheGetObjectFromMagazine(Cache, Index)) != NULL)
-            CachePutObjectToList(Cache, Object, TRUE);
+        status = STATUS_NO_MEMORY;
+        if (Slab == NULL)
+            goto fail1;
     }
-}
 
-static VOID
-CacheDestroyObject(
-    IN  PXENBUS_CACHE           Cache,
-    IN  PVOID                   Object
-    )
-{
-    PXENBUS_CACHE_OBJECT_HEADER Header;
+    __CacheReleaseLock(Cache);
+    KeLowerIrql(Irql);
 
-    Header = Object;
-    --Header;
-    ASSERT3U(Header->Magic, ==, XENBUS_CACHE_OBJECT_HEADER_MAGIC);
+    return STATUS_SUCCESS;
 
-    Cache->Dtor(Cache->Argument, Object);
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Cache->SlabList)) {
+        PLIST_ENTRY         ListEntry = Cache->SlabList.Flink;
+        PXENBUS_CACHE_SLAB  Slab;
 
-    Header->Magic = 0;
+        Slab = CONTAINING_RECORD(ListEntry, XENBUS_CACHE_SLAB, ListEntry);
+
+        (VOID) CacheDestroySlab(Cache, Slab);
+    }
+    ASSERT3U(Cache->Count, ==, 0);
 
-    ASSERT(IsZeroMemory(Header, sizeof (XENBUS_CACHE_OBJECT_HEADER)));
-    __CacheFree(Header);
+    __CacheReleaseLock(Cache);
+    KeLowerIrql(Irql);
+
+    return status;
 }
 
-static NTSTATUS
-CacheFill(
-    IN  PXENBUS_CACHE   Cache,
-    IN  ULONG           Count
+static FORCEINLINE VOID
+__CacheEmpty(
+    IN  PXENBUS_CACHE   Cache
     )
 {
-    while (Count != 0) {
-        PVOID   Object = CacheCreateObject(Cache);
+    KIRQL               Irql;
 
-        if (Object == NULL)
-            break;
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __CacheAcquireLock(Cache);
+
+    while (!IsListEmpty(&Cache->SlabList)) {
+        PLIST_ENTRY         ListEntry = Cache->SlabList.Flink;
+        PXENBUS_CACHE_SLAB  Slab;
+        NTSTATUS            status;
 
-        CachePutObjectToList(Cache, Object, FALSE);
-        --Count;
+        Slab = CONTAINING_RECORD(ListEntry, XENBUS_CACHE_SLAB, ListEntry);
+
+        status = CacheDestroySlab(Cache, Slab);
+        ASSERT(NT_SUCCESS(status));
     }
+    ASSERT3U(Cache->Count, ==, 0);
 
-    return (Count == 0) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+    __CacheReleaseLock(Cache);
+    KeLowerIrql(Irql);
 }
 
-static VOID
-CacheSpill(
-    IN  PXENBUS_CACHE   Cache,
-    IN  ULONG           Count
+static FORCEINLINE VOID
+__CacheFlushMagazines(
+    IN  PXENBUS_CACHE   Cache
     )
 {
-    while (Count != 0) {
-        PVOID   Object = CacheGetObjectFromList(Cache, FALSE);
+    ULONG               Index;
 
-        if (Object == NULL)
-            break;
+    for (Index = 0; Index < Cache->MagazineCount; Index++) {
+        PXENBUS_CACHE_MAGAZINE  Magazine = &Cache->Magazine[Index];
+        PVOID                   Object;
+
+        while ((Object = CacheGetObjectFromMagazine(Magazine)) != NULL) {
+            PXENBUS_CACHE_SLAB  Slab;
 
-        CacheDestroyObject(Cache, Object);
-        --Count;
+            Slab = (PXENBUS_CACHE_SLAB)PAGE_ALIGN(Object);
+            ASSERT3U(Slab->Magic, ==, XENBUS_CACHE_SLAB_MAGIC);
+
+            CachePutObjectToSlab(Slab, Object);
+        }
     }
 }
 
@@ -504,17 +560,20 @@ CacheCreate(
         goto fail2;
 
     (*Cache)->Size = Size;
+    (*Cache)->Reservation = Reservation;
     (*Cache)->Ctor = Ctor;
     (*Cache)->Dtor = Dtor;
     (*Cache)->AcquireLock = AcquireLock;
     (*Cache)->ReleaseLock = ReleaseLock;
     (*Cache)->Argument = Argument;
 
-    InitializeListHead(&(*Cache)->GetList);
+    InitializeListHead(&(*Cache)->SlabList);
 
-    status =  CacheFill(*Cache, Reservation);
-    if (!NT_SUCCESS(status))
-        goto fail3;
+    if ((*Cache)->Reservation != 0) {
+        status = __CacheFill(*Cache);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+    }
 
     (*Cache)->MagazineCount = 
KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);
     (*Cache)->Magazine = __CacheAllocate(sizeof (XENBUS_CACHE_MAGAZINE) * 
(*Cache)->MagazineCount);
@@ -523,8 +582,6 @@ CacheCreate(
     if ((*Cache)->Magazine == NULL)
         goto fail4;
 
-    (*Cache)->Reservation = Reservation;
-
     KeAcquireSpinLock(&Context->Lock, &Irql);
     InsertTailList(&Context->List, &(*Cache)->ListEntry);
     KeReleaseSpinLock(&Context->Lock, Irql);
@@ -538,10 +595,13 @@ fail4:
 
     (*Cache)->MagazineCount = 0;
 
+    __CacheEmpty(*Cache);
+
 fail3:
     Error("fail3\n");
 
-    RtlZeroMemory(&(*Cache)->GetList, sizeof (LIST_ENTRY));
+    ASSERT(IsListEmpty(&(*Cache)->SlabList));
+    RtlZeroMemory(&(*Cache)->SlabList, sizeof (LIST_ENTRY));
 
     (*Cache)->Argument = NULL;
     (*Cache)->ReleaseLock = NULL;
@@ -581,23 +641,18 @@ CacheDestroy(
 
     RtlZeroMemory(&Cache->ListEntry, sizeof (LIST_ENTRY));
 
-    ASSERT3U(Cache->PutCount, ==, Cache->GetCount);
-    Cache->PutCount = 0;
-    Cache->GetCount = 0;
-
-    Cache->Reservation = 0;
-    CacheFlushMagazines(Cache);
+    __CacheFlushMagazines(Cache);
 
     ASSERT(IsZeroMemory(Cache->Magazine, sizeof (XENBUS_CACHE_MAGAZINE) * 
Cache->MagazineCount));
     __CacheFree(Cache->Magazine);
     Cache->Magazine = NULL;
     Cache->MagazineCount = 0;
 
-    CacheSpill(Cache, Cache->ListCount);
-    ASSERT3U(Cache->ListCount, ==, 0);
+    __CacheEmpty(Cache);
+    Cache->Reservation = 0;
 
-    ASSERT(IsListEmpty(&Cache->GetList));
-    RtlZeroMemory(&Cache->GetList, sizeof (LIST_ENTRY));
+    ASSERT(IsListEmpty(&Cache->SlabList));
+    RtlZeroMemory(&Cache->SlabList, sizeof (LIST_ENTRY));
 
     Cache->Argument = NULL;
     Cache->ReleaseLock = NULL;
@@ -642,79 +697,12 @@ CacheDebugCallback(
                          &Context->DebugInterface,
                          "- %s: Count = %d (Reservation = %d)\n",
                          Cache->Name,
-                         Cache->ListCount,
+                         Cache->Count,
                          Cache->Reservation);
         }
     }
 }
 
-#define TIME_US(_us)        ((_us) * 10)
-#define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
-#define TIME_S(_s)          (TIME_MS((_s) * 1000))
-#define TIME_RELATIVE(_t)   (-(_t))
-
-#define XENBUS_CACHE_MONITOR_PERIOD 5
-
-static NTSTATUS
-CacheMonitor(
-    IN  PXENBUS_THREAD      Self,
-    IN  PVOID               _Context
-    )
-{
-    PXENBUS_CACHE_CONTEXT   Context = _Context;
-    PKEVENT                 Event;
-    LARGE_INTEGER           Timeout;
-    PLIST_ENTRY             ListEntry;
-
-    Trace("====>\n");
-
-    Event = ThreadGetEvent(Self);
-
-    Timeout.QuadPart = TIME_RELATIVE(TIME_S(XENBUS_CACHE_MONITOR_PERIOD));
-
-    for (;;) {
-        KIRQL   Irql;
-
-        (VOID) KeWaitForSingleObject(Event,
-                                     Executive,
-                                     KernelMode,
-                                     FALSE,
-                                     &Timeout);
-        KeClearEvent(Event);
-
-        if (ThreadIsAlerted(Self))
-            break;
-
-        KeAcquireSpinLock(&Context->Lock, &Irql);
-
-        if (Context->References == 0)
-            goto loop;
-
-        for (ListEntry = Context->List.Flink;
-             ListEntry != &Context->List;
-             ListEntry = ListEntry->Flink) {
-            PXENBUS_CACHE   Cache;
-            ULONG           Count;
-
-            Cache = CONTAINING_RECORD(ListEntry, XENBUS_CACHE, ListEntry);
-
-            Count = Cache->ListCount;
-
-            if (Count < Cache->Reservation)
-                CacheFill(Cache, Cache->Reservation - Count);
-            else if (Count > Cache->Reservation)
-                CacheSpill(Cache, (Count - Cache->Reservation + 1) / 2);
-        }
-
-loop:
-        KeReleaseSpinLock(&Context->Lock, Irql);
-    }
-
-    Trace("====>\n");
-
-    return STATUS_SUCCESS;
-}
-
 static NTSTATUS
 CacheAcquire(
     PINTERFACE              Interface
@@ -833,25 +821,12 @@ CacheInitialize(
     InitializeListHead(&(*Context)->List);
     KeInitializeSpinLock(&(*Context)->Lock);
 
-    status = ThreadCreate(CacheMonitor, *Context, &(*Context)->MonitorThread);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
     (*Context)->Fdo = Fdo;
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
-
-    RtlZeroMemory(&(*Context)->Lock, sizeof (KSPIN_LOCK));
-    RtlZeroMemory(&(*Context)->List, sizeof (LIST_ENTRY));
-
-    RtlZeroMemory(&(*Context)->DebugInterface,
-                  sizeof (XENBUS_DEBUG_INTERFACE));
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -913,10 +888,6 @@ CacheTeardown(
 
     Context->Fdo = NULL;
 
-    ThreadAlert(Context->MonitorThread);
-    ThreadJoin(Context->MonitorThread);
-    Context->MonitorThread = NULL;
-
     RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY));
 
diff --git a/vs2015/xenbus/xenbus.vcxproj b/vs2015/xenbus/xenbus.vcxproj
index 038d3d7..65e416c 100644
--- a/vs2015/xenbus/xenbus.vcxproj
+++ b/vs2015/xenbus/xenbus.vcxproj
@@ -23,7 +23,7 @@
       
<PreprocessorDefinitions>__MODULE__="XENBUS";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;</AdditionalIncludeDirectories>
       <WarningLevel>EnableAllWarnings</WarningLevel>
-      
<DisableSpecificWarnings>4464;4711;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      
<DisableSpecificWarnings>4146;4464;4711;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <EnablePREfast>true</EnablePREfast>
     </ClCompile>
diff --git a/vs2017/xenbus/xenbus.vcxproj b/vs2017/xenbus/xenbus.vcxproj
index f3e62ec..b418a24 100644
--- a/vs2017/xenbus/xenbus.vcxproj
+++ b/vs2017/xenbus/xenbus.vcxproj
@@ -24,7 +24,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;</AdditionalIncludeDirectories>
       <WarningLevel>EnableAllWarnings</WarningLevel>
-      
<DisableSpecificWarnings>4464;4711;4770;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      
<DisableSpecificWarnings>4146;4464;4711;4770;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <EnablePREfast>true</EnablePREfast>
     </ClCompile>
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.