|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #if defined(_PR_PTHREADS) |
|
7 |
|
8 #error "This file should not be compiled" |
|
9 |
|
10 #else /* defined(_PR_PTHREADS) */ |
|
11 |
|
12 #include "primpl.h" |
|
13 |
|
14 #include <sys/time.h> |
|
15 |
|
16 #include <fcntl.h> |
|
17 #ifdef _PR_USE_POLL |
|
18 #include <poll.h> |
|
19 #endif |
|
20 |
|
21 #if defined(_PR_USE_POLL) |
|
22 static PRInt32 NativeThreadPoll( |
|
23 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) |
|
24 { |
|
25 /* |
|
26 * This function is mostly duplicated from ptio.s's PR_Poll(). |
|
27 */ |
|
28 PRInt32 ready = 0; |
|
29 /* |
|
30 * For restarting poll() if it is interrupted by a signal. |
|
31 * We use these variables to figure out how much time has |
|
32 * elapsed and how much of the timeout still remains. |
|
33 */ |
|
34 PRIntn index, msecs; |
|
35 struct pollfd *syspoll = NULL; |
|
36 PRIntervalTime start, elapsed, remaining; |
|
37 |
|
38 syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd)); |
|
39 if (NULL == syspoll) |
|
40 { |
|
41 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
|
42 return -1; |
|
43 } |
|
44 for (index = 0; index < npds; ++index) |
|
45 { |
|
46 PRFileDesc *bottom; |
|
47 PRInt16 in_flags_read = 0, in_flags_write = 0; |
|
48 PRInt16 out_flags_read = 0, out_flags_write = 0; |
|
49 |
|
50 if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) |
|
51 { |
|
52 if (pds[index].in_flags & PR_POLL_READ) |
|
53 { |
|
54 in_flags_read = (pds[index].fd->methods->poll)( |
|
55 pds[index].fd, |
|
56 pds[index].in_flags & ~PR_POLL_WRITE, |
|
57 &out_flags_read); |
|
58 } |
|
59 if (pds[index].in_flags & PR_POLL_WRITE) |
|
60 { |
|
61 in_flags_write = (pds[index].fd->methods->poll)( |
|
62 pds[index].fd, |
|
63 pds[index].in_flags & ~PR_POLL_READ, |
|
64 &out_flags_write); |
|
65 } |
|
66 if ((0 != (in_flags_read & out_flags_read)) |
|
67 || (0 != (in_flags_write & out_flags_write))) |
|
68 { |
|
69 /* this one is ready right now */ |
|
70 if (0 == ready) |
|
71 { |
|
72 /* |
|
73 * We will return without calling the system |
|
74 * poll function. So zero the out_flags |
|
75 * fields of all the poll descriptors before |
|
76 * this one. |
|
77 */ |
|
78 int i; |
|
79 for (i = 0; i < index; i++) |
|
80 { |
|
81 pds[i].out_flags = 0; |
|
82 } |
|
83 } |
|
84 ready += 1; |
|
85 pds[index].out_flags = out_flags_read | out_flags_write; |
|
86 } |
|
87 else |
|
88 { |
|
89 pds[index].out_flags = 0; /* pre-condition */ |
|
90 /* now locate the NSPR layer at the bottom of the stack */ |
|
91 bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER); |
|
92 PR_ASSERT(NULL != bottom); /* what to do about that? */ |
|
93 if ((NULL != bottom) |
|
94 && (_PR_FILEDESC_OPEN == bottom->secret->state)) |
|
95 { |
|
96 if (0 == ready) |
|
97 { |
|
98 syspoll[index].fd = bottom->secret->md.osfd; |
|
99 syspoll[index].events = 0; /* pre-condition */ |
|
100 if (in_flags_read & PR_POLL_READ) |
|
101 { |
|
102 pds[index].out_flags |= |
|
103 _PR_POLL_READ_SYS_READ; |
|
104 syspoll[index].events |= POLLIN; |
|
105 } |
|
106 if (in_flags_read & PR_POLL_WRITE) |
|
107 { |
|
108 pds[index].out_flags |= |
|
109 _PR_POLL_READ_SYS_WRITE; |
|
110 syspoll[index].events |= POLLOUT; |
|
111 } |
|
112 if (in_flags_write & PR_POLL_READ) |
|
113 { |
|
114 pds[index].out_flags |= |
|
115 _PR_POLL_WRITE_SYS_READ; |
|
116 syspoll[index].events |= POLLIN; |
|
117 } |
|
118 if (in_flags_write & PR_POLL_WRITE) |
|
119 { |
|
120 pds[index].out_flags |= |
|
121 _PR_POLL_WRITE_SYS_WRITE; |
|
122 syspoll[index].events |= POLLOUT; |
|
123 } |
|
124 if (pds[index].in_flags & PR_POLL_EXCEPT) |
|
125 syspoll[index].events |= POLLPRI; |
|
126 } |
|
127 } |
|
128 else |
|
129 { |
|
130 if (0 == ready) |
|
131 { |
|
132 int i; |
|
133 for (i = 0; i < index; i++) |
|
134 { |
|
135 pds[i].out_flags = 0; |
|
136 } |
|
137 } |
|
138 ready += 1; /* this will cause an abrupt return */ |
|
139 pds[index].out_flags = PR_POLL_NVAL; /* bogii */ |
|
140 } |
|
141 } |
|
142 } |
|
143 else |
|
144 { |
|
145 /* make poll() ignore this entry */ |
|
146 syspoll[index].fd = -1; |
|
147 syspoll[index].events = 0; |
|
148 pds[index].out_flags = 0; |
|
149 } |
|
150 } |
|
151 |
|
152 if (0 == ready) |
|
153 { |
|
154 switch (timeout) |
|
155 { |
|
156 case PR_INTERVAL_NO_WAIT: msecs = 0; break; |
|
157 case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break; |
|
158 default: |
|
159 msecs = PR_IntervalToMilliseconds(timeout); |
|
160 start = PR_IntervalNow(); |
|
161 } |
|
162 |
|
163 retry: |
|
164 ready = _MD_POLL(syspoll, npds, msecs); |
|
165 if (-1 == ready) |
|
166 { |
|
167 PRIntn oserror = errno; |
|
168 |
|
169 if (EINTR == oserror) |
|
170 { |
|
171 if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; |
|
172 else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0; |
|
173 else |
|
174 { |
|
175 elapsed = (PRIntervalTime)(PR_IntervalNow() - start); |
|
176 if (elapsed > timeout) ready = 0; /* timed out */ |
|
177 else |
|
178 { |
|
179 remaining = timeout - elapsed; |
|
180 msecs = PR_IntervalToMilliseconds(remaining); |
|
181 goto retry; |
|
182 } |
|
183 } |
|
184 } |
|
185 else _PR_MD_MAP_POLL_ERROR(oserror); |
|
186 } |
|
187 else if (ready > 0) |
|
188 { |
|
189 for (index = 0; index < npds; ++index) |
|
190 { |
|
191 PRInt16 out_flags = 0; |
|
192 if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) |
|
193 { |
|
194 if (0 != syspoll[index].revents) |
|
195 { |
|
196 /* |
|
197 ** Set up the out_flags so that it contains the |
|
198 ** bits that the highest layer thinks are nice |
|
199 ** to have. Then the client of that layer will |
|
200 ** call the appropriate I/O function and maybe |
|
201 ** the protocol will make progress. |
|
202 */ |
|
203 if (syspoll[index].revents & POLLIN) |
|
204 { |
|
205 if (pds[index].out_flags |
|
206 & _PR_POLL_READ_SYS_READ) |
|
207 { |
|
208 out_flags |= PR_POLL_READ; |
|
209 } |
|
210 if (pds[index].out_flags |
|
211 & _PR_POLL_WRITE_SYS_READ) |
|
212 { |
|
213 out_flags |= PR_POLL_WRITE; |
|
214 } |
|
215 } |
|
216 if (syspoll[index].revents & POLLOUT) |
|
217 { |
|
218 if (pds[index].out_flags |
|
219 & _PR_POLL_READ_SYS_WRITE) |
|
220 { |
|
221 out_flags |= PR_POLL_READ; |
|
222 } |
|
223 if (pds[index].out_flags |
|
224 & _PR_POLL_WRITE_SYS_WRITE) |
|
225 { |
|
226 out_flags |= PR_POLL_WRITE; |
|
227 } |
|
228 } |
|
229 if (syspoll[index].revents & POLLPRI) |
|
230 out_flags |= PR_POLL_EXCEPT; |
|
231 if (syspoll[index].revents & POLLERR) |
|
232 out_flags |= PR_POLL_ERR; |
|
233 if (syspoll[index].revents & POLLNVAL) |
|
234 out_flags |= PR_POLL_NVAL; |
|
235 if (syspoll[index].revents & POLLHUP) |
|
236 out_flags |= PR_POLL_HUP; |
|
237 } |
|
238 } |
|
239 pds[index].out_flags = out_flags; |
|
240 } |
|
241 } |
|
242 } |
|
243 |
|
244 PR_DELETE(syspoll); |
|
245 return ready; |
|
246 |
|
247 } /* NativeThreadPoll */ |
|
248 #endif /* defined(_PR_USE_POLL) */ |
|
249 |
|
250 #if !defined(_PR_USE_POLL) |
|
251 static PRInt32 NativeThreadSelect( |
|
252 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) |
|
253 { |
|
254 /* |
|
255 * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL(). |
|
256 */ |
|
257 fd_set rd, wt, ex; |
|
258 PRFileDesc *bottom; |
|
259 PRPollDesc *pd, *epd; |
|
260 PRInt32 maxfd = -1, ready, err; |
|
261 PRIntervalTime remaining, elapsed, start; |
|
262 |
|
263 struct timeval tv, *tvp = NULL; |
|
264 |
|
265 FD_ZERO(&rd); |
|
266 FD_ZERO(&wt); |
|
267 FD_ZERO(&ex); |
|
268 |
|
269 ready = 0; |
|
270 for (pd = pds, epd = pd + npds; pd < epd; pd++) |
|
271 { |
|
272 PRInt16 in_flags_read = 0, in_flags_write = 0; |
|
273 PRInt16 out_flags_read = 0, out_flags_write = 0; |
|
274 |
|
275 if ((NULL != pd->fd) && (0 != pd->in_flags)) |
|
276 { |
|
277 if (pd->in_flags & PR_POLL_READ) |
|
278 { |
|
279 in_flags_read = (pd->fd->methods->poll)( |
|
280 pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); |
|
281 } |
|
282 if (pd->in_flags & PR_POLL_WRITE) |
|
283 { |
|
284 in_flags_write = (pd->fd->methods->poll)( |
|
285 pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); |
|
286 } |
|
287 if ((0 != (in_flags_read & out_flags_read)) |
|
288 || (0 != (in_flags_write & out_flags_write))) |
|
289 { |
|
290 /* this one's ready right now */ |
|
291 if (0 == ready) |
|
292 { |
|
293 /* |
|
294 * We will have to return without calling the |
|
295 * system poll/select function. So zero the |
|
296 * out_flags fields of all the poll descriptors |
|
297 * before this one. |
|
298 */ |
|
299 PRPollDesc *prev; |
|
300 for (prev = pds; prev < pd; prev++) |
|
301 { |
|
302 prev->out_flags = 0; |
|
303 } |
|
304 } |
|
305 ready += 1; |
|
306 pd->out_flags = out_flags_read | out_flags_write; |
|
307 } |
|
308 else |
|
309 { |
|
310 pd->out_flags = 0; /* pre-condition */ |
|
311 |
|
312 /* make sure this is an NSPR supported stack */ |
|
313 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); |
|
314 PR_ASSERT(NULL != bottom); /* what to do about that? */ |
|
315 if ((NULL != bottom) |
|
316 && (_PR_FILEDESC_OPEN == bottom->secret->state)) |
|
317 { |
|
318 if (0 == ready) |
|
319 { |
|
320 PRInt32 osfd = bottom->secret->md.osfd; |
|
321 if (osfd > maxfd) maxfd = osfd; |
|
322 if (in_flags_read & PR_POLL_READ) |
|
323 { |
|
324 pd->out_flags |= _PR_POLL_READ_SYS_READ; |
|
325 FD_SET(osfd, &rd); |
|
326 } |
|
327 if (in_flags_read & PR_POLL_WRITE) |
|
328 { |
|
329 pd->out_flags |= _PR_POLL_READ_SYS_WRITE; |
|
330 FD_SET(osfd, &wt); |
|
331 } |
|
332 if (in_flags_write & PR_POLL_READ) |
|
333 { |
|
334 pd->out_flags |= _PR_POLL_WRITE_SYS_READ; |
|
335 FD_SET(osfd, &rd); |
|
336 } |
|
337 if (in_flags_write & PR_POLL_WRITE) |
|
338 { |
|
339 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; |
|
340 FD_SET(osfd, &wt); |
|
341 } |
|
342 if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); |
|
343 } |
|
344 } |
|
345 else |
|
346 { |
|
347 if (0 == ready) |
|
348 { |
|
349 PRPollDesc *prev; |
|
350 for (prev = pds; prev < pd; prev++) |
|
351 { |
|
352 prev->out_flags = 0; |
|
353 } |
|
354 } |
|
355 ready += 1; /* this will cause an abrupt return */ |
|
356 pd->out_flags = PR_POLL_NVAL; /* bogii */ |
|
357 } |
|
358 } |
|
359 } |
|
360 else |
|
361 { |
|
362 pd->out_flags = 0; |
|
363 } |
|
364 } |
|
365 |
|
366 if (0 != ready) return ready; /* no need to block */ |
|
367 |
|
368 remaining = timeout; |
|
369 start = PR_IntervalNow(); |
|
370 |
|
371 retry: |
|
372 if (timeout != PR_INTERVAL_NO_TIMEOUT) |
|
373 { |
|
374 PRInt32 ticksPerSecond = PR_TicksPerSecond(); |
|
375 tv.tv_sec = remaining / ticksPerSecond; |
|
376 tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); |
|
377 tvp = &tv; |
|
378 } |
|
379 |
|
380 ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); |
|
381 |
|
382 if (ready == -1 && errno == EINTR) |
|
383 { |
|
384 if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; |
|
385 else |
|
386 { |
|
387 elapsed = (PRIntervalTime) (PR_IntervalNow() - start); |
|
388 if (elapsed > timeout) ready = 0; /* timed out */ |
|
389 else |
|
390 { |
|
391 remaining = timeout - elapsed; |
|
392 goto retry; |
|
393 } |
|
394 } |
|
395 } |
|
396 |
|
397 /* |
|
398 ** Now to unravel the select sets back into the client's poll |
|
399 ** descriptor list. Is this possibly an area for pissing away |
|
400 ** a few cycles or what? |
|
401 */ |
|
402 if (ready > 0) |
|
403 { |
|
404 ready = 0; |
|
405 for (pd = pds, epd = pd + npds; pd < epd; pd++) |
|
406 { |
|
407 PRInt16 out_flags = 0; |
|
408 if ((NULL != pd->fd) && (0 != pd->in_flags)) |
|
409 { |
|
410 PRInt32 osfd; |
|
411 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); |
|
412 PR_ASSERT(NULL != bottom); |
|
413 |
|
414 osfd = bottom->secret->md.osfd; |
|
415 |
|
416 if (FD_ISSET(osfd, &rd)) |
|
417 { |
|
418 if (pd->out_flags & _PR_POLL_READ_SYS_READ) |
|
419 out_flags |= PR_POLL_READ; |
|
420 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) |
|
421 out_flags |= PR_POLL_WRITE; |
|
422 } |
|
423 if (FD_ISSET(osfd, &wt)) |
|
424 { |
|
425 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) |
|
426 out_flags |= PR_POLL_READ; |
|
427 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) |
|
428 out_flags |= PR_POLL_WRITE; |
|
429 } |
|
430 if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; |
|
431 } |
|
432 pd->out_flags = out_flags; |
|
433 if (out_flags) ready++; |
|
434 } |
|
435 PR_ASSERT(ready > 0); |
|
436 } |
|
437 else if (ready < 0) |
|
438 { |
|
439 err = _MD_ERRNO(); |
|
440 if (err == EBADF) |
|
441 { |
|
442 /* Find the bad fds */ |
|
443 ready = 0; |
|
444 for (pd = pds, epd = pd + npds; pd < epd; pd++) |
|
445 { |
|
446 pd->out_flags = 0; |
|
447 if ((NULL != pd->fd) && (0 != pd->in_flags)) |
|
448 { |
|
449 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); |
|
450 if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) |
|
451 { |
|
452 pd->out_flags = PR_POLL_NVAL; |
|
453 ready++; |
|
454 } |
|
455 } |
|
456 } |
|
457 PR_ASSERT(ready > 0); |
|
458 } |
|
459 else _PR_MD_MAP_SELECT_ERROR(err); |
|
460 } |
|
461 |
|
462 return ready; |
|
463 } /* NativeThreadSelect */ |
|
464 #endif /* !defined(_PR_USE_POLL) */ |
|
465 |
|
466 static PRInt32 LocalThreads( |
|
467 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) |
|
468 { |
|
469 PRPollDesc *pd, *epd; |
|
470 PRInt32 ready, pdcnt; |
|
471 _PRUnixPollDesc *unixpds, *unixpd; |
|
472 |
|
473 /* |
|
474 * XXX |
|
475 * PRPollDesc has a PRFileDesc field, fd, while the IOQ |
|
476 * is a list of PRPollQueue structures, each of which contains |
|
477 * a _PRUnixPollDesc. A _PRUnixPollDesc struct contains |
|
478 * the OS file descriptor, osfd, and not a PRFileDesc. |
|
479 * So, we have allocate memory for _PRUnixPollDesc structures, |
|
480 * copy the flags information from the pds list and have pq |
|
481 * point to this list of _PRUnixPollDesc structures. |
|
482 * |
|
483 * It would be better if the memory allocation can be avoided. |
|
484 */ |
|
485 |
|
486 unixpd = unixpds = (_PRUnixPollDesc*) |
|
487 PR_MALLOC(npds * sizeof(_PRUnixPollDesc)); |
|
488 if (NULL == unixpds) |
|
489 { |
|
490 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
|
491 return -1; |
|
492 } |
|
493 |
|
494 ready = 0; |
|
495 for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++) |
|
496 { |
|
497 PRFileDesc *bottom; |
|
498 PRInt16 in_flags_read = 0, in_flags_write = 0; |
|
499 PRInt16 out_flags_read = 0, out_flags_write = 0; |
|
500 |
|
501 if ((NULL != pd->fd) && (0 != pd->in_flags)) |
|
502 { |
|
503 if (pd->in_flags & PR_POLL_READ) |
|
504 { |
|
505 in_flags_read = (pd->fd->methods->poll)( |
|
506 pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); |
|
507 } |
|
508 if (pd->in_flags & PR_POLL_WRITE) |
|
509 { |
|
510 in_flags_write = (pd->fd->methods->poll)( |
|
511 pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); |
|
512 } |
|
513 if ((0 != (in_flags_read & out_flags_read)) |
|
514 || (0 != (in_flags_write & out_flags_write))) |
|
515 { |
|
516 /* this one's ready right now */ |
|
517 if (0 == ready) |
|
518 { |
|
519 /* |
|
520 * We will have to return without calling the |
|
521 * system poll/select function. So zero the |
|
522 * out_flags fields of all the poll descriptors |
|
523 * before this one. |
|
524 */ |
|
525 PRPollDesc *prev; |
|
526 for (prev = pds; prev < pd; prev++) |
|
527 { |
|
528 prev->out_flags = 0; |
|
529 } |
|
530 } |
|
531 ready += 1; |
|
532 pd->out_flags = out_flags_read | out_flags_write; |
|
533 } |
|
534 else |
|
535 { |
|
536 pd->out_flags = 0; /* pre-condition */ |
|
537 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); |
|
538 PR_ASSERT(NULL != bottom); /* what to do about that? */ |
|
539 if ((NULL != bottom) |
|
540 && (_PR_FILEDESC_OPEN == bottom->secret->state)) |
|
541 { |
|
542 if (0 == ready) |
|
543 { |
|
544 unixpd->osfd = bottom->secret->md.osfd; |
|
545 unixpd->in_flags = 0; |
|
546 if (in_flags_read & PR_POLL_READ) |
|
547 { |
|
548 unixpd->in_flags |= _PR_UNIX_POLL_READ; |
|
549 pd->out_flags |= _PR_POLL_READ_SYS_READ; |
|
550 } |
|
551 if (in_flags_read & PR_POLL_WRITE) |
|
552 { |
|
553 unixpd->in_flags |= _PR_UNIX_POLL_WRITE; |
|
554 pd->out_flags |= _PR_POLL_READ_SYS_WRITE; |
|
555 } |
|
556 if (in_flags_write & PR_POLL_READ) |
|
557 { |
|
558 unixpd->in_flags |= _PR_UNIX_POLL_READ; |
|
559 pd->out_flags |= _PR_POLL_WRITE_SYS_READ; |
|
560 } |
|
561 if (in_flags_write & PR_POLL_WRITE) |
|
562 { |
|
563 unixpd->in_flags |= _PR_UNIX_POLL_WRITE; |
|
564 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; |
|
565 } |
|
566 if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT) |
|
567 { |
|
568 unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT; |
|
569 } |
|
570 unixpd++; pdcnt++; |
|
571 } |
|
572 } |
|
573 else |
|
574 { |
|
575 if (0 == ready) |
|
576 { |
|
577 PRPollDesc *prev; |
|
578 for (prev = pds; prev < pd; prev++) |
|
579 { |
|
580 prev->out_flags = 0; |
|
581 } |
|
582 } |
|
583 ready += 1; /* this will cause an abrupt return */ |
|
584 pd->out_flags = PR_POLL_NVAL; /* bogii */ |
|
585 } |
|
586 } |
|
587 } |
|
588 } |
|
589 |
|
590 if (0 != ready) |
|
591 { |
|
592 /* no need to block */ |
|
593 PR_DELETE(unixpds); |
|
594 return ready; |
|
595 } |
|
596 |
|
597 ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout); |
|
598 |
|
599 /* |
|
600 * Copy the out_flags from the _PRUnixPollDesc structures to the |
|
601 * user's PRPollDesc structures and free the allocated memory |
|
602 */ |
|
603 unixpd = unixpds; |
|
604 for (pd = pds, epd = pd + npds; pd < epd; pd++) |
|
605 { |
|
606 PRInt16 out_flags = 0; |
|
607 if ((NULL != pd->fd) && (0 != pd->in_flags)) |
|
608 { |
|
609 /* |
|
610 * take errors from the poll operation, |
|
611 * the R/W bits from the request |
|
612 */ |
|
613 if (0 != unixpd->out_flags) |
|
614 { |
|
615 if (unixpd->out_flags & _PR_UNIX_POLL_READ) |
|
616 { |
|
617 if (pd->out_flags & _PR_POLL_READ_SYS_READ) |
|
618 out_flags |= PR_POLL_READ; |
|
619 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) |
|
620 out_flags |= PR_POLL_WRITE; |
|
621 } |
|
622 if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) |
|
623 { |
|
624 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) |
|
625 out_flags |= PR_POLL_READ; |
|
626 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) |
|
627 out_flags |= PR_POLL_WRITE; |
|
628 } |
|
629 if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) |
|
630 out_flags |= PR_POLL_EXCEPT; |
|
631 if (unixpd->out_flags & _PR_UNIX_POLL_ERR) |
|
632 out_flags |= PR_POLL_ERR; |
|
633 if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) |
|
634 out_flags |= PR_POLL_NVAL; |
|
635 if (unixpd->out_flags & _PR_UNIX_POLL_HUP) |
|
636 out_flags |= PR_POLL_HUP; |
|
637 } |
|
638 unixpd++; |
|
639 } |
|
640 pd->out_flags = out_flags; |
|
641 } |
|
642 |
|
643 PR_DELETE(unixpds); |
|
644 |
|
645 return ready; |
|
646 } /* LocalThreads */ |
|
647 |
|
648 #if defined(_PR_USE_POLL) |
|
649 #define NativeThreads NativeThreadPoll |
|
650 #else |
|
651 #define NativeThreads NativeThreadSelect |
|
652 #endif |
|
653 |
|
654 PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) |
|
655 { |
|
656 PRInt32 rv = 0; |
|
657 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
658 |
|
659 if (_PR_PENDING_INTERRUPT(me)) |
|
660 { |
|
661 me->flags &= ~_PR_INTERRUPT; |
|
662 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); |
|
663 return -1; |
|
664 } |
|
665 if (0 == npds) PR_Sleep(timeout); |
|
666 else if (_PR_IS_NATIVE_THREAD(me)) |
|
667 rv = NativeThreads(pds, npds, timeout); |
|
668 else rv = LocalThreads(pds, npds, timeout); |
|
669 |
|
670 return rv; |
|
671 } /* _MD_pr_poll */ |
|
672 |
|
673 #endif /* defined(_PR_PTHREADS) */ |
|
674 |
|
675 /* uxpoll.c */ |
|
676 |