diff options
author | Rutger Broekhoff | 2023-12-29 21:31:53 +0100 |
---|---|---|
committer | Rutger Broekhoff | 2023-12-29 21:31:53 +0100 |
commit | 404aeae4545d2426c089a5f8d5e82dae56f5212b (patch) | |
tree | 2d84e00af272b39fc04f3795ae06bc48970e57b5 /vendor/golang.org/x/sys/unix/epoll_zos.go | |
parent | 209d8b0187ed025dec9ac149ebcced3462877bff (diff) | |
download | gitolfs3-404aeae4545d2426c089a5f8d5e82dae56f5212b.tar.gz gitolfs3-404aeae4545d2426c089a5f8d5e82dae56f5212b.zip |
Make Nix builds work
Diffstat (limited to 'vendor/golang.org/x/sys/unix/epoll_zos.go')
-rw-r--r-- | vendor/golang.org/x/sys/unix/epoll_zos.go | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/unix/epoll_zos.go b/vendor/golang.org/x/sys/unix/epoll_zos.go new file mode 100644 index 0000000..7753fdd --- /dev/null +++ b/vendor/golang.org/x/sys/unix/epoll_zos.go | |||
@@ -0,0 +1,220 @@ | |||
1 | // Copyright 2020 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 | //go:build zos && s390x | ||
6 | |||
7 | package unix | ||
8 | |||
9 | import ( | ||
10 | "sync" | ||
11 | ) | ||
12 | |||
13 | // This file simulates epoll on z/OS using poll. | ||
14 | |||
15 | // Analogous to epoll_event on Linux. | ||
16 | // TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove? | ||
17 | type EpollEvent struct { | ||
18 | Events uint32 | ||
19 | Fd int32 | ||
20 | Pad int32 | ||
21 | } | ||
22 | |||
23 | const ( | ||
24 | EPOLLERR = 0x8 | ||
25 | EPOLLHUP = 0x10 | ||
26 | EPOLLIN = 0x1 | ||
27 | EPOLLMSG = 0x400 | ||
28 | EPOLLOUT = 0x4 | ||
29 | EPOLLPRI = 0x2 | ||
30 | EPOLLRDBAND = 0x80 | ||
31 | EPOLLRDNORM = 0x40 | ||
32 | EPOLLWRBAND = 0x200 | ||
33 | EPOLLWRNORM = 0x100 | ||
34 | EPOLL_CTL_ADD = 0x1 | ||
35 | EPOLL_CTL_DEL = 0x2 | ||
36 | EPOLL_CTL_MOD = 0x3 | ||
37 | // The following constants are part of the epoll API, but represent | ||
38 | // currently unsupported functionality on z/OS. | ||
39 | // EPOLL_CLOEXEC = 0x80000 | ||
40 | // EPOLLET = 0x80000000 | ||
41 | // EPOLLONESHOT = 0x40000000 | ||
42 | // EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis | ||
43 | // EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode | ||
44 | // EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability | ||
45 | ) | ||
46 | |||
47 | // TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL | ||
48 | // constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16). | ||
49 | |||
50 | // epToPollEvt converts epoll event field to poll equivalent. | ||
51 | // In epoll, Events is a 32-bit field, while poll uses 16 bits. | ||
52 | func epToPollEvt(events uint32) int16 { | ||
53 | var ep2p = map[uint32]int16{ | ||
54 | EPOLLIN: POLLIN, | ||
55 | EPOLLOUT: POLLOUT, | ||
56 | EPOLLHUP: POLLHUP, | ||
57 | EPOLLPRI: POLLPRI, | ||
58 | EPOLLERR: POLLERR, | ||
59 | } | ||
60 | |||
61 | var pollEvts int16 = 0 | ||
62 | for epEvt, pEvt := range ep2p { | ||
63 | if (events & epEvt) != 0 { | ||
64 | pollEvts |= pEvt | ||
65 | } | ||
66 | } | ||
67 | |||
68 | return pollEvts | ||
69 | } | ||
70 | |||
71 | // pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields. | ||
72 | func pToEpollEvt(revents int16) uint32 { | ||
73 | var p2ep = map[int16]uint32{ | ||
74 | POLLIN: EPOLLIN, | ||
75 | POLLOUT: EPOLLOUT, | ||
76 | POLLHUP: EPOLLHUP, | ||
77 | POLLPRI: EPOLLPRI, | ||
78 | POLLERR: EPOLLERR, | ||
79 | } | ||
80 | |||
81 | var epollEvts uint32 = 0 | ||
82 | for pEvt, epEvt := range p2ep { | ||
83 | if (revents & pEvt) != 0 { | ||
84 | epollEvts |= epEvt | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return epollEvts | ||
89 | } | ||
90 | |||
91 | // Per-process epoll implementation. | ||
92 | type epollImpl struct { | ||
93 | mu sync.Mutex | ||
94 | epfd2ep map[int]*eventPoll | ||
95 | nextEpfd int | ||
96 | } | ||
97 | |||
98 | // eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances. | ||
99 | // On Linux, this is an in-kernel data structure accessed through a fd. | ||
100 | type eventPoll struct { | ||
101 | mu sync.Mutex | ||
102 | fds map[int]*EpollEvent | ||
103 | } | ||
104 | |||
105 | // epoll impl for this process. | ||
106 | var impl epollImpl = epollImpl{ | ||
107 | epfd2ep: make(map[int]*eventPoll), | ||
108 | nextEpfd: 0, | ||
109 | } | ||
110 | |||
111 | func (e *epollImpl) epollcreate(size int) (epfd int, err error) { | ||
112 | e.mu.Lock() | ||
113 | defer e.mu.Unlock() | ||
114 | epfd = e.nextEpfd | ||
115 | e.nextEpfd++ | ||
116 | |||
117 | e.epfd2ep[epfd] = &eventPoll{ | ||
118 | fds: make(map[int]*EpollEvent), | ||
119 | } | ||
120 | return epfd, nil | ||
121 | } | ||
122 | |||
123 | func (e *epollImpl) epollcreate1(flag int) (fd int, err error) { | ||
124 | return e.epollcreate(4) | ||
125 | } | ||
126 | |||
127 | func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) { | ||
128 | e.mu.Lock() | ||
129 | defer e.mu.Unlock() | ||
130 | |||
131 | ep, ok := e.epfd2ep[epfd] | ||
132 | if !ok { | ||
133 | |||
134 | return EBADF | ||
135 | } | ||
136 | |||
137 | switch op { | ||
138 | case EPOLL_CTL_ADD: | ||
139 | // TODO(neeilan): When we make epfds and fds disjoint, detect epoll | ||
140 | // loops here (instances watching each other) and return ELOOP. | ||
141 | if _, ok := ep.fds[fd]; ok { | ||
142 | return EEXIST | ||
143 | } | ||
144 | ep.fds[fd] = event | ||
145 | case EPOLL_CTL_MOD: | ||
146 | if _, ok := ep.fds[fd]; !ok { | ||
147 | return ENOENT | ||
148 | } | ||
149 | ep.fds[fd] = event | ||
150 | case EPOLL_CTL_DEL: | ||
151 | if _, ok := ep.fds[fd]; !ok { | ||
152 | return ENOENT | ||
153 | } | ||
154 | delete(ep.fds, fd) | ||
155 | |||
156 | } | ||
157 | return nil | ||
158 | } | ||
159 | |||
160 | // Must be called while holding ep.mu | ||
161 | func (ep *eventPoll) getFds() []int { | ||
162 | fds := make([]int, len(ep.fds)) | ||
163 | for fd := range ep.fds { | ||
164 | fds = append(fds, fd) | ||
165 | } | ||
166 | return fds | ||
167 | } | ||
168 | |||
169 | func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) { | ||
170 | e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait | ||
171 | ep, ok := e.epfd2ep[epfd] | ||
172 | |||
173 | if !ok { | ||
174 | e.mu.Unlock() | ||
175 | return 0, EBADF | ||
176 | } | ||
177 | |||
178 | pollfds := make([]PollFd, 4) | ||
179 | for fd, epollevt := range ep.fds { | ||
180 | pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)}) | ||
181 | } | ||
182 | e.mu.Unlock() | ||
183 | |||
184 | n, err = Poll(pollfds, msec) | ||
185 | if err != nil { | ||
186 | return n, err | ||
187 | } | ||
188 | |||
189 | i := 0 | ||
190 | for _, pFd := range pollfds { | ||
191 | if pFd.Revents != 0 { | ||
192 | events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)} | ||
193 | i++ | ||
194 | } | ||
195 | |||
196 | if i == n { | ||
197 | break | ||
198 | } | ||
199 | } | ||
200 | |||
201 | return n, nil | ||
202 | } | ||
203 | |||
204 | func EpollCreate(size int) (fd int, err error) { | ||
205 | return impl.epollcreate(size) | ||
206 | } | ||
207 | |||
208 | func EpollCreate1(flag int) (fd int, err error) { | ||
209 | return impl.epollcreate1(flag) | ||
210 | } | ||
211 | |||
212 | func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { | ||
213 | return impl.epollctl(epfd, op, fd, event) | ||
214 | } | ||
215 | |||
216 | // Because EpollWait mutates events, the caller is expected to coordinate | ||
217 | // concurrent access if calling with the same epfd from multiple goroutines. | ||
218 | func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { | ||
219 | return impl.epollwait(epfd, events, msec) | ||
220 | } | ||