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.
42 #include <sys/time.h> /* For timeval. */
47 /* Utility functions called when using OS/2 select */
49 PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
52 PRBool isSet = PR_FALSE;
54 for( i = start; i < start+count; i++ )
56 if( socks[i] == osfd )
64 PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
76 PRInt32 maxfd = -1, ready, err;
77 PRIntervalTime remaining, elapsed, start;
80 struct timeval tv, *tvp = NULL;
89 socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
93 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
99 for (pd = pds, epd = pd + npds; pd < epd; pd++)
101 PRInt16 in_flags_read = 0, in_flags_write = 0;
102 PRInt16 out_flags_read = 0, out_flags_write = 0;
104 if ((NULL != pd->fd) && (0 != pd->in_flags))
106 if (pd->in_flags & PR_POLL_READ)
108 in_flags_read = (pd->fd->methods->poll)(
109 pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
111 if (pd->in_flags & PR_POLL_WRITE)
113 in_flags_write = (pd->fd->methods->poll)(
114 pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
116 if ((0 != (in_flags_read & out_flags_read)) ||
117 (0 != (in_flags_write & out_flags_write)))
119 /* this one's ready right now */
123 * We will have to return without calling the
124 * system poll/select function. So zero the
125 * out_flags fields of all the poll descriptors
129 for (prev = pds; prev < pd; prev++)
135 pd->out_flags = out_flags_read | out_flags_write;
139 pd->out_flags = 0; /* pre-condition */
141 /* make sure this is an NSPR supported stack */
142 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
143 PR_ASSERT(NULL != bottom); /* what to do about that? */
144 if ((NULL != bottom) &&
145 (_PR_FILEDESC_OPEN == bottom->secret->state))
149 PRInt32 osfd = bottom->secret->md.osfd;
152 if (in_flags_read & PR_POLL_READ)
154 pd->out_flags |= _PR_POLL_READ_SYS_READ;
162 if (in_flags_read & PR_POLL_WRITE)
164 pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
168 socks[npds+wt] = osfd;
172 if (in_flags_write & PR_POLL_READ)
174 pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
182 if (in_flags_write & PR_POLL_WRITE)
184 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
188 socks[npds+wt] = osfd;
192 if (pd->in_flags & PR_POLL_EXCEPT)
197 socks[npds*2+ex] = osfd;
208 for (prev = pds; prev < pd; prev++)
213 ready += 1; /* this will cause an abrupt return */
214 pd->out_flags = PR_POLL_NVAL; /* bogii */
229 return ready; /* no need to block */
233 start = PR_IntervalNow();
237 if (timeout != PR_INTERVAL_NO_TIMEOUT)
239 PRInt32 ticksPerSecond = PR_TicksPerSecond();
240 tv.tv_sec = remaining / ticksPerSecond;
241 tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
245 ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
249 case PR_INTERVAL_NO_WAIT:
252 case PR_INTERVAL_NO_TIMEOUT:
256 msecs = PR_IntervalToMilliseconds(remaining);
260 for( i = rd, j = npds; j < npds+wt; i++,j++ )
262 for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
265 ready = os2_select(socks, rd, wt, ex, msecs);
268 if (ready == -1 && errno == EINTR)
270 if (timeout == PR_INTERVAL_NO_TIMEOUT)
274 elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
275 if (elapsed > timeout)
276 ready = 0; /* timed out */
279 remaining = timeout - elapsed;
286 ** Now to unravel the select sets back into the client's poll
287 ** descriptor list. Is this possibly an area for pissing away
288 ** a few cycles or what?
293 for (pd = pds, epd = pd + npds; pd < epd; pd++)
295 PRInt16 out_flags = 0;
296 if ((NULL != pd->fd) && (0 != pd->in_flags))
299 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
300 PR_ASSERT(NULL != bottom);
302 osfd = bottom->secret->md.osfd;
305 if (FD_ISSET(osfd, &rd))
307 if( IsSocketSet(osfd, socks, 0, rd) )
310 if (pd->out_flags & _PR_POLL_READ_SYS_READ)
311 out_flags |= PR_POLL_READ;
312 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
313 out_flags |= PR_POLL_WRITE;
317 if (FD_ISSET(osfd, &wt))
319 if( IsSocketSet(osfd, socks, rd, wt) )
322 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
323 out_flags |= PR_POLL_READ;
324 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
325 out_flags |= PR_POLL_WRITE;
329 if (FD_ISSET(osfd, &ex))
331 if( IsSocketSet(osfd, socks, rd+wt, ex) )
334 out_flags |= PR_POLL_EXCEPT;
337 pd->out_flags = out_flags;
338 if (out_flags) ready++;
340 PR_ASSERT(ready > 0);
347 /* Find the bad fds */
349 int optlen = sizeof(optval);
351 for (pd = pds, epd = pd + npds; pd < epd; pd++)
354 if ((NULL != pd->fd) && (0 != pd->in_flags))
356 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
357 if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
358 SO_TYPE, (char *) &optval, &optlen) == -1)
360 PR_ASSERT(sock_errno() == ENOTSOCK);
361 if (sock_errno() == ENOTSOCK)
363 pd->out_flags = PR_POLL_NVAL;
369 PR_ASSERT(ready > 0);
372 _PR_MD_MAP_SELECT_ERROR(err);