~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/net/fd_linux.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
}