nsprpub/pr/src/md/os2/os2poll.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * This file implements _PR_MD_PR_POLL for OS/2.
michael@0 8 */
michael@0 9
michael@0 10 #include <sys/time.h> /* For timeval. */
michael@0 11
michael@0 12 #include "primpl.h"
michael@0 13
michael@0 14 #ifndef BSD_SELECT
michael@0 15 /* Utility functions called when using OS/2 select */
michael@0 16
michael@0 17 PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
michael@0 18 {
michael@0 19 int i;
michael@0 20 PRBool isSet = PR_FALSE;
michael@0 21
michael@0 22 for( i = start; i < start+count; i++ )
michael@0 23 {
michael@0 24 if( socks[i] == osfd )
michael@0 25 isSet = PR_TRUE;
michael@0 26 }
michael@0 27
michael@0 28 return isSet;
michael@0 29 }
michael@0 30 #endif
michael@0 31
michael@0 32 PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
michael@0 33 {
michael@0 34 #ifdef BSD_SELECT
michael@0 35 fd_set rd, wt, ex;
michael@0 36 #else
michael@0 37 int rd, wt, ex;
michael@0 38 int* socks;
michael@0 39 unsigned long msecs;
michael@0 40 int i, j;
michael@0 41 #endif
michael@0 42 PRFileDesc *bottom;
michael@0 43 PRPollDesc *pd, *epd;
michael@0 44 PRInt32 maxfd = -1, ready, err;
michael@0 45 PRIntervalTime remaining, elapsed, start;
michael@0 46
michael@0 47 #ifdef BSD_SELECT
michael@0 48 struct timeval tv, *tvp = NULL;
michael@0 49
michael@0 50 FD_ZERO(&rd);
michael@0 51 FD_ZERO(&wt);
michael@0 52 FD_ZERO(&ex);
michael@0 53 #else
michael@0 54 rd = 0;
michael@0 55 wt = 0;
michael@0 56 ex = 0;
michael@0 57 socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
michael@0 58
michael@0 59 if (!socks)
michael@0 60 {
michael@0 61 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
michael@0 62 return -1;
michael@0 63 }
michael@0 64 #endif
michael@0 65
michael@0 66 ready = 0;
michael@0 67 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 68 {
michael@0 69 PRInt16 in_flags_read = 0, in_flags_write = 0;
michael@0 70 PRInt16 out_flags_read = 0, out_flags_write = 0;
michael@0 71
michael@0 72 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 73 {
michael@0 74 if (pd->in_flags & PR_POLL_READ)
michael@0 75 {
michael@0 76 in_flags_read = (pd->fd->methods->poll)(
michael@0 77 pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
michael@0 78 }
michael@0 79 if (pd->in_flags & PR_POLL_WRITE)
michael@0 80 {
michael@0 81 in_flags_write = (pd->fd->methods->poll)(
michael@0 82 pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
michael@0 83 }
michael@0 84 if ((0 != (in_flags_read & out_flags_read)) ||
michael@0 85 (0 != (in_flags_write & out_flags_write)))
michael@0 86 {
michael@0 87 /* this one's ready right now */
michael@0 88 if (0 == ready)
michael@0 89 {
michael@0 90 /*
michael@0 91 * We will have to return without calling the
michael@0 92 * system poll/select function. So zero the
michael@0 93 * out_flags fields of all the poll descriptors
michael@0 94 * before this one.
michael@0 95 */
michael@0 96 PRPollDesc *prev;
michael@0 97 for (prev = pds; prev < pd; prev++)
michael@0 98 {
michael@0 99 prev->out_flags = 0;
michael@0 100 }
michael@0 101 }
michael@0 102 ready += 1;
michael@0 103 pd->out_flags = out_flags_read | out_flags_write;
michael@0 104 }
michael@0 105 else
michael@0 106 {
michael@0 107 pd->out_flags = 0; /* pre-condition */
michael@0 108
michael@0 109 /* make sure this is an NSPR supported stack */
michael@0 110 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 111 PR_ASSERT(NULL != bottom); /* what to do about that? */
michael@0 112 if ((NULL != bottom) &&
michael@0 113 (_PR_FILEDESC_OPEN == bottom->secret->state))
michael@0 114 {
michael@0 115 if (0 == ready)
michael@0 116 {
michael@0 117 PRInt32 osfd = bottom->secret->md.osfd;
michael@0 118 if (osfd > maxfd)
michael@0 119 maxfd = osfd;
michael@0 120 if (in_flags_read & PR_POLL_READ)
michael@0 121 {
michael@0 122 pd->out_flags |= _PR_POLL_READ_SYS_READ;
michael@0 123 #ifdef BSD_SELECT
michael@0 124 FD_SET(osfd, &rd);
michael@0 125 #else
michael@0 126 socks[rd] = osfd;
michael@0 127 rd++;
michael@0 128 #endif
michael@0 129 }
michael@0 130 if (in_flags_read & PR_POLL_WRITE)
michael@0 131 {
michael@0 132 pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
michael@0 133 #ifdef BSD_SELECT
michael@0 134 FD_SET(osfd, &wt);
michael@0 135 #else
michael@0 136 socks[npds+wt] = osfd;
michael@0 137 wt++;
michael@0 138 #endif
michael@0 139 }
michael@0 140 if (in_flags_write & PR_POLL_READ)
michael@0 141 {
michael@0 142 pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
michael@0 143 #ifdef BSD_SELECT
michael@0 144 FD_SET(osfd, &rd);
michael@0 145 #else
michael@0 146 socks[rd] = osfd;
michael@0 147 rd++;
michael@0 148 #endif
michael@0 149 }
michael@0 150 if (in_flags_write & PR_POLL_WRITE)
michael@0 151 {
michael@0 152 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
michael@0 153 #ifdef BSD_SELECT
michael@0 154 FD_SET(osfd, &wt);
michael@0 155 #else
michael@0 156 socks[npds+wt] = osfd;
michael@0 157 wt++;
michael@0 158 #endif
michael@0 159 }
michael@0 160 if (pd->in_flags & PR_POLL_EXCEPT)
michael@0 161 {
michael@0 162 #ifdef BSD_SELECT
michael@0 163 FD_SET(osfd, &ex);
michael@0 164 #else
michael@0 165 socks[npds*2+ex] = osfd;
michael@0 166 ex++;
michael@0 167 #endif
michael@0 168 }
michael@0 169 }
michael@0 170 }
michael@0 171 else
michael@0 172 {
michael@0 173 if (0 == ready)
michael@0 174 {
michael@0 175 PRPollDesc *prev;
michael@0 176 for (prev = pds; prev < pd; prev++)
michael@0 177 {
michael@0 178 prev->out_flags = 0;
michael@0 179 }
michael@0 180 }
michael@0 181 ready += 1; /* this will cause an abrupt return */
michael@0 182 pd->out_flags = PR_POLL_NVAL; /* bogii */
michael@0 183 }
michael@0 184 }
michael@0 185 }
michael@0 186 else
michael@0 187 {
michael@0 188 pd->out_flags = 0;
michael@0 189 }
michael@0 190 }
michael@0 191
michael@0 192 if (0 != ready)
michael@0 193 {
michael@0 194 #ifndef BSD_SELECT
michael@0 195 PR_Free(socks);
michael@0 196 #endif
michael@0 197 return ready; /* no need to block */
michael@0 198 }
michael@0 199
michael@0 200 remaining = timeout;
michael@0 201 start = PR_IntervalNow();
michael@0 202
michael@0 203 retry:
michael@0 204 #ifdef BSD_SELECT
michael@0 205 if (timeout != PR_INTERVAL_NO_TIMEOUT)
michael@0 206 {
michael@0 207 PRInt32 ticksPerSecond = PR_TicksPerSecond();
michael@0 208 tv.tv_sec = remaining / ticksPerSecond;
michael@0 209 tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
michael@0 210 tvp = &tv;
michael@0 211 }
michael@0 212
michael@0 213 ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
michael@0 214 #else
michael@0 215 switch (timeout)
michael@0 216 {
michael@0 217 case PR_INTERVAL_NO_WAIT:
michael@0 218 msecs = 0;
michael@0 219 break;
michael@0 220 case PR_INTERVAL_NO_TIMEOUT:
michael@0 221 msecs = -1;
michael@0 222 break;
michael@0 223 default:
michael@0 224 msecs = PR_IntervalToMilliseconds(remaining);
michael@0 225 }
michael@0 226
michael@0 227 /* compact array */
michael@0 228 for( i = rd, j = npds; j < npds+wt; i++,j++ )
michael@0 229 socks[i] = socks[j];
michael@0 230 for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
michael@0 231 socks[i] = socks[j];
michael@0 232
michael@0 233 ready = os2_select(socks, rd, wt, ex, msecs);
michael@0 234 #endif
michael@0 235
michael@0 236 if (ready == -1 && errno == EINTR)
michael@0 237 {
michael@0 238 if (timeout == PR_INTERVAL_NO_TIMEOUT)
michael@0 239 goto retry;
michael@0 240 else
michael@0 241 {
michael@0 242 elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
michael@0 243 if (elapsed > timeout)
michael@0 244 ready = 0; /* timed out */
michael@0 245 else
michael@0 246 {
michael@0 247 remaining = timeout - elapsed;
michael@0 248 goto retry;
michael@0 249 }
michael@0 250 }
michael@0 251 }
michael@0 252
michael@0 253 /*
michael@0 254 ** Now to unravel the select sets back into the client's poll
michael@0 255 ** descriptor list. Is this possibly an area for pissing away
michael@0 256 ** a few cycles or what?
michael@0 257 */
michael@0 258 if (ready > 0)
michael@0 259 {
michael@0 260 ready = 0;
michael@0 261 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 262 {
michael@0 263 PRInt16 out_flags = 0;
michael@0 264 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 265 {
michael@0 266 PRInt32 osfd;
michael@0 267 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 268 PR_ASSERT(NULL != bottom);
michael@0 269
michael@0 270 osfd = bottom->secret->md.osfd;
michael@0 271
michael@0 272 #ifdef BSD_SELECT
michael@0 273 if (FD_ISSET(osfd, &rd))
michael@0 274 #else
michael@0 275 if( IsSocketSet(osfd, socks, 0, rd) )
michael@0 276 #endif
michael@0 277 {
michael@0 278 if (pd->out_flags & _PR_POLL_READ_SYS_READ)
michael@0 279 out_flags |= PR_POLL_READ;
michael@0 280 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
michael@0 281 out_flags |= PR_POLL_WRITE;
michael@0 282 }
michael@0 283
michael@0 284 #ifdef BSD_SELECT
michael@0 285 if (FD_ISSET(osfd, &wt))
michael@0 286 #else
michael@0 287 if( IsSocketSet(osfd, socks, rd, wt) )
michael@0 288 #endif
michael@0 289 {
michael@0 290 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
michael@0 291 out_flags |= PR_POLL_READ;
michael@0 292 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
michael@0 293 out_flags |= PR_POLL_WRITE;
michael@0 294 }
michael@0 295
michael@0 296 #ifdef BSD_SELECT
michael@0 297 if (FD_ISSET(osfd, &ex))
michael@0 298 #else
michael@0 299 if( IsSocketSet(osfd, socks, rd+wt, ex) )
michael@0 300 #endif
michael@0 301 {
michael@0 302 out_flags |= PR_POLL_EXCEPT;
michael@0 303 }
michael@0 304 }
michael@0 305 pd->out_flags = out_flags;
michael@0 306 if (out_flags) ready++;
michael@0 307 }
michael@0 308 PR_ASSERT(ready > 0);
michael@0 309 }
michael@0 310 else if (ready < 0)
michael@0 311 {
michael@0 312 err = _MD_ERRNO();
michael@0 313 if (err == EBADF)
michael@0 314 {
michael@0 315 /* Find the bad fds */
michael@0 316 int optval;
michael@0 317 int optlen = sizeof(optval);
michael@0 318 ready = 0;
michael@0 319 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 320 {
michael@0 321 pd->out_flags = 0;
michael@0 322 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 323 {
michael@0 324 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 325 if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
michael@0 326 SO_TYPE, (char *) &optval, &optlen) == -1)
michael@0 327 {
michael@0 328 PR_ASSERT(sock_errno() == ENOTSOCK);
michael@0 329 if (sock_errno() == ENOTSOCK)
michael@0 330 {
michael@0 331 pd->out_flags = PR_POLL_NVAL;
michael@0 332 ready++;
michael@0 333 }
michael@0 334 }
michael@0 335 }
michael@0 336 }
michael@0 337 PR_ASSERT(ready > 0);
michael@0 338 }
michael@0 339 else
michael@0 340 _PR_MD_MAP_SELECT_ERROR(err);
michael@0 341 }
michael@0 342
michael@0 343 #ifndef BSD_SELECT
michael@0 344 PR_Free(socks);
michael@0 345 #endif
michael@0 346 return ready;
michael@0 347 }
michael@0 348

mercurial