IN PXENBUS_EVTCHN_CHANNEL Channel
);
+/*! \typedef XENBUS_EVTCHN_GET_COUNT
+ \brief Get the number of events received by the channel since it was opened
+
+ \param Interface The interface header
+ \param Channel The channel handle
+ \return The number of events
+*/
+typedef ULONG
+(*XENBUS_EVTCHN_GET_COUNT)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel
+ );
+
+typedef NTSTATUS
+(*XENBUS_EVTCHN_WAIT_V5)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN PLARGE_INTEGER Timeout OPTIONAL
+ );
+
/*! \typedef XENBUS_EVTCHN_WAIT
- \brief Wait for an event to the local end of the channel
+ \brief Wait for events to the local end of the channel
\param Interface The interface header
\param Channel The channel handle
+ \param Count The event count to wait for
\param Timeout An optional timeout value (similar to KeWaitForSingleObject(), but non-zero values are allowed at DISPATCH_LEVEL).
*/
typedef NTSTATUS
(*XENBUS_EVTCHN_WAIT)(
IN PINTERFACE Interface,
IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN ULONG Count,
IN PLARGE_INTEGER Timeout OPTIONAL
);
XENBUS_EVTCHN_UNMASK EvtchnUnmask;
XENBUS_EVTCHN_SEND_V1 EvtchnSendVersion1;
XENBUS_EVTCHN_TRIGGER EvtchnTrigger;
- XENBUS_EVTCHN_WAIT EvtchnWait;
+ XENBUS_EVTCHN_WAIT_V5 EvtchnWaitVersion5;
XENBUS_EVTCHN_GET_PORT EvtchnGetPort;
XENBUS_EVTCHN_CLOSE EvtchnClose;
};
XENBUS_EVTCHN_UNMASK EvtchnUnmask;
XENBUS_EVTCHN_SEND EvtchnSend;
XENBUS_EVTCHN_TRIGGER EvtchnTrigger;
+ XENBUS_EVTCHN_WAIT_V5 EvtchnWaitVersion5;
+ XENBUS_EVTCHN_GET_PORT EvtchnGetPort;
+ XENBUS_EVTCHN_CLOSE EvtchnClose;
+};
+
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V7
+ \brief EVTCHN interface version 7
+ \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V7 {
+ INTERFACE Interface;
+ XENBUS_EVTCHN_ACQUIRE EvtchnAcquire;
+ XENBUS_EVTCHN_RELEASE EvtchnRelease;
+ XENBUS_EVTCHN_OPEN EvtchnOpen;
+ XENBUS_EVTCHN_BIND EvtchnBind;
+ XENBUS_EVTCHN_UNMASK EvtchnUnmask;
+ XENBUS_EVTCHN_SEND EvtchnSend;
+ XENBUS_EVTCHN_TRIGGER EvtchnTrigger;
+ XENBUS_EVTCHN_GET_COUNT EvtchnGetCount;
XENBUS_EVTCHN_WAIT EvtchnWait;
XENBUS_EVTCHN_GET_PORT EvtchnGetPort;
XENBUS_EVTCHN_CLOSE EvtchnClose;
};
-typedef struct _XENBUS_EVTCHN_INTERFACE_V6 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+typedef struct _XENBUS_EVTCHN_INTERFACE_V7 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
/*! \def XENBUS_EVTCHN
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 6
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 7
#endif // _XENBUS_EVTCHN_INTERFACE_H
DEFINE_REVISION(0x08000009, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1), \
DEFINE_REVISION(0x0800000A, 1, 2, 5, 1, 1, 1, 1, 1, 1, 1), \
DEFINE_REVISION(0x0800000B, 1, 2, 5, 1, 2, 1, 1, 2, 1, 1), \
- DEFINE_REVISION(0x0800000C, 1, 2, 6, 1, 2, 1, 1, 2, 1, 1)
+ DEFINE_REVISION(0x0800000C, 1, 2, 6, 1, 2, 1, 1, 2, 1, 1), \
+ DEFINE_REVISION(0x0800000D, 1, 2, 7, 1, 2, 1, 1, 2, 1, 1)
#endif // _REVISION_H
PKSERVICE_ROUTINE Callback;
PVOID Argument;
BOOLEAN Active; // Must be tested at >= DISPATCH_LEVEL
- ULONG Events;
+ ULONG Count;
XENBUS_EVTCHN_TYPE Type;
XENBUS_EVTCHN_PARAMETERS Parameters;
BOOLEAN Mask;
Trace("%u\n", LocalPort);
- Channel->Events = 0;
+ Channel->Count = 0;
ASSERT(Channel->Closed);
Channel->Closed = FALSE;
KeMemoryBarrier();
if (!Channel->Closed) {
- Channel->Events++;
+ Channel->Count++;
RemoveEntryList(&Channel->PendingListEntry);
InitializeListHead(&Channel->PendingListEntry);
return Channel->LocalPort;
}
+static ULONG
+EvtchnGetCount(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel
+ )
+{
+ UNREFERENCED_PARAMETER(Interface);
+
+ return Channel->Count;
+}
+
static NTSTATUS
EvtchnWait(
IN PINTERFACE Interface,
IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN ULONG Count,
IN PLARGE_INTEGER Timeout
)
{
KIRQL Irql;
- ULONG Events;
LARGE_INTEGER Start;
NTSTATUS status;
ASSERT3U(KeGetCurrentIrql(), <=, DISPATCH_LEVEL);
KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
- Events = Channel->Events;
- KeMemoryBarrier();
-
KeQuerySystemTime(&Start);
for (;;) {
+ KeMemoryBarrier();
+
status = STATUS_SUCCESS;
- if (Channel->Events != Events)
+ if ((LONG64)Count - (LONG64)Channel->Count <= 0)
break;
if (Timeout != NULL) {
}
_mm_pause();
- KeMemoryBarrier();
}
+ if (status == STATUS_TIMEOUT)
+ Info("TIMED OUT: Count = %08x Channel->Count = %08x\n",
+ Count,
+ Channel->Count);
+
KeLowerIrql(Irql);
return status;
}
+static NTSTATUS
+EvtchnWaitVersion5(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN PLARGE_INTEGER Timeout
+ )
+{
+ ULONG Count;
+
+ Count = EvtchnGetCount(Interface, Channel);
+
+ return EvtchnWait(Interface,
+ Channel,
+ Count + 1,
+ Timeout);
+}
+
static
_Function_class_(KSERVICE_ROUTINE)
__drv_requiresIRQL(HIGH_LEVEL)
XENBUS_DEBUG(Printf,
&Context->DebugInterface,
- "Events = %lu\n",
- Channel->Events);
+ "Count = %lu\n",
+ Channel->Count);
}
}
}
EvtchnUnmask,
EvtchnSendVersion1,
EvtchnTrigger,
- EvtchnWait,
+ EvtchnWaitVersion5,
EvtchnGetPort,
EvtchnClose,
};
EvtchnUnmask,
EvtchnSend,
EvtchnTrigger,
+ EvtchnWaitVersion5,
+ EvtchnGetPort,
+ EvtchnClose,
+};
+
+static struct _XENBUS_EVTCHN_INTERFACE_V7 EvtchnInterfaceVersion7 = {
+ { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V7), 7, NULL, NULL, NULL },
+ EvtchnAcquire,
+ EvtchnRelease,
+ EvtchnOpen,
+ EvtchnBind,
+ EvtchnUnmask,
+ EvtchnSend,
+ EvtchnTrigger,
+ EvtchnGetCount,
EvtchnWait,
EvtchnGetPort,
EvtchnClose,
status = STATUS_SUCCESS;
break;
}
+ case 7: {
+ struct _XENBUS_EVTCHN_INTERFACE_V7 *EvtchnInterface;
+
+ EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V7 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V7))
+ break;
+
+ *EvtchnInterface = EvtchnInterfaceVersion7;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
{
PXENBUS_STORE_RESPONSE Response;
KIRQL Irql;
+ ULONG Count;
LARGE_INTEGER Timeout;
ASSERT3U(Request->State, ==, XENBUS_STORE_REQUEST_PREPARED);
InsertTailList(&Context->SubmittedList, &Request->ListEntry);
Request->State = XENBUS_STORE_REQUEST_SUBMITTED;
+
+ Count = XENBUS_EVTCHN(GetCount,
+ &Context->EvtchnInterface,
+ Context->Channel);
+
StorePollLocked(Context);
KeMemoryBarrier();
status = XENBUS_EVTCHN(Wait,
&Context->EvtchnInterface,
Context->Channel,
+ Count + 1,
&Timeout);
if (status == STATUS_TIMEOUT)
Warning("TIMED OUT\n");
+ Count = XENBUS_EVTCHN(GetCount,
+ &Context->EvtchnInterface,
+ Context->Channel);
+
StorePollLocked(Context);
KeMemoryBarrier();
}