1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <fio.h>
include <fset.h>
include <config.h>
include <syserr.h>
include <poll.h>
.help poll
.nf ___________________________________________________________________________
POLL -- FIO descriptor polling interface. See <poll.h> for a definition of
the interface data structures and flags, this file is required to be included
by source files using this interface.
fds = poll_open () # open a poll descriptor set
npolls = poll (fds, nfds, timeout) # poll the set
poll_close (fds) # free the poll descriptor set
poll_zero (fds) # zero the poll array
poll_set (fds, fd, type) # set fd to poll for type
poll_clear (fds, fd, type) # unset type on fd poll
y/n = poll_test (fds, fd, type) # test fd for type event
N = poll_get_nfds (fds) # get size of descriptor set
The polling interface provides the same functionality as the unix function
of the same name with a few implementation differences. The poll_open()
procedure is used to allocate a dynamic structure containing the descriptors
to be polled, poll_close() is used when done to free that structure.
The poll_zero(), poll_set(), and poll_clear() utility functions are
used to manipulate the descriptor set by zeroing the entire set, or adding or
removing a descriptor check for the specified polling type. Polling types
include POLLIN (fd is readable), POLLOUT (fd is writeable & won't block), or
POLLPRI (priority info at fd). The poll_test() function can be used to test
for these types folling the return of poll(). Additionally, a descriptor may
be checked for POLLERR (fd has error condition), POLLHUP (fd has been hung up
on), POLLNVAL (invalid pollfd entry). Descriptors may be checked for more
than one testable event.
Once the descriptor set has been created, the poll() function can be
called to check for activity on the set. A negative timeout value will cause
the function to block indefinitely, otherwise it represents a wait time given
in milliseconds. The poll() function will return a negative number if an
error is encountered, zero if the call times out and no file descriptors have
been selected, or a positive number indicating the number of descriptors
which can be serviced without blocking.
.endhelp ______________________________________________________________________
# POLL_OPEN -- Open a poll descriptor set.
pointer procedure poll_open ()
pointer fds
begin
iferr (call calloc (fds, LEN_FPOLL, TY_STRUCT))
call syserr (SYS_MFULL)
return (fds)
end
# POLL -- Poll the descriptor set.
int procedure poll (fds, nfds, timeout)
pointer fds
int nfds
int timeout
int pfds[LEN_FPOLL]
int i, j, npoll, status
include <fio.com>
begin
# Transform the descriptor set to a linear array.
j = 0
for (i=1; j < nfds; i=i+3) {
pfds[i ] = FCHAN(fiodes[POLL_FD(fds,j)])
pfds[i+1] = POLL_EVENTS(fds,j)
pfds[i+2] = POLL_REVENTS(fds,j)
j = j + 1
}
# Call the kernel routine to poll on the descriptor set.
call zfpoll (pfds, nfds, timeout, npoll, status)
if (status == ERR)
return (ERR)
j = 0
for (i=3; j < nfds; i=i+3) {
POLL_REVENTS(fds,j) = pfds[i]
j = j + 1
}
return (npoll)
end
# POLL_CLOSE -- Close and free a poll descriptor set.
procedure poll_close (fds)
pointer fds #i descriptor set pointer
begin
call mfree (fds, TY_STRUCT)
end
# POLL_ZERO -- Zero the descriptor set.
procedure poll_zero (fds)
pointer fds #i descriptor set pointer
begin
call aclri (Memi[fds], LEN_FPOLL)
end
# POLL_SET -- Add a descriptor to the set, and/or modify the event type.
# The type may be a bitwise or of testable events.
procedure poll_set (fds, fd, type)
pointer fds #i descriptor set pointer
int fd #i file descriptor
int type #i event type
int i, top
int ori()
begin
top = POLL_NFD(fds)
if (top > MAX_POLL_FD)
call eprintf ("File descriptor set overflow.\n")
for (i=0; i < top; i=i+1) {
# Search for requested descriptor and OR the type on the event mask.
if (fd == POLL_FD(fds,i)) {
POLL_EVENTS(fds,i) = ori (POLL_EVENTS(fds,i), type)
return
}
}
# Descriptor not found, add it to the set at the top
POLL_FD(fds,top) = fd
POLL_EVENTS(fds,top) = ori (POLL_EVENTS(fds,top), type)
POLL_NFD(fds) = top + 1
end
# POLL_GET_NFDS -- Get the number of descriptors in the set.
int procedure poll_get_nfds (fds)
pointer fds #i descriptor set pointer
begin
return (POLL_NFD(fds))
end
# POLL_CLEAR -- Remove a descriptor or event type from the set. The type
# may be a bitwise or of testable events. If the event mask becomes NULL
# the descriptor is removed entirely from the set.
procedure poll_clear (fds, fd, type)
pointer fds #i descriptor set pointer
int fd #i file descriptor
int type #i event type
int i, j, top
int noti(), andi()
begin
top = POLL_NFD(fds)
for (i=0; i < top; i=i+1) {
# Search for requested descriptor.
if (fd == POLL_FD(fds,i)) {
POLL_EVENTS(fds,i) = andi (noti(type), POLL_EVENTS(fds,i))
# If there are no events, remove the descriptor from the set
# by deleting it from the array and shifting the remainder.
if (POLL_EVENTS(fds,i) == 0) {
for (j=i+1; i < top; j=j+1) {
POLL_FD(fds,i) = POLL_FD(fds,j)
POLL_EVENTS(fds,i) = POLL_EVENTS(fds,j)
i = i + 1
}
POLL_NFD(fds) = top - 1
break
}
}
}
end
# POLL_TEST -- Test the descriptor for the given event type.
int procedure poll_test (fds, fd, type)
pointer fds #i descriptor set pointer
int fd #i file descriptor
int type #i event type
int i, top
int andi()
begin
top = POLL_NFD(fds)
for (i=0; i < top; i=i+1) {
# Search for requested descriptor.
if (fd == POLL_FD(fds,i)) {
# OR the type on the event mask.
if (andi (POLL_REVENTS(fds,i), type) > 0)
return (YES)
else
return (NO)
}
}
return (NO)
end
# POLL_PRINT -- Print the descriptor set (debug utility).
procedure poll_print (fds)
pointer fds #i descriptor set pointer
int i, top
begin
top = POLL_NFD(fds)
for (i=0; i < top; i=i+1) {
call eprintf ("%2d: fd=%3d events=%6d revents=%6d\n")
call pargi(i)
call pargi(POLL_FD(fds,i))
call pargi(POLL_EVENTS(fds,i))
call pargi(POLL_REVENTS(fds,i))
}
end
|