]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
tun: windows: spin for a bit before falling back to event object
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 17 Jul 2019 07:06:34 +0000 (09:06 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Thu, 18 Jul 2019 08:25:20 +0000 (10:25 +0200)
tun/tun_windows.go

index 49cbdadd07bee7ee391f04f0b46818318fc4ad92..d22e13082a3baa361748a714c5b8774281affc2c 100644 (file)
@@ -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 {