From 85a8076d08d75cd939136dc01fde4a18aeb78e70 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 3 Aug 2019 20:43:16 +0000 Subject: [PATCH] Spin less and more efficiently Signed-off-by: Jason A. Donenfeld --- README.md | 2 +- undocumented.h | 2 ++ wintun.c | 9 ++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 186f637..6b2b509 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ for (;;) { } ``` -It may be desirable to spin for ~50ms before waiting on the `TailMoved` event, in order to reduce latency. +It may be desirable to spin a short amount of time before waiting on the `TailMoved` event, in order to reduce latency. When closing the handle, Wintun will set the `Tail` to 0xFFFFFFFF and set the `TailMoved` event to unblock the waiting user process. diff --git a/undocumented.h b/undocumented.h index c904c7a..cf85823 100644 --- a/undocumented.h +++ b/undocumented.h @@ -37,3 +37,5 @@ ZwQuerySystemInformation( PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength); + +extern NTSTATUS ZwYieldExecution(VOID); diff --git a/wintun.c b/wintun.c index 41e1b16..9486457 100644 --- a/wintun.c +++ b/wintun.c @@ -402,9 +402,11 @@ _Function_class_(KSTART_ROUTINE) static VOID TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) { + KeSetPriorityThread(KeGetCurrentThread(), 1); + TUN_RING *Ring = Ctx->Device.Receive.Ring; ULONG RingCapacity = Ctx->Device.Receive.Capacity; - const ULONG SpinMax = 10000 * 50 / KeQueryTimeIncrement(); /* 50ms */ + const ULONG SpinMax = 10000 * 20 / KeQueryTimeIncrement(); /* 20 ms */ VOID *Events[] = { &Ctx->Device.Disconnected, Ctx->Device.Receive.TailMoved }; ASSERT(RTL_NUMBER_OF(Events) <= THREAD_WAIT_OBJECTS); @@ -431,10 +433,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) KeQueryTickCount(&SpinNow); if ((ULONG64)SpinNow.QuadPart - (ULONG64)SpinStart.QuadPart >= SpinMax) break; - - /* This should really call KeYieldProcessorEx(&zero), so it does the Hyper-V paravirtualization call, - * but it's not exported. */ - YieldProcessor(); + ZwYieldExecution(); } if (RingHead == RingTail) {