Spin less and more efficiently

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2019-08-03 20:43:16 +00:00
parent bc22e2dd25
commit 85a8076d08
3 changed files with 7 additions and 6 deletions

View File

@ -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. When closing the handle, Wintun will set the `Tail` to 0xFFFFFFFF and set the `TailMoved` event to unblock the waiting user process.

View File

@ -37,3 +37,5 @@ ZwQuerySystemInformation(
PVOID SystemInformation, PVOID SystemInformation,
ULONG SystemInformationLength, ULONG SystemInformationLength,
ULONG *ReturnLength); ULONG *ReturnLength);
extern NTSTATUS ZwYieldExecution(VOID);

View File

@ -402,9 +402,11 @@ _Function_class_(KSTART_ROUTINE)
static VOID static VOID
TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
{ {
KeSetPriorityThread(KeGetCurrentThread(), 1);
TUN_RING *Ring = Ctx->Device.Receive.Ring; TUN_RING *Ring = Ctx->Device.Receive.Ring;
ULONG RingCapacity = Ctx->Device.Receive.Capacity; 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 }; VOID *Events[] = { &Ctx->Device.Disconnected, Ctx->Device.Receive.TailMoved };
ASSERT(RTL_NUMBER_OF(Events) <= THREAD_WAIT_OBJECTS); ASSERT(RTL_NUMBER_OF(Events) <= THREAD_WAIT_OBJECTS);
@ -431,10 +433,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
KeQueryTickCount(&SpinNow); KeQueryTickCount(&SpinNow);
if ((ULONG64)SpinNow.QuadPart - (ULONG64)SpinStart.QuadPart >= SpinMax) if ((ULONG64)SpinNow.QuadPart - (ULONG64)SpinStart.QuadPart >= SpinMax)
break; break;
ZwYieldExecution();
/* This should really call KeYieldProcessorEx(&zero), so it does the Hyper-V paravirtualization call,
* but it's not exported. */
YieldProcessor();
} }
if (RingHead == RingTail) if (RingHead == RingTail)
{ {