diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-07-17 09:06:34 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-07-18 10:25:20 +0200 |
commit | 9ea9a921178fe6b0e1e823cea2cd73d654217b4c (patch) | |
tree | 368d570652bade68ada62f73d9b6d2bb8ae605b4 /tun/tun_windows.go | |
parent | 2e24e7dcae421c45aadf4c052a33b784ad320014 (diff) |
tun: windows: spin for a bit before falling back to event object
Diffstat (limited to 'tun/tun_windows.go')
-rw-r--r-- | tun/tun_windows.go | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/tun/tun_windows.go b/tun/tun_windows.go index 49cbdad..d22e130 100644 --- a/tun/tun_windows.go +++ b/tun/tun_windows.go @@ -267,6 +267,9 @@ func (tun *NativeTun) ForceMTU(mtu int) { tun.forcedMTU = mtu } +//go:linkname procyield runtime.procyield +func procyield(cycles uint32) + // Note: Read() and Write() assume the caller comes only from a single thread; there's no locking. func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { @@ -277,6 +280,7 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { } retries := maybeRetry(1000) +top: for !tun.close { _, err := tun.getTUN() if err != nil { @@ -288,10 +292,21 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { return 0, errors.New("send ring head out of bounds") } - buffTail := atomic.LoadUint32(&tun.rings.send.ring.tail) - if buffHead == buffTail { - windows.WaitForSingleObject(tun.rings.send.tailMoved, windows.INFINITE) - continue + start := time.Now() + var buffTail uint32 + for { + buffTail = atomic.LoadUint32(&tun.rings.send.ring.tail) + if buffHead != buffTail { + break + } + if tun.close { + return 0, os.ErrClosed + } + if time.Since(start) >= time.Millisecond*50 { + windows.WaitForSingleObject(tun.rings.send.tailMoved, windows.INFINITE) + continue top + } + procyield(1) } if buffTail >= packetCapacity { if retries > 0 { |