~john-koepi/ubuntu/trusty/golang/default

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-04-20 17:36:48 UTC
  • Revision ID: james.westby@ubuntu.com-20110420173648-ifergoxyrm832trd
Tags: upstream-2011.03.07.1
Import upstream version 2011.03.07.1

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
        events map[int]uint32
 
24
}
 
25
 
 
26
func newpollster() (p *pollster, err os.Error) {
 
27
        p = new(pollster)
 
28
        var e int
 
29
 
 
30
        // The arg to epoll_create is a hint to the kernel
 
31
        // about the number of FDs we will care about.
 
32
        // We don't know.
 
33
        if p.epfd, e = syscall.EpollCreate(16); e != 0 {
 
34
                return nil, os.NewSyscallError("epoll_create", e)
 
35
        }
 
36
        p.events = make(map[int]uint32)
 
37
        return p, nil
 
38
}
 
39
 
 
40
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
 
41
        var ev syscall.EpollEvent
 
42
        var already bool
 
43
        ev.Fd = int32(fd)
 
44
        ev.Events, already = p.events[fd]
 
45
        if !repeat {
 
46
                ev.Events |= syscall.EPOLLONESHOT
 
47
        }
 
48
        if mode == 'r' {
 
49
                ev.Events |= readFlags
 
50
        } else {
 
51
                ev.Events |= writeFlags
 
52
        }
 
53
 
 
54
        var op int
 
55
        if already {
 
56
                op = syscall.EPOLL_CTL_MOD
 
57
        } else {
 
58
                op = syscall.EPOLL_CTL_ADD
 
59
        }
 
60
        if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 {
 
61
                return os.NewSyscallError("epoll_ctl", e)
 
62
        }
 
63
        p.events[fd] = ev.Events
 
64
        return nil
 
65
}
 
66
 
 
67
func (p *pollster) StopWaiting(fd int, bits uint) {
 
68
        events, already := p.events[fd]
 
69
        if !already {
 
70
                print("Epoll unexpected fd=", fd, "\n")
 
71
                return
 
72
        }
 
73
 
 
74
        // If syscall.EPOLLONESHOT is not set, the wait
 
75
        // is a repeating wait, so don't change it.
 
76
        if events&syscall.EPOLLONESHOT == 0 {
 
77
                return
 
78
        }
 
79
 
 
80
        // Disable the given bits.
 
81
        // If we're still waiting for other events, modify the fd
 
82
        // event in the kernel.  Otherwise, delete it.
 
83
        events &= ^uint32(bits)
 
84
        if int32(events)&^syscall.EPOLLONESHOT != 0 {
 
85
                var ev syscall.EpollEvent
 
86
                ev.Fd = int32(fd)
 
87
                ev.Events = events
 
88
                if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
 
89
                        print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
 
90
                }
 
91
                p.events[fd] = events
 
92
        } else {
 
93
                if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
 
94
                        print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
 
95
                }
 
96
                p.events[fd] = 0, false
 
97
        }
 
98
}
 
99
 
 
100
func (p *pollster) DelFD(fd int, mode int) {
 
101
        if mode == 'r' {
 
102
                p.StopWaiting(fd, readFlags)
 
103
        } else {
 
104
                p.StopWaiting(fd, writeFlags)
 
105
        }
 
106
}
 
107
 
 
108
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
 
109
        // Get an event.
 
110
        var evarray [1]syscall.EpollEvent
 
111
        ev := &evarray[0]
 
112
        var msec int = -1
 
113
        if nsec > 0 {
 
114
                msec = int((nsec + 1e6 - 1) / 1e6)
 
115
        }
 
116
        n, e := syscall.EpollWait(p.epfd, evarray[0:], msec)
 
117
        for e == syscall.EAGAIN || e == syscall.EINTR {
 
118
                n, e = syscall.EpollWait(p.epfd, evarray[0:], msec)
 
119
        }
 
120
        if e != 0 {
 
121
                return -1, 0, os.NewSyscallError("epoll_wait", e)
 
122
        }
 
123
        if n == 0 {
 
124
                return -1, 0, nil
 
125
        }
 
126
        fd = int(ev.Fd)
 
127
 
 
128
        if ev.Events&writeFlags != 0 {
 
129
                p.StopWaiting(fd, writeFlags)
 
130
                return fd, 'w', nil
 
131
        }
 
132
        if ev.Events&readFlags != 0 {
 
133
                p.StopWaiting(fd, readFlags)
 
134
                return fd, 'r', nil
 
135
        }
 
136
 
 
137
        // Other events are error conditions - wake whoever is waiting.
 
138
        events, _ := p.events[fd]
 
139
        if events&writeFlags != 0 {
 
140
                p.StopWaiting(fd, writeFlags)
 
141
                return fd, 'w', nil
 
142
        }
 
143
        p.StopWaiting(fd, readFlags)
 
144
        return fd, 'r', nil
 
145
}
 
146
 
 
147
func (p *pollster) Close() os.Error {
 
148
        return os.NewSyscallError("close", syscall.Close(p.epfd))
 
149
}