]> Cypherpunks.ru repositories - gostls13.git/blob - src/internal/poll/fd_poll_runtime.go
0a2e76d73f224197330ed50b5eabd08476243555
[gostls13.git] / src / internal / poll / fd_poll_runtime.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build unix || windows
6
7 package poll
8
9 import (
10         "errors"
11         "sync"
12         "syscall"
13         "time"
14         _ "unsafe" // for go:linkname
15 )
16
17 // runtimeNano returns the current value of the runtime clock in nanoseconds.
18 //
19 //go:linkname runtimeNano runtime.nanotime
20 func runtimeNano() int64
21
22 func runtime_pollServerInit()
23 func runtime_pollOpen(fd uintptr) (uintptr, int)
24 func runtime_pollClose(ctx uintptr)
25 func runtime_pollWait(ctx uintptr, mode int) int
26 func runtime_pollWaitCanceled(ctx uintptr, mode int)
27 func runtime_pollReset(ctx uintptr, mode int) int
28 func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
29 func runtime_pollUnblock(ctx uintptr)
30 func runtime_isPollServerDescriptor(fd uintptr) bool
31
32 type pollDesc struct {
33         runtimeCtx uintptr
34 }
35
36 var serverInit sync.Once
37
38 func (pd *pollDesc) init(fd *FD) error {
39         serverInit.Do(runtime_pollServerInit)
40         ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
41         if errno != 0 {
42                 return errnoErr(syscall.Errno(errno))
43         }
44         pd.runtimeCtx = ctx
45         return nil
46 }
47
48 func (pd *pollDesc) close() {
49         if pd.runtimeCtx == 0 {
50                 return
51         }
52         runtime_pollClose(pd.runtimeCtx)
53         pd.runtimeCtx = 0
54 }
55
56 // Evict evicts fd from the pending list, unblocking any I/O running on fd.
57 func (pd *pollDesc) evict() {
58         if pd.runtimeCtx == 0 {
59                 return
60         }
61         runtime_pollUnblock(pd.runtimeCtx)
62 }
63
64 func (pd *pollDesc) prepare(mode int, isFile bool) error {
65         if pd.runtimeCtx == 0 {
66                 return nil
67         }
68         res := runtime_pollReset(pd.runtimeCtx, mode)
69         return convertErr(res, isFile)
70 }
71
72 func (pd *pollDesc) prepareRead(isFile bool) error {
73         return pd.prepare('r', isFile)
74 }
75
76 func (pd *pollDesc) prepareWrite(isFile bool) error {
77         return pd.prepare('w', isFile)
78 }
79
80 func (pd *pollDesc) wait(mode int, isFile bool) error {
81         if pd.runtimeCtx == 0 {
82                 return errors.New("waiting for unsupported file type")
83         }
84         res := runtime_pollWait(pd.runtimeCtx, mode)
85         return convertErr(res, isFile)
86 }
87
88 func (pd *pollDesc) waitRead(isFile bool) error {
89         return pd.wait('r', isFile)
90 }
91
92 func (pd *pollDesc) waitWrite(isFile bool) error {
93         return pd.wait('w', isFile)
94 }
95
96 func (pd *pollDesc) waitCanceled(mode int) {
97         if pd.runtimeCtx == 0 {
98                 return
99         }
100         runtime_pollWaitCanceled(pd.runtimeCtx, mode)
101 }
102
103 func (pd *pollDesc) pollable() bool {
104         return pd.runtimeCtx != 0
105 }
106
107 // Error values returned by runtime_pollReset and runtime_pollWait.
108 // These must match the values in runtime/netpoll.go.
109 const (
110         pollNoError        = 0
111         pollErrClosing     = 1
112         pollErrTimeout     = 2
113         pollErrNotPollable = 3
114 )
115
116 func convertErr(res int, isFile bool) error {
117         switch res {
118         case pollNoError:
119                 return nil
120         case pollErrClosing:
121                 return errClosing(isFile)
122         case pollErrTimeout:
123                 return ErrDeadlineExceeded
124         case pollErrNotPollable:
125                 return ErrNotPollable
126         }
127         println("unreachable: ", res)
128         panic("unreachable")
129 }
130
131 // SetDeadline sets the read and write deadlines associated with fd.
132 func (fd *FD) SetDeadline(t time.Time) error {
133         return setDeadlineImpl(fd, t, 'r'+'w')
134 }
135
136 // SetReadDeadline sets the read deadline associated with fd.
137 func (fd *FD) SetReadDeadline(t time.Time) error {
138         return setDeadlineImpl(fd, t, 'r')
139 }
140
141 // SetWriteDeadline sets the write deadline associated with fd.
142 func (fd *FD) SetWriteDeadline(t time.Time) error {
143         return setDeadlineImpl(fd, t, 'w')
144 }
145
146 func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
147         var d int64
148         if !t.IsZero() {
149                 d = int64(time.Until(t))
150                 if d == 0 {
151                         d = -1 // don't confuse deadline right now with no deadline
152                 }
153         }
154         if err := fd.incref(); err != nil {
155                 return err
156         }
157         defer fd.decref()
158         if fd.pd.runtimeCtx == 0 {
159                 return ErrNoDeadline
160         }
161         runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
162         return nil
163 }
164
165 // IsPollDescriptor reports whether fd is the descriptor being used by the poller.
166 // This is only used for testing.
167 func IsPollDescriptor(fd uintptr) bool {
168         return runtime_isPollServerDescriptor(fd)
169 }