diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-04 10:18:42 +0000 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-04 11:13:39 +0000 |
commit | 5b872e8cf9f5b6800512005abb310596dc9ea771 (patch) | |
tree | 977e1b5e115db83b20357b90d63b54eb83b148b7 | |
parent | Spin less and more efficiently (diff) | |
download | wintun-5b872e8cf9f5b6800512005abb310596dc9ea771.tar.xz wintun-5b872e8cf9f5b6800512005abb310596dc9ea771.zip |
Use performance counter for less spinning
Previously we had to spin for a minimum of 15ms because the tick
interval is 156250 on NT. On linux, usually trips to the high
performance timers are discouraged because if they don't hit the RDTSC
path (due to being unstable or the like), they hit more expensive
hardware. I assume that's probably the same on NT, but all of tcpip.sys
and ndis.sys uses the performance counters too, so what are we going to
do?
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | wintun.c | 10 |
1 files changed, 5 insertions, 5 deletions
@@ -406,7 +406,9 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) TUN_RING *Ring = Ctx->Device.Receive.Ring; ULONG RingCapacity = Ctx->Device.Receive.Capacity; - const ULONG SpinMax = 10000 * 20 / KeQueryTimeIncrement(); /* 20 ms */ + LARGE_INTEGER Frequency; + KeQueryPerformanceCounter(&Frequency); + ULONG64 SpinMax = Frequency.QuadPart / 1000 / 10; /* 1/10 ms */ VOID *Events[] = { &Ctx->Device.Disconnected, Ctx->Device.Receive.TailMoved }; ASSERT(RTL_NUMBER_OF(Events) <= THREAD_WAIT_OBJECTS); @@ -420,8 +422,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) ULONG RingTail = InterlockedGetU(&Ring->Tail); if (RingHead == RingTail) { - LARGE_INTEGER SpinStart; - KeQueryTickCount(&SpinStart); + LARGE_INTEGER SpinStart = KeQueryPerformanceCounter(NULL); for (;;) { RingTail = InterlockedGetU(&Ring->Tail); @@ -429,8 +430,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) break; if (KeReadStateEvent(&Ctx->Device.Disconnected)) break; - LARGE_INTEGER SpinNow; - KeQueryTickCount(&SpinNow); + LARGE_INTEGER SpinNow = KeQueryPerformanceCounter(NULL); if ((ULONG64)SpinNow.QuadPart - (ULONG64)SpinStart.QuadPart >= SpinMax) break; ZwYieldExecution(); |