1
// Copyright 2009 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.
5
// +build freebsd netbsd openbsd
7
// Waiting for FDs via kqueue/kevent.
16
type pollster struct {
18
eventbuf [10]syscall.Kevent_t
19
events []syscall.Kevent_t
21
// An event buffer for AddFD/DelFD.
22
// Must hold pollServer lock.
23
kbuf [1]syscall.Kevent_t
26
func newpollster() (p *pollster, err error) {
28
if p.kq, err = syscall.Kqueue(); err != nil {
29
return nil, os.NewSyscallError("kqueue", err)
31
syscall.CloseOnExec(p.kq)
32
p.events = p.eventbuf[0:0]
36
// First return value is whether the pollServer should be woken up.
37
// This version always returns false.
38
func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
39
// pollServer is locked.
43
kmode = syscall.EVFILT_READ
45
kmode = syscall.EVFILT_WRITE
48
// EV_ADD - add event to kqueue list
49
// EV_ONESHOT - delete the event the first time it triggers
50
flags := syscall.EV_ADD
52
flags |= syscall.EV_ONESHOT
54
syscall.SetKevent(ev, fd, kmode, flags)
56
n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
58
return false, os.NewSyscallError("kevent", err)
60
if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
61
return false, os.NewSyscallError("kqueue phase error", err)
64
return false, syscall.Errno(int(ev.Data))
69
// Return value is whether the pollServer should be woken up.
70
// This version always returns false.
71
func (p *pollster) DelFD(fd int, mode int) bool {
72
// pollServer is locked.
76
kmode = syscall.EVFILT_READ
78
kmode = syscall.EVFILT_WRITE
81
// EV_DELETE - delete event from kqueue list
82
syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
83
syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
87
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
88
var t *syscall.Timespec
89
for len(p.events) == 0 {
92
t = new(syscall.Timespec)
94
*t = syscall.NsecToTimespec(nsec)
98
n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
102
if err == syscall.EINTR {
105
return -1, 0, os.NewSyscallError("kevent", err)
110
p.events = p.eventbuf[:n]
113
p.events = p.events[1:]
115
if ev.Filter == syscall.EVFILT_READ {
123
func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }