Spin for a bit before falling back to event object
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
66e51bd08f
commit
1914547ab3
39
wintun.c
39
wintun.c
@ -330,6 +330,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
|
|||||||
KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
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 */
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -345,18 +346,40 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
|
|||||||
ULONG RingTail = InterlockedGetU(&Ring->Tail);
|
ULONG RingTail = InterlockedGetU(&Ring->Tail);
|
||||||
if (RingHead == RingTail)
|
if (RingHead == RingTail)
|
||||||
{
|
{
|
||||||
InterlockedExchange(&Ring->Alertable, TRUE);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
||||||
RingTail = InterlockedGetU(&Ring->Tail);
|
ULONG64 SpinStart;
|
||||||
|
KeQueryTickCount(&SpinStart);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
RingTail = InterlockedGetU(&Ring->Tail);
|
||||||
|
if (RingTail != RingHead)
|
||||||
|
break;
|
||||||
|
if (!(InterlockedGet(&Ctx->Flags) & TUN_FLAGS_CONNECTED))
|
||||||
|
break;
|
||||||
|
ULONG64 SpinNow;
|
||||||
|
KeQueryTickCount(&SpinNow);
|
||||||
|
if (SpinNow - SpinStart >= SpinMax)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
{
|
{
|
||||||
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
InterlockedExchange(&Ring->Alertable, TRUE);
|
||||||
KeWaitForSingleObject(Ctx->Device.Receive.TailMoved, Executive, KernelMode, FALSE, NULL);
|
RingTail = InterlockedGetU(&Ring->Tail);
|
||||||
|
if (RingHead == RingTail)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(Ctx->Device.Receive.TailMoved, Executive, KernelMode, FALSE, NULL);
|
||||||
|
InterlockedExchange(&Ring->Alertable, FALSE);
|
||||||
|
Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
InterlockedExchange(&Ring->Alertable, FALSE);
|
InterlockedExchange(&Ring->Alertable, FALSE);
|
||||||
Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
KeClearEvent(Ctx->Device.Receive.TailMoved);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
InterlockedExchange(&Ring->Alertable, FALSE);
|
Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
KeClearEvent(Ctx->Device.Receive.TailMoved);
|
|
||||||
}
|
}
|
||||||
if (RingTail >= RingCapacity)
|
if (RingTail >= RingCapacity)
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user