]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: change netpoll in preparation for windows implementation
authorAlex Brainman <alex.brainman@gmail.com>
Tue, 25 Jun 2013 02:29:00 +0000 (12:29 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Tue, 25 Jun 2013 02:29:00 +0000 (12:29 +1000)
- change runtime_pollWait so it does not return
  closed or timeout if IO is ready - windows must
  know if IO has completed or not even after
  interruption;
- add (*pollDesc).Prepare(mode int) that can be
  used for both read and write, same for Wait;
- introduce runtime_pollWaitCanceled and expose
  it in net as (*pollDesc).WaitCanceled(mode int);

Full windows netpoll changes are
here https://golang.org/cl/8670044/.

R=golang-dev, dvyukov
CC=golang-dev
https://golang.org/cl/10485043

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

index c76f1de7b7cf09e5aa084ccda0648b1a6b6c571c..03ab3e429285d5e29590aa6a5b24ba612e801ac2 100644 (file)
@@ -16,6 +16,7 @@ func runtime_pollServerInit()
 func runtime_pollOpen(fd uintptr) (uintptr, int)
 func runtime_pollClose(ctx uintptr)
 func runtime_pollWait(ctx uintptr, mode int) int
+func runtime_pollWaitCanceled(ctx uintptr, mode int) int
 func runtime_pollReset(ctx uintptr, mode int) int
 func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
 func runtime_pollUnblock(ctx uintptr)
@@ -56,24 +57,42 @@ func (pd *pollDesc) Evict() bool {
        return false
 }
 
-func (pd *pollDesc) PrepareRead() error {
-       res := runtime_pollReset(pd.runtimeCtx, 'r')
+func (pd *pollDesc) Prepare(mode int) error {
+       res := runtime_pollReset(pd.runtimeCtx, mode)
        return convertErr(res)
 }
 
+func (pd *pollDesc) PrepareRead() error {
+       return pd.Prepare('r')
+}
+
 func (pd *pollDesc) PrepareWrite() error {
-       res := runtime_pollReset(pd.runtimeCtx, 'w')
+       return pd.Prepare('w')
+}
+
+func (pd *pollDesc) Wait(mode int) error {
+       res := runtime_pollWait(pd.runtimeCtx, mode)
        return convertErr(res)
 }
 
 func (pd *pollDesc) WaitRead() error {
-       res := runtime_pollWait(pd.runtimeCtx, 'r')
-       return convertErr(res)
+       return pd.Wait('r')
 }
 
 func (pd *pollDesc) WaitWrite() error {
-       res := runtime_pollWait(pd.runtimeCtx, 'w')
-       return convertErr(res)
+       return pd.Wait('w')
+}
+
+func (pd *pollDesc) WaitCanceled(mode int) {
+       runtime_pollWaitCanceled(pd.runtimeCtx, mode)
+}
+
+func (pd *pollDesc) WaitCanceledRead() {
+       pd.WaitCanceled('r')
+}
+
+func (pd *pollDesc) WaitCanceledWrite() {
+       pd.WaitCanceled('w')
 }
 
 func convertErr(res int) error {
@@ -85,6 +104,7 @@ func convertErr(res int) error {
        case 2:
                return errTimeout
        }
+       println("unreachable: ", res)
        panic("unreachable")
 }
 
index 59420f781ffa54ce9ba75366d94b2244a1b6a682..e9c0218393b56025db269df123860a949324e73e 100644 (file)
@@ -47,8 +47,8 @@ static struct
        // seq is incremented when deadlines are changed or descriptor is reused.
 } pollcache;
 
-static void    netpollblock(PollDesc*, int32);
-static G*      netpollunblock(PollDesc*, int32);
+static bool    netpollblock(PollDesc*, int32);
+static G*      netpollunblock(PollDesc*, int32, bool);
 static void    deadline(int64, Eface);
 static void    readDeadline(int64, Eface);
 static void    writeDeadline(int64, Eface);
@@ -112,11 +112,21 @@ ret:
 func runtime_pollWait(pd *PollDesc, mode int) (err int) {
        runtime·lock(pd);
        err = checkerr(pd, mode);
-       if(err)
-               goto ret;
-       netpollblock(pd, mode);
-       err = checkerr(pd, mode);
-ret:
+       if(err == 0) {
+               if(!netpollblock(pd, mode)) {
+                       err = checkerr(pd, mode);
+                       if(err == 0)
+                               runtime·throw("runtime_pollWait: unblocked by ioready");
+               }
+       }
+       runtime·unlock(pd);
+}
+
+func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
+       runtime·lock(pd);
+       // wait for ioready, ignore closing or timeouts.
+       while(!netpollblock(pd, mode))
+               ;
        runtime·unlock(pd);
 }
 
