2015-09-24 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libgo / go / runtime / netpoll_kqueue.go
blobd6d55b97b8d1b7917beeb0d020a9b72d5b6aa58c
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.
5 // +build darwin dragonfly freebsd netbsd openbsd
7 package runtime
9 // Integrated network poller (kqueue-based implementation).
11 import "unsafe"
13 func kqueue() int32
15 //go:noescape
16 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
17 func closeonexec(fd int32)
19 var (
20 kq int32 = -1
21 netpolllasterr int32
24 func netpollinit() {
25 kq = kqueue()
26 if kq < 0 {
27 println("netpollinit: kqueue failed with", -kq)
28 gothrow("netpollinit: kqueue failed")
30 closeonexec(kq)
33 func netpollopen(fd uintptr, pd *pollDesc) int32 {
34 // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
35 // for the whole fd lifetime. The notifications are automatically unregistered
36 // when fd is closed.
37 var ev [2]keventt
38 *(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
39 ev[0].filter = _EVFILT_READ
40 ev[0].flags = _EV_ADD | _EV_CLEAR
41 ev[0].fflags = 0
42 ev[0].data = 0
43 ev[0].udata = (*byte)(unsafe.Pointer(pd))
44 ev[1] = ev[0]
45 ev[1].filter = _EVFILT_WRITE
46 n := kevent(kq, &ev[0], 2, nil, 0, nil)
47 if n < 0 {
48 return -n
50 return 0
53 func netpollclose(fd uintptr) int32 {
54 // Don't need to unregister because calling close()
55 // on fd will remove any kevents that reference the descriptor.
56 return 0
59 func netpollarm(pd *pollDesc, mode int) {
60 gothrow("unused")
63 // Polls for ready network connections.
64 // Returns list of goroutines that become runnable.
65 func netpoll(block bool) (gp *g) {
66 if kq == -1 {
67 return
69 var tp *timespec
70 var ts timespec
71 if !block {
72 tp = &ts
74 var events [64]keventt
75 retry:
76 n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
77 if n < 0 {
78 if n != -_EINTR && n != netpolllasterr {
79 netpolllasterr = n
80 println("runtime: kevent on fd", kq, "failed with", -n)
82 goto retry
84 for i := 0; i < int(n); i++ {
85 ev := &events[i]
86 var mode int32
87 if ev.filter == _EVFILT_READ {
88 mode += 'r'
90 if ev.filter == _EVFILT_WRITE {
91 mode += 'w'
93 if mode != 0 {
94 netpollready((**g)(noescape(unsafe.Pointer(&gp))), (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
97 if block && gp == nil {
98 goto retry
100 return gp