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