@@ -179,8 +189,8 @@ func runtime_pollUnblock(pd *PollDesc) {
                runtime·throw("runtime_pollUnblock: already closing");
        pd->closing = true;
        pd->seq++;
-       rg = netpollunblock(pd, 'r');
-       wg = netpollunblock(pd, 'w');
+       rg = netpollunblock(pd, 'r', false);
+       wg = netpollunblock(pd, 'w', false);
        if(pd->rt.fv) {
                runtime·deltimer(&pd->rt);
                pd->rt.fv = nil;
@@ -205,9 +215,9 @@ runtime·netpollready(G **gpp, PollDesc *pd, int32 mode)
        rg = wg = nil;
        runtime·lock(pd);
        if(mode == 'r' || mode == 'r'+'w')
-               rg = netpollunblock(pd, 'r');
+               rg = netpollunblock(pd, 'r', true);
        if(mode == 'w' || mode == 'r'+'w')
-               wg = netpollunblock(pd, 'w');
+               wg = netpollunblock(pd, 'w', true);
        runtime·unlock(pd);
        if(rg) {
                rg->schedlink = *gpp;
@@ -229,7 +239,8 @@ checkerr(PollDesc *pd, int32 mode)
        return 0;
 }
 
-static void
+// returns true if IO is ready, or false if timedout or closed
+static bool
 netpollblock(PollDesc *pd, int32 mode)
 {
        G **gpp;
@@ -239,17 +250,20 @@ netpollblock(PollDesc *pd, int32 mode)
                gpp = &pd->wg;
        if(*gpp == READY) {
                *gpp = nil;
-               return;
+               return true;
        }
        if(*gpp != nil)
                runtime·throw("epoll: double wait");
        *gpp = g;
        runtime·park(runtime·unlock, &pd->Lock, "IO wait");
        runtime·lock(pd);
+       if(g->param)
+               return true;
+       return false;
 }
 
 static G*
-netpollunblock(PollDesc *pd, int32 mode)
+netpollunblock(PollDesc *pd, int32 mode, bool ioready)
 {
        G **gpp, *old;
 
@@ -259,10 +273,15 @@ netpollunblock(PollDesc *pd, int32 mode)
        if(*gpp == READY)
                return nil;
        if(*gpp == nil) {
-               *gpp = READY;
+               // Only set READY for ioready. runtime_pollWait
+               // will check for timeout/cancel before waiting.
+               if(ioready)
+                       *gpp = READY;
                return nil;
        }
        old = *gpp;
+       // pass unblock reason onto blocked g
+       old->param = (void*)ioready;
        *gpp = nil;
        return old;
 }
@@ -291,14 +310,14 @@ deadlineimpl(int64 now, Eface arg, bool read, bool write)
                        runtime·throw("deadlineimpl: inconsistent read deadline");
                pd->rd = -1;
                pd->rt.fv = nil;
-               rg = netpollunblock(pd, 'r');
+               rg = netpollunblock(pd, 'r', false);
        }
        if(write) {
                if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
                        runtime·throw("deadlineimpl: inconsistent write deadline");
                pd->wd = -1;
                pd->wt.fv = nil;
-               wg = netpollunblock(pd, 'w');
+               wg = netpollunblock(pd, 'w', false);
        }
        runtime·unlock(pd);
        if(rg)