Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/sfio/sfpoll.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#include "sfhdr.h"
23
24
/* Poll a set of streams to see if any is available for I/O.
25
** Ready streams are moved to front of array but retain the
26
** same relative order.
27
**
28
** Written by Kiem-Phong Vo.
29
*/
30
31
#if __STD_C
32
int sfpoll(Sfio_t** fa, reg int n, int tm)
33
#else
34
int sfpoll(fa, n, tm)
35
Sfio_t** fa; /* array of streams to poll */
36
reg int n; /* number of streams in array */
37
int tm; /* time in millisecs for select/poll */
38
#endif
39
{
40
reg int r, c, m, np, eintr;
41
reg Sfio_t* f;
42
reg int *status, *check;
43
44
if(n <= 0 || !fa)
45
return -1;
46
47
if(!(status = (int*)malloc(2*n*sizeof(int))) )
48
return -1;
49
check = status+n; /* streams that need polling */
50
51
/* a SF_READ stream is ready if there is buffered read data */
52
#define RDREADY(f) (((f->mode&SF_READ) && f->next < f->endb) || \
53
((f->mode&SF_WRITE) && f->proc && f->proc->ndata > 0) )
54
55
/* a SF_WRITE stream is ready if there is no write data */
56
#define WRREADY(f) (!(f->mode&SF_WRITE) || f->next == f->data)
57
58
#define HASAUXFD(f) (f->proc && f->proc->file >= 0 && f->proc->file != f->file)
59
60
for(r = c = eintr = 0; r < n; ++r) /* compute streams that must be checked */
61
{ f = fa[r];
62
status[r] = 0;
63
64
/* terminate poll on interrupt? */
65
if(f->flags&SF_IOINTR)
66
eintr++;
67
/* check accessibility */
68
m = f->mode&SF_RDWR;
69
if((int)f->mode != m && _sfmode(f,m,0) < 0)
70
continue;
71
72
if((f->flags&SF_READ) && RDREADY(f))
73
status[r] |= SF_READ;
74
75
if((f->flags&SF_WRITE) && WRREADY(f))
76
status[r] |= SF_WRITE;
77
78
if((f->flags&SF_RDWR) == status[r])
79
continue;
80
81
/* has discipline, ask its opinion */
82
if(f->disc && f->disc->exceptf)
83
{ if((m = (*f->disc->exceptf)(f,SF_DPOLL,&tm,f->disc)) < 0)
84
continue;
85
else if(m > 0)
86
{ status[r] = m&SF_RDWR;
87
continue;
88
}
89
}
90
91
if(f->extent < 0) /* unseekable stream, must poll/select */
92
check[c++] = r;
93
else /* seekable streams are always ready */
94
{ if(f->flags&SF_READ)
95
status[r] |= SF_READ;
96
if(f->flags&SF_WRITE)
97
status[r] |= SF_WRITE;
98
}
99
}
100
/* terminate poll on interrupt only if all streams marked SF_IOINTR */
101
eintr = eintr == n ? -1 : EINTR;
102
103
np = -1;
104
#if _lib_poll
105
if(c > 0)
106
{ struct pollfd* fds;
107
108
/* construct the poll array */
109
for(m = 0, r = 0; r < c; ++r, ++m)
110
{ f = fa[check[r]];
111
if(HASAUXFD(f))
112
m += 1;
113
}
114
if(!(fds = (struct pollfd*)malloc(m*sizeof(struct pollfd))) )
115
return -1;
116
117
for(m = 0, r = 0; r < c; ++r, ++m)
118
{ f = fa[check[r]];
119
120
fds[m].fd = f->file;
121
fds[m].events = fds[m].revents = 0;
122
123
if((f->flags&SF_WRITE) && !WRREADY(f) )
124
fds[m].events |= POLLOUT;
125
126
if((f->flags&SF_READ) && !RDREADY(f) )
127
{ /* a sfpopen situation with two file descriptors */
128
if((f->mode&SF_WRITE) && HASAUXFD(f))
129
{ m += 1;
130
fds[m].fd = f->proc->file;
131
fds[m].revents = 0;
132
}
133
134
fds[m].events |= POLLIN;
135
}
136
}
137
138
while((np = SFPOLL(fds,m,tm)) < 0 )
139
{ if(errno == eintr || errno == EAGAIN)
140
errno = 0;
141
else break;
142
}
143
if(np > 0) /* poll succeeded */
144
np = c;
145
146
for(m = 0, r = 0; r < np; ++r, ++m)
147
{ f = fa[check[r]];
148
149
if((f->flags&SF_WRITE) && !WRREADY(f) )
150
{ if(fds[m].revents&POLLOUT)
151
status[check[r]] |= SF_WRITE;
152
}
153
154
if((f->flags&SF_READ) && !RDREADY(f))
155
{ if((f->mode&SF_WRITE) && HASAUXFD(f))
156
m += 1;
157
if(fds[m].revents&POLLIN)
158
status[check[r]] |= SF_READ;
159
}
160
}
161
162
free((Void_t*)fds);
163
}
164
#endif /*_lib_poll*/
165
166
#if _lib_select
167
if(np < 0 && c > 0)
168
{ fd_set rd, wr;
169
struct timeval tmb, *tmp;
170
171
FD_ZERO(&rd);
172
FD_ZERO(&wr);
173
m = 0;
174
for(r = 0; r < c; ++r)
175
{ f = fa[check[r]];
176
177
if(f->file > m)
178
m = f->file;
179
180
if((f->flags&SF_WRITE) && !WRREADY(f))
181
FD_SET(f->file,&wr);
182
183
if((f->flags&SF_READ) && !RDREADY(f))
184
{ if((f->mode&SF_WRITE) && HASAUXFD(f))
185
{ if(f->proc->file > m)
186
m = f->proc->file;
187
FD_SET(f->proc->file, &rd);
188
}
189
else FD_SET(f->file,&rd);
190
}
191
}
192
if(tm < 0)
193
tmp = NIL(struct timeval*);
194
else
195
{ tmp = &tmb;
196
tmb.tv_sec = tm/SECOND;
197
tmb.tv_usec = (tm%SECOND)*SECOND;
198
}
199
200
while((np = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) < 0 )
201
{ if(errno == eintr)
202
errno = 0;
203
else break;
204
}
205
if(np > 0)
206
np = c;
207
208
for(r = 0; r < np; ++r)
209
{ f = fa[check[r]];
210
211
if((f->flags&SF_WRITE) && !WRREADY(f) )
212
{ if(FD_ISSET(f->file,&wr) )
213
status[check[r]] |= SF_WRITE;
214
}
215
216
if((f->flags&SF_READ) && !RDREADY(f) )
217
{ if((f->mode&SF_WRITE) && HASAUXFD(f) )
218
{ if(FD_ISSET(f->proc->file, &rd) )
219
status[check[r]] |= SF_READ;
220
}
221
else
222
{ if(FD_ISSET(f->file,&rd) )
223
status[check[r]] |= SF_READ;
224
}
225
}
226
}
227
}
228
#endif /*_lib_select*/
229
230
for(r = c = 0; c < n; ++c)
231
{ if(status[c] == 0)
232
continue;
233
234
f = fa[c];
235
f->val = (ssize_t)status[c];
236
237
/* announce status */
238
if(f->disc && f->disc->exceptf)
239
(*f->disc->exceptf)(f,SF_READY,(Void_t*)(long)status[c],f->disc);
240
241
if(c > r) /* move to front of list */
242
{ fa[c] = fa[r];
243
fa[r] = f;
244
}
245
r += 1;
246
}
247
248
free((Void_t*)status);
249
return r ? r : np < 0 ? -1 : 0;
250
}
251
252