LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Waiting for FDs via kqueue/kevent. | 5 // Waiting for FDs via kqueue/kevent. |
6 | 6 |
7 package net | 7 package net |
8 | 8 |
9 import ( | 9 import ( |
10 "errors" | 10 "errors" |
11 "os" | 11 "os" |
12 "syscall" | 12 "syscall" |
13 ) | 13 ) |
14 | 14 |
15 type pollster struct { | 15 type pollster struct { |
16 kq int | 16 kq int |
17 eventbuf [10]syscall.Kevent_t | 17 eventbuf [10]syscall.Kevent_t |
18 events []syscall.Kevent_t | 18 events []syscall.Kevent_t |
19 | 19 |
20 // An event buffer for AddFD/DelFD. | 20 // An event buffer for AddFD/DelFD. |
21 // Must hold pollServer lock. | 21 // Must hold pollServer lock. |
22 kbuf [1]syscall.Kevent_t | 22 kbuf [1]syscall.Kevent_t |
23 } | 23 } |
24 | 24 |
25 func newpollster() (p *pollster, err error) { | 25 func newpollster() (p *pollster, err error) { |
26 p = new(pollster) | 26 p = new(pollster) |
27 » var e int | 27 » if p.kq, err = syscall.Kqueue(); err != nil { |
28 » if p.kq, e = syscall.Kqueue(); e != 0 { | 28 » » return nil, os.NewSyscallError("kqueue", err) |
29 » » return nil, os.NewSyscallError("kqueue", e) | |
30 } | 29 } |
31 p.events = p.eventbuf[0:0] | 30 p.events = p.eventbuf[0:0] |
32 return p, nil | 31 return p, nil |
33 } | 32 } |
34 | 33 |
35 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { | 34 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { |
36 // pollServer is locked. | 35 // pollServer is locked. |
37 | 36 |
38 var kmode int | 37 var kmode int |
39 if mode == 'r' { | 38 if mode == 'r' { |
40 kmode = syscall.EVFILT_READ | 39 kmode = syscall.EVFILT_READ |
41 } else { | 40 } else { |
42 kmode = syscall.EVFILT_WRITE | 41 kmode = syscall.EVFILT_WRITE |
43 } | 42 } |
44 ev := &p.kbuf[0] | 43 ev := &p.kbuf[0] |
45 // EV_ADD - add event to kqueue list | 44 // EV_ADD - add event to kqueue list |
46 // EV_RECEIPT - generate fake EV_ERROR as result of add, | 45 // EV_RECEIPT - generate fake EV_ERROR as result of add, |
47 // rather than waiting for real event | 46 // rather than waiting for real event |
48 // EV_ONESHOT - delete the event the first time it triggers | 47 // EV_ONESHOT - delete the event the first time it triggers |
49 flags := syscall.EV_ADD | syscall.EV_RECEIPT | 48 flags := syscall.EV_ADD | syscall.EV_RECEIPT |
50 if !repeat { | 49 if !repeat { |
51 flags |= syscall.EV_ONESHOT | 50 flags |= syscall.EV_ONESHOT |
52 } | 51 } |
53 syscall.SetKevent(ev, fd, kmode, flags) | 52 syscall.SetKevent(ev, fd, kmode, flags) |
54 | 53 |
55 » n, e := syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil) | 54 » n, err := syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil) |
56 » if e != 0 { | 55 » if err != nil { |
57 » » return false, os.NewSyscallError("kevent", e) | 56 » » return false, os.NewSyscallError("kevent", err) |
58 } | 57 } |
59 if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd ||
int(ev.Filter) != kmode { | 58 if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd ||
int(ev.Filter) != kmode { |
60 return false, errors.New("kqueue phase error") | 59 return false, errors.New("kqueue phase error") |
61 } | 60 } |
62 if ev.Data != 0 { | 61 if ev.Data != 0 { |
63 » » return false, os.Errno(int(ev.Data)) | 62 » » return false, syscall.Errno(ev.Data) |
64 } | 63 } |
65 return false, nil | 64 return false, nil |
66 } | 65 } |
67 | 66 |
68 func (p *pollster) DelFD(fd int, mode int) { | 67 func (p *pollster) DelFD(fd int, mode int) { |
69 // pollServer is locked. | 68 // pollServer is locked. |
70 | 69 |
71 var kmode int | 70 var kmode int |
72 if mode == 'r' { | 71 if mode == 'r' { |
73 kmode = syscall.EVFILT_READ | 72 kmode = syscall.EVFILT_READ |
(...skipping 15 matching lines...) Expand all Loading... |
89 if t == nil { | 88 if t == nil { |
90 t = new(syscall.Timespec) | 89 t = new(syscall.Timespec) |
91 } | 90 } |
92 *t = syscall.NsecToTimespec(nsec) | 91 *t = syscall.NsecToTimespec(nsec) |
93 } | 92 } |
94 | 93 |
95 s.Unlock() | 94 s.Unlock() |
96 nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[0:], t) | 95 nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[0:], t) |
97 s.Lock() | 96 s.Lock() |
98 | 97 |
99 » » if e != 0 { | 98 » » if e != nil { |
100 if e == syscall.EINTR { | 99 if e == syscall.EINTR { |
101 continue | 100 continue |
102 } | 101 } |
103 » » » return -1, 0, os.NewSyscallError("kevent", e) | 102 » » » return -1, 0, os.NewSyscallError("kevent", nil) |
104 } | 103 } |
105 if nn == 0 { | 104 if nn == 0 { |
106 return -1, 0, nil | 105 return -1, 0, nil |
107 } | 106 } |
108 p.events = p.eventbuf[0:nn] | 107 p.events = p.eventbuf[0:nn] |
109 } | 108 } |
110 ev := &p.events[0] | 109 ev := &p.events[0] |
111 p.events = p.events[1:] | 110 p.events = p.events[1:] |
112 fd = int(ev.Ident) | 111 fd = int(ev.Ident) |
113 if ev.Filter == syscall.EVFILT_READ { | 112 if ev.Filter == syscall.EVFILT_READ { |
114 mode = 'r' | 113 mode = 'r' |
115 } else { | 114 } else { |
116 mode = 'w' | 115 mode = 'w' |
117 } | 116 } |
118 return fd, mode, nil | 117 return fd, mode, nil |
119 } | 118 } |
120 | 119 |
121 func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Cl
ose(p.kq)) } | 120 func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Cl
ose(p.kq)) } |
LEFT | RIGHT |