1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is the Netscape Portable Runtime (NSPR).
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998-2000
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
* This file implements _PR_MD_PR_POLL for OS/2.
43
#include <sys/time.h> /* For timeval. */
49
/* Utility functions called when using OS/2 select */
51
PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
54
PRBool isSet = PR_FALSE;
56
for( i = start; i < start+count; i++ )
58
if( socks[i] == osfd )
66
PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
78
PRInt32 maxfd = -1, ready, err;
79
PRIntervalTime remaining, elapsed, start;
82
struct timeval tv, *tvp = NULL;
91
socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
95
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
101
for (pd = pds, epd = pd + npds; pd < epd; pd++)
103
PRInt16 in_flags_read = 0, in_flags_write = 0;
104
PRInt16 out_flags_read = 0, out_flags_write = 0;
106
if ((NULL != pd->fd) && (0 != pd->in_flags))
108
if (pd->in_flags & PR_POLL_READ)
110
in_flags_read = (pd->fd->methods->poll)(
111
pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
113
if (pd->in_flags & PR_POLL_WRITE)
115
in_flags_write = (pd->fd->methods->poll)(
116
pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
118
if ((0 != (in_flags_read & out_flags_read)) ||
119
(0 != (in_flags_write & out_flags_write)))
121
/* this one's ready right now */
125
* We will have to return without calling the
126
* system poll/select function. So zero the
127
* out_flags fields of all the poll descriptors
131
for (prev = pds; prev < pd; prev++)
137
pd->out_flags = out_flags_read | out_flags_write;
141
pd->out_flags = 0; /* pre-condition */
143
/* make sure this is an NSPR supported stack */
144
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
145
PR_ASSERT(NULL != bottom); /* what to do about that? */
146
if ((NULL != bottom) &&
147
(_PR_FILEDESC_OPEN == bottom->secret->state))
151
PRInt32 osfd = bottom->secret->md.osfd;
154
if (in_flags_read & PR_POLL_READ)
156
pd->out_flags |= _PR_POLL_READ_SYS_READ;
164
if (in_flags_read & PR_POLL_WRITE)
166
pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
170
socks[npds+wt] = osfd;
174
if (in_flags_write & PR_POLL_READ)
176
pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
184
if (in_flags_write & PR_POLL_WRITE)
186
pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
190
socks[npds+wt] = osfd;
194
if (pd->in_flags & PR_POLL_EXCEPT)
199
socks[npds*2+ex] = osfd;
210
for (prev = pds; prev < pd; prev++)
215
ready += 1; /* this will cause an abrupt return */
216
pd->out_flags = PR_POLL_NVAL; /* bogii */
231
return ready; /* no need to block */
235
start = PR_IntervalNow();
239
if (timeout != PR_INTERVAL_NO_TIMEOUT)
241
PRInt32 ticksPerSecond = PR_TicksPerSecond();
242
tv.tv_sec = remaining / ticksPerSecond;
243
tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
247
ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
251
case PR_INTERVAL_NO_WAIT:
254
case PR_INTERVAL_NO_TIMEOUT:
258
msecs = PR_IntervalToMilliseconds(remaining);
262
for( i = rd, j = npds; j < npds+wt; i++,j++ )
264
for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
267
ready = os2_select(socks, rd, wt, ex, msecs);
270
if (ready == -1 && errno == EINTR)
272
if (timeout == PR_INTERVAL_NO_TIMEOUT)
276
elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
277
if (elapsed > timeout)
278
ready = 0; /* timed out */
281
remaining = timeout - elapsed;
288
** Now to unravel the select sets back into the client's poll
289
** descriptor list. Is this possibly an area for pissing away
290
** a few cycles or what?
295
for (pd = pds, epd = pd + npds; pd < epd; pd++)
297
PRInt16 out_flags = 0;
298
if ((NULL != pd->fd) && (0 != pd->in_flags))
301
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
302
PR_ASSERT(NULL != bottom);
304
osfd = bottom->secret->md.osfd;
307
if (FD_ISSET(osfd, &rd))
309
if( IsSocketSet(osfd, socks, 0, rd) )
312
if (pd->out_flags & _PR_POLL_READ_SYS_READ)
313
out_flags |= PR_POLL_READ;
314
if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
315
out_flags |= PR_POLL_WRITE;
319
if (FD_ISSET(osfd, &wt))
321
if( IsSocketSet(osfd, socks, rd, wt) )
324
if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
325
out_flags |= PR_POLL_READ;
326
if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
327
out_flags |= PR_POLL_WRITE;
331
if (FD_ISSET(osfd, &ex))
333
if( IsSocketSet(osfd, socks, rd+wt, ex) )
336
out_flags |= PR_POLL_EXCEPT;
339
pd->out_flags = out_flags;
340
if (out_flags) ready++;
342
PR_ASSERT(ready > 0);
349
/* Find the bad fds */
351
int optlen = sizeof(optval);
353
for (pd = pds, epd = pd + npds; pd < epd; pd++)
356
if ((NULL != pd->fd) && (0 != pd->in_flags))
358
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
359
if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
360
SO_TYPE, (char *) &optval, &optlen) == -1)
362
PR_ASSERT(sock_errno() == ENOTSOCK);
363
if (sock_errno() == ENOTSOCK)
365
pd->out_flags = PR_POLL_NVAL;
371
PR_ASSERT(ready > 0);
374
_PR_MD_MAP_SELECT_ERROR(err);