Source file src/pkg/net/fd_linux.go
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. 4 5 // Waiting for FDs via epoll(7). 6 7 package net 8 9 import ( 10 "os" 11 "syscall" 12 ) 13 14 const ( 15 readFlags = syscall.EPOLLIN | syscall.EPOLLRDHUP 16 writeFlags = syscall.EPOLLOUT 17 ) 18 19 type pollster struct { 20 epfd int 21 22 // Events we're already waiting for 23 // Must hold pollServer lock 24 events map[int]uint32 25 26 // An event buffer for EpollWait. 27 // Used without a lock, may only be used by WaitFD. 28 waitEventBuf [10]syscall.EpollEvent 29 waitEvents []syscall.EpollEvent 30 31 // An event buffer for EpollCtl, to avoid a malloc. 32 // Must hold pollServer lock. 33 ctlEvent syscall.EpollEvent 34 } 35 36 func newpollster() (p *pollster, err error) { 37 p = new(pollster) 38 if p.epfd, err = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil { 39 if err != syscall.ENOSYS { 40 return nil, os.NewSyscallError("epoll_create1", err) 41 } 42 // The arg to epoll_create is a hint to the kernel 43 // about the number of FDs we will care about. 44 // We don't know, and since 2.6.8 the kernel ignores it anyhow. 45 if p.epfd, err = syscall.EpollCreate(16); err != nil { 46 return nil, os.NewSyscallError("epoll_create", err) 47 } 48 syscall.CloseOnExec(p.epfd) 49 } 50 p.events = make(map[int]uint32) 51 return p, nil 52 } 53 54 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { 55 // pollServer is locked. 56 57 var already bool 58 p.ctlEvent.Fd = int32(fd) 59 p.ctlEvent.Events, already = p.events[fd] 60 if !repeat { 61 p.ctlEvent.Events |= syscall.EPOLLONESHOT 62 } 63 if mode == 'r' { 64 p.ctlEvent.Events |= readFlags 65 } else { 66 p.ctlEvent.Events |= writeFlags 67 } 68 69 var op int 70 if already { 71 op = syscall.EPOLL_CTL_MOD 72 } else { 73 op = syscall.EPOLL_CTL_ADD 74 } 75 if err := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); err != nil { 76 return false, os.NewSyscallError("epoll_ctl", err) 77 } 78 p.events[fd] = p.ctlEvent.Events 79 return false, nil 80 } 81 82 func (p *pollster) StopWaiting(fd int, bits uint) { 83 // pollServer is locked. 84 85 events, already := p.events[fd] 86 if !already { 87 // The fd returned by the kernel may have been 88 // cancelled already; return silently. 89 return 90 } 91 92 // If syscall.EPOLLONESHOT is not set, the wait 93 // is a repeating wait, so don't change it. 94 if events&syscall.EPOLLONESHOT == 0 { 95 return 96 } 97 98 // Disable the given bits. 99 // If we're still waiting for other events, modify the fd 100 // event in the kernel. Otherwise, delete it. 101 events &= ^uint32(bits) 102 if int32(events)&^syscall.EPOLLONESHOT != 0 { 103 p.ctlEvent.Fd = int32(fd) 104 p.ctlEvent.Events = events 105 if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil { 106 print("Epoll modify fd=", fd, ": ", err.Error(), "\n") 107 } 108 p.events[fd] = events 109 } else { 110 if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil { 111 print("Epoll delete fd=", fd, ": ", err.Error(), "\n") 112 } 113 delete(p.events, fd) 114 } 115 } 116 117 func (p *pollster) DelFD(fd int, mode int) { 118 // pollServer is locked. 119 120 if mode == 'r' { 121 p.StopWaiting(fd, readFlags) 122 } else { 123 p.StopWaiting(fd, writeFlags) 124 } 125 126 // Discard any queued up events. 127 i := 0 128 for i < len(p.waitEvents) { 129 if fd == int(p.waitEvents[i].Fd) { 130 copy(p.waitEvents[i:], p.waitEvents[i+1:]) 131 p.waitEvents = p.waitEvents[:len(p.waitEvents)-1] 132 } else { 133 i++ 134 } 135 } 136 } 137 138 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) { 139 for len(p.waitEvents) == 0 { 140 var msec int = -1 141 if nsec > 0 { 142 msec = int((nsec + 1e6 - 1) / 1e6) 143 } 144 145 s.Unlock() 146 n, err := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec) 147 s.Lock() 148 149 if err != nil { 150 if err == syscall.EAGAIN || err == syscall.EINTR { 151 continue 152 } 153 return -1, 0, os.NewSyscallError("epoll_wait", err) 154 } 155 if n == 0 { 156 return -1, 0, nil 157 } 158 p.waitEvents = p.waitEventBuf[0:n] 159 } 160 161 ev := &p.waitEvents[0] 162 p.waitEvents = p.waitEvents[1:] 163 164 fd = int(ev.Fd) 165 166 if ev.Events&writeFlags != 0 { 167 p.StopWaiting(fd, writeFlags) 168 return fd, 'w', nil 169 } 170 if ev.Events&readFlags != 0 { 171 p.StopWaiting(fd, readFlags) 172 return fd, 'r', nil 173 } 174 175 // Other events are error conditions - wake whoever is waiting. 176 events, _ := p.events[fd] 177 if events&writeFlags != 0 { 178 p.StopWaiting(fd, writeFlags) 179 return fd, 'w', nil 180 } 181 p.StopWaiting(fd, readFlags) 182 return fd, 'r', nil 183 } 184 185 func (p *pollster) Close() error { 186 return os.NewSyscallError("close", syscall.Close(p.epfd)) 187 }