]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix handling of network deadlines
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 13 Aug 2013 15:11:42 +0000 (19:11 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 13 Aug 2013 15:11:42 +0000 (19:11 +0400)
Ensure that deadlines affect already issued IO.

R=golang-dev, mikioh.mikioh, bradfitz
CC=golang-dev
https://golang.org/cl/12847043

src/pkg/net/fd_poll_unix.go
src/pkg/runtime/netpoll.goc

index e763c7e4d3e0cd69b1e60ec1f9d28ae20698758d..dd1bc104afc701c4795a2ce7d6f28cb466c352d5 100644 (file)
@@ -351,20 +351,29 @@ func (pd *pollDesc) Init(fd *netFD) error {
        return nil
 }
 
-// TODO(dfc) these unused error returns could be removed
-
 func (fd *netFD) setDeadline(t time.Time) error {
-       fd.setReadDeadline(t)
-       fd.setWriteDeadline(t)
-       return nil
+       return setDeadlineImpl(fd, t, true, true)
 }
 
 func (fd *netFD) setReadDeadline(t time.Time) error {
-       fd.pd.rdeadline.setTime(t)
-       return nil
+       return setDeadlineImpl(fd, t, true, false)
 }
 
 func (fd *netFD) setWriteDeadline(t time.Time) error {
-       fd.pd.wdeadline.setTime(t)
+       return setDeadlineImpl(fd, t, false, true)
+}
+
+func setDeadlineImpl(fd *netFD, t time.Time, read, write bool) error {
+       if err := fd.incref(); err != nil {
+               return err
+       }
+       defer fd.decref()
+       if read {
+               fd.pd.rdeadline.setTime(t)
+       }
+       if write {
+               fd.pd.wdeadline.setTime(t)
+       }
+       fd.pd.Wakeup()
        return nil
 }
index da6929eed2e52ad21eb74be5bd57d56a641ecd7c..3fb347c74fe11e69f8cc063f50153e8735accff5 100644 (file)
@@ -134,9 +134,13 @@ func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
 }
 
 func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
+       G *rg, *wg;
+
        runtime·lock(pd);
-       if(pd->closing)
-               goto ret;
+       if(pd->closing) {
+               runtime·unlock(pd);
+               return;
+       }
        pd->seq++;  // invalidate current timers
        // Reset current timers.
        if(pd->rt.fv) {
@@ -148,9 +152,8 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
                pd->wt.fv = nil;
        }
        // Setup new timers.
-       if(d != 0 && d <= runtime·nanotime()) {
+       if(d != 0 && d <= runtime·nanotime())
                d = -1;
-       }
        if(mode == 'r' || mode == 'r'+'w')
                pd->rd = d;
        if(mode == 'w' || mode == 'r'+'w')
@@ -180,8 +183,18 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
                        runtime·addtimer(&pd->wt);
                }
        }
-ret:
+       // If we set the new deadline in the past, unblock currently pending IO if any.
+       rg = nil;
+       wg = nil;
+       if(pd->rd < 0)
+               rg = netpollunblock(pd, 'r', false);
+       if(pd->wd < 0)
+               wg = netpollunblock(pd, 'w', false);
        runtime·unlock(pd);
+       if(rg)
+               runtime·ready(rg);
+       if(wg)
+               runtime·ready(wg);
 }
 
 func runtime_pollUnblock(pd *PollDesc) {