runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / netpoll_kqueue.go
blob1f68effbf9d459ccbb2b8b92344f425224f37792
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 //extern kqueue
14 func kqueue() int32
16 //go:noescape
17 //extern kevent
18 func kevent(kq int32, ch *keventt, nch uintptr, ev *keventt, nev uintptr, ts *timespec) int32
20 //extern __go_fcntl_uintptr
21 func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr)
23 func closeonexec(fd int32) {
24 fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC)
27 var (
28 kq int32 = -1
31 func netpollinit() {
32 kq = kqueue()
33 if kq < 0 {
34 println("netpollinit: kqueue failed with", errno())
35 throw("runtime: netpollinit failed")
37 closeonexec(kq)
40 func netpolldescriptor() uintptr {
41 return uintptr(kq)
44 func netpollopen(fd uintptr, pd *pollDesc) int32 {
45 // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
46 // for the whole fd lifetime. The notifications are automatically unregistered
47 // when fd is closed.
48 var ev [2]keventt
49 *(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
50 ev[0].filter = _EVFILT_READ
51 ev[0].flags = _EV_ADD | _EV_CLEAR
52 ev[0].fflags = 0
53 ev[0].data = 0
54 ev[0].udata = (*byte)(unsafe.Pointer(pd))
55 ev[1] = ev[0]
56 ev[1].filter = _EVFILT_WRITE
57 n := kevent(kq, &ev[0], 2, nil, 0, nil)
58 if n < 0 {
59 return int32(errno())
61 return 0
64 func netpollclose(fd uintptr) int32 {
65 // Don't need to unregister because calling close()
66 // on fd will remove any kevents that reference the descriptor.
67 return 0
70 func netpollarm(pd *pollDesc, mode int) {
71 throw("runtime: unused")
74 // Polls for ready network connections.
75 // Returns list of goroutines that become runnable.
76 func netpoll(block bool) *g {
77 if kq == -1 {
78 return nil
80 var tp *timespec
81 var ts timespec
82 if !block {
83 tp = &ts
85 var events [64]keventt
86 retry:
87 n := kevent(kq, nil, 0, &events[0], uintptr(len(events)), tp)
88 if n < 0 {
89 e := errno()
90 if e != _EINTR {
91 println("runtime: kevent on fd", kq, "failed with", e)
92 throw("runtime: netpoll failed")
94 goto retry
96 var gp guintptr
97 for i := 0; i < int(n); i++ {
98 ev := &events[i]
99 var mode int32
100 switch ev.filter {
101 case _EVFILT_READ:
102 mode += 'r'
104 // On some systems when the read end of a pipe
105 // is closed the write end will not get a
106 // _EVFILT_WRITE event, but will get a
107 // _EVFILT_READ event with EV_EOF set.
108 // Note that setting 'w' here just means that we
109 // will wake up a goroutine waiting to write;
110 // that goroutine will try the write again,
111 // and the appropriate thing will happen based
112 // on what that write returns (success, EPIPE, EAGAIN).
113 if ev.flags&_EV_EOF != 0 {
114 mode += 'w'
116 case _EVFILT_WRITE:
117 mode += 'w'
119 if mode != 0 {
120 netpollready(&gp, (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
123 if block && gp == 0 {
124 goto retry
126 return gp.ptr()