OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [fd_linux.go] - Blame information for rev 775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
                print("Epoll unexpected fd=", fd, "\n")
88
                return
89
        }
90
 
91
        // If syscall.EPOLLONESHOT is not set, the wait
92
        // is a repeating wait, so don't change it.
93
        if events&syscall.EPOLLONESHOT == 0 {
94
                return
95
        }
96
 
97
        // Disable the given bits.
98
        // If we're still waiting for other events, modify the fd
99
        // event in the kernel.  Otherwise, delete it.
100
        events &= ^uint32(bits)
101
        if int32(events)&^syscall.EPOLLONESHOT != 0 {
102
                p.ctlEvent.Fd = int32(fd)
103
                p.ctlEvent.Events = events
104
                if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil {
105
                        print("Epoll modify fd=", fd, ": ", err.Error(), "\n")
106
                }
107
                p.events[fd] = events
108
        } else {
109
                if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
110
                        print("Epoll delete fd=", fd, ": ", err.Error(), "\n")
111
                }
112
                delete(p.events, fd)
113
        }
114
}
115
 
116
func (p *pollster) DelFD(fd int, mode int) {
117
        // pollServer is locked.
118
 
119
        if mode == 'r' {
120
                p.StopWaiting(fd, readFlags)
121
        } else {
122
                p.StopWaiting(fd, writeFlags)
123
        }
124
 
125
        // Discard any queued up events.
126
        i := 0
127
        for i < len(p.waitEvents) {
128
                if fd == int(p.waitEvents[i].Fd) {
129
                        copy(p.waitEvents[i:], p.waitEvents[i+1:])
130
                        p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
131
                } else {
132
                        i++
133
                }
134
        }
135
}
136
 
137
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
138
        for len(p.waitEvents) == 0 {
139
                var msec int = -1
140
                if nsec > 0 {
141
                        msec = int((nsec + 1e6 - 1) / 1e6)
142
                }
143
 
144
                s.Unlock()
145
                n, err := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
146
                s.Lock()
147
 
148
                if err != nil {
149
                        if err == syscall.EAGAIN || err == syscall.EINTR {
150
                                continue
151
                        }
152
                        return -1, 0, os.NewSyscallError("epoll_wait", err)
153
                }
154
                if n == 0 {
155
                        return -1, 0, nil
156
                }
157
                p.waitEvents = p.waitEventBuf[0:n]
158
        }
159
 
160
        ev := &p.waitEvents[0]
161
        p.waitEvents = p.waitEvents[1:]
162
 
163
        fd = int(ev.Fd)
164
 
165
        if ev.Events&writeFlags != 0 {
166
                p.StopWaiting(fd, writeFlags)
167
                return fd, 'w', nil
168
        }
169
        if ev.Events&readFlags != 0 {
170
                p.StopWaiting(fd, readFlags)
171
                return fd, 'r', nil
172
        }
173
 
174
        // Other events are error conditions - wake whoever is waiting.
175
        events, _ := p.events[fd]
176
        if events&writeFlags != 0 {
177
                p.StopWaiting(fd, writeFlags)
178
                return fd, 'w', nil
179
        }
180
        p.StopWaiting(fd, readFlags)
181
        return fd, 'r', nil
182
}
183
 
184
func (p *pollster) Close() error {
185
        return os.NewSyscallError("close", syscall.Close(p.epfd))
186
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.