Wed, 31 Dec 2014 06:09:35 +0100
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 |