github.com/aloncn/graphics-go@v0.0.1/src/runtime/netpoll_kqueue.go (about) 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 // +build darwin dragonfly freebsd netbsd openbsd 6 7 package runtime 8 9 // Integrated network poller (kqueue-based implementation). 10 11 import "unsafe" 12 13 func kqueue() int32 14 15 //go:noescape 16 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 17 func closeonexec(fd int32) 18 19 var ( 20 kq int32 = -1 21 ) 22 23 func netpollinit() { 24 kq = kqueue() 25 if kq < 0 { 26 println("netpollinit: kqueue failed with", -kq) 27 throw("netpollinit: kqueue failed") 28 } 29 closeonexec(kq) 30 } 31 32 func netpollopen(fd uintptr, pd *pollDesc) int32 { 33 // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR) 34 // for the whole fd lifetime. The notifications are automatically unregistered 35 // when fd is closed. 36 var ev [2]keventt 37 *(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd 38 ev[0].filter = _EVFILT_READ 39 ev[0].flags = _EV_ADD | _EV_CLEAR 40 ev[0].fflags = 0 41 ev[0].data = 0 42 ev[0].udata = (*byte)(unsafe.Pointer(pd)) 43 ev[1] = ev[0] 44 ev[1].filter = _EVFILT_WRITE 45 n := kevent(kq, &ev[0], 2, nil, 0, nil) 46 if n < 0 { 47 return -n 48 } 49 return 0 50 } 51 52 func netpollclose(fd uintptr) int32 { 53 // Don't need to unregister because calling close() 54 // on fd will remove any kevents that reference the descriptor. 55 return 0 56 } 57 58 func netpollarm(pd *pollDesc, mode int) { 59 throw("unused") 60 } 61 62 // Polls for ready network connections. 63 // Returns list of goroutines that become runnable. 64 func netpoll(block bool) *g { 65 if kq == -1 { 66 return nil 67 } 68 var tp *timespec 69 var ts timespec 70 if !block { 71 tp = &ts 72 } 73 var events [64]keventt 74 retry: 75 n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp) 76 if n < 0 { 77 if n != -_EINTR { 78 println("runtime: kevent on fd", kq, "failed with", -n) 79 throw("kevent failed") 80 } 81 goto retry 82 } 83 var gp guintptr 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' 89 } 90 if ev.filter == _EVFILT_WRITE { 91 mode += 'w' 92 } 93 if mode != 0 { 94 netpollready(&gp, (*pollDesc)(unsafe.Pointer(ev.udata)), mode) 95 } 96 } 97 if block && gp == 0 { 98 goto retry 99 } 100 return gp.ptr() 101 }