[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 05/10] Use a hash table for event channel lookup
Rather than using a large array for mapping port values to channel structures, use a hash table. This means we no longer need to code a hard port number limit into the EVTCHN implementation. Because the hash table implementation manages its own locking, we also no longer need to make such liberal use of the interrupt lock in the EVTCHN implementation and can use the spinlock instead. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/evtchn_interface.h | 4 +- include/shared_info_interface.h | 3 - src/xenbus/evtchn.c | 89 ++++++---- src/xenbus/hash_table.c | 367 ++++++++++++++++++++++++++++++++++++++++ src/xenbus/hash_table.h | 70 ++++++++ src/xenbus/shared_info.c | 3 + vs2012/xenbus/xenbus.vcxproj | 1 + vs2013/xenbus/xenbus.vcxproj | 3 +- 8 files changed, 504 insertions(+), 36 deletions(-) create mode 100644 src/xenbus/hash_table.c create mode 100644 src/xenbus/hash_table.h diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h index 991d610..3a48915 100644 --- a/include/evtchn_interface.h +++ b/include/evtchn_interface.h @@ -117,14 +117,14 @@ typedef PXENBUS_EVTCHN_CHANNEL \param Interface The interface header \param Channel The channel handle - \param Locked Set to TRUE if this method is invoked in context of the channel callback + \param InCallback Set to TRUE if this method is invoked in context of the channel callback \return TRUE if there was an event pending at the point of unmask, FALSE otherwise */ typedef BOOLEAN (*XENBUS_EVTCHN_UNMASK)( IN PINTERFACE Interface, IN PXENBUS_EVTCHN_CHANNEL Channel, - IN BOOLEAN Locked + IN BOOLEAN InCallback ); /*! \typedef XENBUS_EVTCHN_SEND diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h index 0d36ac8..0e5a0d7 100644 --- a/include/shared_info_interface.h +++ b/include/shared_info_interface.h @@ -40,9 +40,6 @@ #ifndef _WINDLL -#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR (sizeof (ULONG_PTR) * 8) -#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR)) - /*! \typedef XENBUS_SHARED_INFO_ACQUIRE \brief Acquire a reference to the SHARED_INFO interface diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index 35ad44a..338a90f 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -36,6 +36,7 @@ #include "evtchn.h" #include "fdo.h" +#include "hash_table.h" #include "dbg_print.h" #include "assert.h" @@ -97,7 +98,7 @@ struct _XENBUS_EVTCHN_CONTEXT { XENBUS_DEBUG_INTERFACE DebugInterface; PXENBUS_DEBUG_CALLBACK DebugCallback; XENBUS_SHARED_INFO_INTERFACE SharedInfoInterface; - PXENBUS_EVTCHN_CHANNEL Channel[XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR]; + PXENBUS_HASH_TABLE Table; LIST_ENTRY List; }; @@ -351,14 +352,16 @@ EvtchnOpen( LocalPort = Channel->LocalPort; - ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0])); - - (VOID) __EvtchnAcquireInterruptLock(Context); + status = HashTableAdd(Context->Table, + LocalPort, + (ULONG_PTR)Channel); + if (!NT_SUCCESS(status)) + goto fail3; - ASSERT3P(Context->Channel[LocalPort], ==, NULL); - Context->Channel[LocalPort] = Channel; Channel->Active = TRUE; + KeAcquireSpinLockAtDpcLevel(&Context->Lock); + InsertTailList(&Context->List, &Channel->ListEntry); if (!IsListEmpty(&Context->List) && !Context->Enabled) { @@ -366,12 +369,18 @@ EvtchnOpen( Context->Enabled = TRUE; } - __EvtchnReleaseInterruptLock(Context, DISPATCH_LEVEL); + KeReleaseSpinLockFromDpcLevel(&Context->Lock); KeLowerIrql(Irql); return Channel; +fail3: + Error("fail3\n"); + + Channel->LocalPort = 0; + RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS)); + fail2: Error("fail2\n"); @@ -398,7 +407,7 @@ static BOOLEAN EvtchnUnmask( IN PINTERFACE Interface, IN PXENBUS_EVTCHN_CHANNEL Channel, - IN BOOLEAN Locked + IN BOOLEAN InCallback ) { PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; @@ -407,8 +416,10 @@ EvtchnUnmask( ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); - if (!Locked) - Irql = __EvtchnAcquireInterruptLock(Context); + if (!InCallback) + KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend + + ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); if (Channel->Active) { Pending = XENBUS_SHARED_INFO(EvtchnUnmask, @@ -446,8 +457,8 @@ EvtchnUnmask( } } - if (!Locked) - __EvtchnReleaseInterruptLock(Context, Irql); + if (!InCallback) + KeLowerIrql(Irql); return Pending; } @@ -513,6 +524,8 @@ EvtchnTrigger( Irql = __EvtchnAcquireInterruptLock(Context); + ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); + if (Channel->Active) { DoneSomething = EvtchnCallback(Context, Channel); } else { @@ -536,7 +549,9 @@ EvtchnClose( ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); - Irql = __EvtchnAcquireInterruptLock(Context); + KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend + + KeAcquireSpinLockAtDpcLevel(&Context->Lock); RemoveEntryList(&Channel->ListEntry); @@ -545,12 +560,13 @@ EvtchnClose( Context->Enabled = FALSE; } + KeReleaseSpinLockFromDpcLevel(&Context->Lock); + RtlZeroMemory(&Channel->ListEntry, sizeof (LIST_ENTRY)); if (Channel->Active) { - ULONG LocalPort = Channel->LocalPort; - - ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0])); + ULONG LocalPort = Channel->LocalPort; + NTSTATUS status; Channel->Active = FALSE; @@ -561,12 +577,10 @@ EvtchnClose( if (Channel->Type != XENBUS_EVTCHN_TYPE_FIXED) (VOID) EventChannelClose(LocalPort); - ASSERT(Context->Channel[LocalPort] != NULL); - Context->Channel[LocalPort] = NULL; + status = HashTableRemove(Context->Table, LocalPort); + ASSERT(NT_SUCCESS(status)); } - __EvtchnReleaseInterruptLock(Context, Irql); - Channel->LocalPort = 0; RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS)); @@ -580,6 +594,8 @@ EvtchnClose( ASSERT(IsZeroMemory(Channel, sizeof (XENBUS_EVTCHN_CHANNEL))); __EvtchnFree(Channel); + + KeLowerIrql(Irql); } static ULONG @@ -606,12 +622,13 @@ EvtchnPollCallback( PXENBUS_EVTCHN_CHANNEL Channel; BOOLEAN Mask; BOOLEAN DoneSomething; + NTSTATUS status; - ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0])); - - Channel = Context->Channel[LocalPort]; - - if (Channel == NULL) { + status = HashTableLookup(Context->Table, + LocalPort, + (PULONG_PTR)&Channel); + + if (!NT_SUCCESS(status)) { Warning("[%d]: INVALID PORT\n", LocalPort); XENBUS_SHARED_INFO(EvtchnMask, @@ -697,14 +714,13 @@ EvtchnSuspendCallbackEarly( Channel = CONTAINING_RECORD(ListEntry, XENBUS_EVTCHN_CHANNEL, ListEntry); if (Channel->Active) { - ULONG LocalPort = Channel->LocalPort; - - ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0])); + ULONG LocalPort = Channel->LocalPort; + NTSTATUS status; Channel->Active = FALSE; - ASSERT(Context->Channel[LocalPort] != NULL); - Context->Channel[LocalPort] = NULL; + status = HashTableRemove(Context->Table, LocalPort); + ASSERT(NT_SUCCESS(status)); } } @@ -958,6 +974,10 @@ EvtchnInitialize( if (*Context == NULL) goto fail1; + status = HashTableCreate(&(*Context)->Table); + if (!NT_SUCCESS(status)) + goto fail2; + status = SuspendGetInterface(FdoGetSuspendContext(Fdo), XENBUS_SUSPEND_INTERFACE_VERSION_MAX, (PINTERFACE)&(*Context)->SuspendInterface, @@ -988,6 +1008,12 @@ EvtchnInitialize( return STATUS_SUCCESS; +fail2: + Error("fail2\n"); + + ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT))); + __EvtchnFree(Context); + fail1: Error("fail1 (%08x)\n", status); @@ -1053,6 +1079,9 @@ EvtchnTeardown( RtlZeroMemory(&Context->SuspendInterface, sizeof (XENBUS_SUSPEND_INTERFACE)); + HashTableDestroy(Context->Table); + Context->Table = NULL; + ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT))); __EvtchnFree(Context); diff --git a/src/xenbus/hash_table.c b/src/xenbus/hash_table.c new file mode 100644 index 0000000..b8e27d8 --- /dev/null +++ b/src/xenbus/hash_table.c @@ -0,0 +1,367 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <ntddk.h> +#include <stdarg.h> +#include <xen.h> +#include <util.h> + +#include "hash_table.h" +#include "dbg_print.h" +#include "assert.h" + +typedef struct _XENBUS_HASH_TABLE_NODE { + LIST_ENTRY ListEntry; + ULONG_PTR Key; + ULONG_PTR Value; +} XENBUS_HASH_TABLE_NODE, *PXENBUS_HASH_TABLE_NODE; + +typedef struct _XENBUS_HASH_TABLE_BUCKET { + LONG Lock; + LIST_ENTRY List; +} XENBUS_HASH_TABLE_BUCKET, *PXENBUS_HASH_TABLE_BUCKET; + +#define XENBUS_HASH_TABLE_NR_BUCKETS \ + (1 << (sizeof (UCHAR) * 8)) + +struct _XENBUS_HASH_TABLE { + XENBUS_HASH_TABLE_BUCKET Bucket[XENBUS_HASH_TABLE_NR_BUCKETS]; +}; + +#define XENBUS_HASH_TABLE_TAG 'HSAH' + +static FORCEINLINE PVOID +__HashTableAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_HASH_TABLE_TAG); +} + +static FORCEINLINE VOID +__HashTableFree( + IN PVOID Buffer + ) +{ + ExFreePoolWithTag(Buffer, XENBUS_HASH_TABLE_TAG); +} + +static ULONG +HashTableHash( + IN ULONG_PTR Key + ) +{ + PUCHAR Array = (PUCHAR)&Key; + ULONG Accumulator; + ULONG Index; + + Accumulator = 0; + + for (Index = 0; Index < sizeof (ULONG_PTR); Index++) { + ULONG Overflow; + + Accumulator = (Accumulator << 4) + Array[Index]; + + Overflow = Accumulator & 0x00000f00; + if (Overflow != 0) { + Accumulator ^= Overflow >> 8; + Accumulator ^= Overflow; + } + } + + ASSERT3U(Accumulator, <, XENBUS_HASH_TABLE_NR_BUCKETS); + + return Accumulator; +} + +static +_IRQL_requires_max_(HIGH_LEVEL) +_IRQL_saves_ +_IRQL_raises_(HIGH_LEVEL) +KIRQL +__HashTableBucketLock( + IN PXENBUS_HASH_TABLE_BUCKET Bucket, + IN BOOLEAN Writer + ) +{ + KIRQL Irql; + + KeRaiseIrql(HIGH_LEVEL, &Irql); + + for (;;) { + LONG Lock; + LONG Readers; + LONG Writers; + LONG Old; + LONG New; + + KeMemoryBarrier(); + + Lock = Bucket->Lock; + Readers = Lock >> 1; + Writers = Lock & 1; + + // There must be no existing writer + Old = Readers << 1; + + if (Writer) + Writers++; + else + Readers++; + + New = (Readers << 1) | (Writers & 1); + + if (InterlockedCompareExchange(&Bucket->Lock, New, Old) != Old) + continue; + + // + // We are done if we're not a writer, or there are no readers + // left. + // + if (!Writer || Readers == 0) + break; + } + + return Irql; +} + +#define HashTableBucketLock(_Bucket, _Writer, _Irql) \ + do { \ + *(_Irql) = __HashTableBucketLock((_Bucket), (_Writer)); \ + } while (FALSE) + +static +__drv_requiresIRQL(HIGH_LEVEL) +VOID +HashTableBucketUnlock( + IN PXENBUS_HASH_TABLE_BUCKET Bucket, + IN BOOLEAN Writer, + IN __drv_restoresIRQL KIRQL Irql + ) +{ + for (;;) { + LONG Lock; + LONG Readers; + LONG Writers; + LONG Old; + LONG New; + + KeMemoryBarrier(); + + Lock = Bucket->Lock; + Readers = Lock >> 1; + Writers = Lock & 1; + + Old = (Readers << 1) | (Writers & 1); + + if (Writer) { + ASSERT(Writers != 0); + --Writers; + } else { + --Readers; + } + + New = (Readers << 1) | (Writers & 1); + + if (InterlockedCompareExchange(&Bucket->Lock, New, Old) == Old) + break; + } + + KeLowerIrql(Irql); +} + +NTSTATUS +HashTableAdd( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key, + IN ULONG_PTR Value + ) +{ + PXENBUS_HASH_TABLE_NODE Node; + PXENBUS_HASH_TABLE_BUCKET Bucket; + KIRQL Irql; + NTSTATUS status; + + Node = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE_NODE)); + + status = STATUS_NO_MEMORY; + if (Node == NULL) + goto fail1; + + Node->Key = Key; + Node->Value = Value; + + Bucket = &Table->Bucket[HashTableHash(Key)]; + + HashTableBucketLock(Bucket, TRUE, &Irql); + InsertTailList(&Bucket->List, &Node->ListEntry); + HashTableBucketUnlock(Bucket, TRUE, Irql); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +HashTableRemove( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key + ) +{ + PXENBUS_HASH_TABLE_BUCKET Bucket; + PLIST_ENTRY ListEntry; + PXENBUS_HASH_TABLE_NODE Node; + KIRQL Irql; + NTSTATUS status; + + Bucket = &Table->Bucket[HashTableHash(Key)]; + + HashTableBucketLock(Bucket, TRUE, &Irql); + + ListEntry = Bucket->List.Flink; + while (ListEntry != &Bucket->List) { + Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry); + + if (Node->Key == Key) + goto found; + } + + HashTableBucketUnlock(Bucket, TRUE, Irql); + + status = STATUS_OBJECT_NAME_NOT_FOUND; + goto fail1; + +found: + RemoveEntryList(ListEntry); + __HashTableFree(Node); + + HashTableBucketUnlock(Bucket, TRUE, Irql); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +HashTableLookup( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key, + OUT PULONG_PTR Value + ) +{ + PXENBUS_HASH_TABLE_BUCKET Bucket; + PLIST_ENTRY ListEntry; + PXENBUS_HASH_TABLE_NODE Node; + KIRQL Irql; + NTSTATUS status; + + Bucket = &Table->Bucket[HashTableHash(Key)]; + + HashTableBucketLock(Bucket, FALSE, &Irql); + + ListEntry = Bucket->List.Flink; + while (ListEntry != &Bucket->List) { + Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry); + + if (Node->Key == Key) + goto found; + } + + HashTableBucketUnlock(Bucket, FALSE, Irql); + + status = STATUS_OBJECT_NAME_NOT_FOUND; + goto fail1; + +found: + *Value = Node->Value; + + HashTableBucketUnlock(Bucket, FALSE, Irql); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +HashTableCreate( + OUT PXENBUS_HASH_TABLE *Table + ) +{ + ULONG Index; + NTSTATUS status; + + *Table = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE)); + + status = STATUS_NO_MEMORY; + if (*Table == NULL) + goto fail1; + + for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) { + PXENBUS_HASH_TABLE_BUCKET Bucket = &(*Table)->Bucket[Index]; + + InitializeListHead(&Bucket->List); + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +VOID +HashTableDestroy( + IN PXENBUS_HASH_TABLE Table + ) +{ + ULONG Index; + + for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) { + PXENBUS_HASH_TABLE_BUCKET Bucket = &Table->Bucket[Index]; + + ASSERT(IsListEmpty(&Bucket->List)); + RtlZeroMemory(&Bucket->List, sizeof (LIST_ENTRY)); + } + + ASSERT(IsZeroMemory(Table, sizeof (XENBUS_HASH_TABLE))); + __HashTableFree(Table); +} + diff --git a/src/xenbus/hash_table.h b/src/xenbus/hash_table.h new file mode 100644 index 0000000..ce0c906 --- /dev/null +++ b/src/xenbus/hash_table.h @@ -0,0 +1,70 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XENBUS_HASH_TABLE_H +#define _XENBUS_HASH_TABLE_H + +#include <ntddk.h> + +typedef struct _XENBUS_HASH_TABLE XENBUS_HASH_TABLE, *PXENBUS_HASH_TABLE; + +extern NTSTATUS +HashTableAdd( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key, + IN ULONG_PTR Value + ); + +extern NTSTATUS +HashTableRemove( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key + ); + +extern NTSTATUS +HashTableLookup( + IN PXENBUS_HASH_TABLE Table, + IN ULONG_PTR Key, + OUT PULONG_PTR Value + ); + +extern NTSTATUS +HashTableCreate( + OUT PXENBUS_HASH_TABLE *Table + ); + +extern VOID +HashTableDestroy( + IN PXENBUS_HASH_TABLE Table + ); + +#endif // _XENBUS_HASH_TABLE_H + diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c index 0afc218..67be20c 100644 --- a/src/xenbus/shared_info.c +++ b/src/xenbus/shared_info.c @@ -38,6 +38,9 @@ #include "dbg_print.h" #include "assert.h" +#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR (sizeof (ULONG_PTR) * 8) +#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR)) + struct _XENBUS_SHARED_INFO_CONTEXT { PXENBUS_FDO Fdo; KSPIN_LOCK Lock; diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj index c30774e..a648bce 100644 --- a/vs2012/xenbus/xenbus.vcxproj +++ b/vs2012/xenbus/xenbus.vcxproj @@ -99,6 +99,7 @@ <ClCompile Include="..\..\src\xenbus\range_set.c" /> <ClCompile Include="..\..\src\xenbus\balloon.c" /> <ClCompile Include="..\..\src\xenbus\cache.c" /> + <ClCompile Include="..\..\src\xenbus\hash_table.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" /> diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj index 588b0c5..2c34ed1 100644 --- a/vs2013/xenbus/xenbus.vcxproj +++ b/vs2013/xenbus/xenbus.vcxproj @@ -1,4 +1,4 @@ -ï<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="..\configs.props" /> <PropertyGroup Label="Globals"> @@ -139,6 +139,7 @@ <ClCompile Include="..\..\src\xenbus\range_set.c" /> <ClCompile Include="..\..\src\xenbus\balloon.c" /> <ClCompile Include="..\..\src\xenbus\cache.c" /> + <ClCompile Include="..\..\src\xenbus\hash_table.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" /> -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |