1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/md/os2/os2poll.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,348 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * This file implements _PR_MD_PR_POLL for OS/2. 1.11 + */ 1.12 + 1.13 +#include <sys/time.h> /* For timeval. */ 1.14 + 1.15 +#include "primpl.h" 1.16 + 1.17 +#ifndef BSD_SELECT 1.18 +/* Utility functions called when using OS/2 select */ 1.19 + 1.20 +PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count ) 1.21 +{ 1.22 + int i; 1.23 + PRBool isSet = PR_FALSE; 1.24 + 1.25 + for( i = start; i < start+count; i++ ) 1.26 + { 1.27 + if( socks[i] == osfd ) 1.28 + isSet = PR_TRUE; 1.29 + } 1.30 + 1.31 + return isSet; 1.32 +} 1.33 +#endif 1.34 + 1.35 +PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) 1.36 +{ 1.37 +#ifdef BSD_SELECT 1.38 + fd_set rd, wt, ex; 1.39 +#else 1.40 + int rd, wt, ex; 1.41 + int* socks; 1.42 + unsigned long msecs; 1.43 + int i, j; 1.44 +#endif 1.45 + PRFileDesc *bottom; 1.46 + PRPollDesc *pd, *epd; 1.47 + PRInt32 maxfd = -1, ready, err; 1.48 + PRIntervalTime remaining, elapsed, start; 1.49 + 1.50 +#ifdef BSD_SELECT 1.51 + struct timeval tv, *tvp = NULL; 1.52 + 1.53 + FD_ZERO(&rd); 1.54 + FD_ZERO(&wt); 1.55 + FD_ZERO(&ex); 1.56 +#else 1.57 + rd = 0; 1.58 + wt = 0; 1.59 + ex = 0; 1.60 + socks = (int) PR_MALLOC( npds * 3 * sizeof(int) ); 1.61 + 1.62 + if (!socks) 1.63 + { 1.64 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.65 + return -1; 1.66 + } 1.67 +#endif 1.68 + 1.69 + ready = 0; 1.70 + for (pd = pds, epd = pd + npds; pd < epd; pd++) 1.71 + { 1.72 + PRInt16 in_flags_read = 0, in_flags_write = 0; 1.73 + PRInt16 out_flags_read = 0, out_flags_write = 0; 1.74 + 1.75 + if ((NULL != pd->fd) && (0 != pd->in_flags)) 1.76 + { 1.77 + if (pd->in_flags & PR_POLL_READ) 1.78 + { 1.79 + in_flags_read = (pd->fd->methods->poll)( 1.80 + pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); 1.81 + } 1.82 + if (pd->in_flags & PR_POLL_WRITE) 1.83 + { 1.84 + in_flags_write = (pd->fd->methods->poll)( 1.85 + pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); 1.86 + } 1.87 + if ((0 != (in_flags_read & out_flags_read)) || 1.88 + (0 != (in_flags_write & out_flags_write))) 1.89 + { 1.90 + /* this one's ready right now */ 1.91 + if (0 == ready) 1.92 + { 1.93 + /* 1.94 + * We will have to return without calling the 1.95 + * system poll/select function. So zero the 1.96 + * out_flags fields of all the poll descriptors 1.97 + * before this one. 1.98 + */ 1.99 + PRPollDesc *prev; 1.100 + for (prev = pds; prev < pd; prev++) 1.101 + { 1.102 + prev->out_flags = 0; 1.103 + } 1.104 + } 1.105 + ready += 1; 1.106 + pd->out_flags = out_flags_read | out_flags_write; 1.107 + } 1.108 + else 1.109 + { 1.110 + pd->out_flags = 0; /* pre-condition */ 1.111 + 1.112 + /* make sure this is an NSPR supported stack */ 1.113 + bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); 1.114 + PR_ASSERT(NULL != bottom); /* what to do about that? */ 1.115 + if ((NULL != bottom) && 1.116 + (_PR_FILEDESC_OPEN == bottom->secret->state)) 1.117 + { 1.118 + if (0 == ready) 1.119 + { 1.120 + PRInt32 osfd = bottom->secret->md.osfd; 1.121 + if (osfd > maxfd) 1.122 + maxfd = osfd; 1.123 + if (in_flags_read & PR_POLL_READ) 1.124 + { 1.125 + pd->out_flags |= _PR_POLL_READ_SYS_READ; 1.126 +#ifdef BSD_SELECT 1.127 + FD_SET(osfd, &rd); 1.128 +#else 1.129 + socks[rd] = osfd; 1.130 + rd++; 1.131 +#endif 1.132 + } 1.133 + if (in_flags_read & PR_POLL_WRITE) 1.134 + { 1.135 + pd->out_flags |= _PR_POLL_READ_SYS_WRITE; 1.136 +#ifdef BSD_SELECT 1.137 + FD_SET(osfd, &wt); 1.138 +#else 1.139 + socks[npds+wt] = osfd; 1.140 + wt++; 1.141 +#endif 1.142 + } 1.143 + if (in_flags_write & PR_POLL_READ) 1.144 + { 1.145 + pd->out_flags |= _PR_POLL_WRITE_SYS_READ; 1.146 +#ifdef BSD_SELECT 1.147 + FD_SET(osfd, &rd); 1.148 +#else 1.149 + socks[rd] = osfd; 1.150 + rd++; 1.151 +#endif 1.152 + } 1.153 + if (in_flags_write & PR_POLL_WRITE) 1.154 + { 1.155 + pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; 1.156 +#ifdef BSD_SELECT 1.157 + FD_SET(osfd, &wt); 1.158 +#else 1.159 + socks[npds+wt] = osfd; 1.160 + wt++; 1.161 +#endif 1.162 + } 1.163 + if (pd->in_flags & PR_POLL_EXCEPT) 1.164 + { 1.165 +#ifdef BSD_SELECT 1.166 + FD_SET(osfd, &ex); 1.167 +#else 1.168 + socks[npds*2+ex] = osfd; 1.169 + ex++; 1.170 +#endif 1.171 + } 1.172 + } 1.173 + } 1.174 + else 1.175 + { 1.176 + if (0 == ready) 1.177 + { 1.178 + PRPollDesc *prev; 1.179 + for (prev = pds; prev < pd; prev++) 1.180 + { 1.181 + prev->out_flags = 0; 1.182 + } 1.183 + } 1.184 + ready += 1; /* this will cause an abrupt return */ 1.185 + pd->out_flags = PR_POLL_NVAL; /* bogii */ 1.186 + } 1.187 + } 1.188 + } 1.189 + else 1.190 + { 1.191 + pd->out_flags = 0; 1.192 + } 1.193 + } 1.194 + 1.195 + if (0 != ready) 1.196 + { 1.197 +#ifndef BSD_SELECT 1.198 + PR_Free(socks); 1.199 +#endif 1.200 + return ready; /* no need to block */ 1.201 + } 1.202 + 1.203 + remaining = timeout; 1.204 + start = PR_IntervalNow(); 1.205 + 1.206 +retry: 1.207 +#ifdef BSD_SELECT 1.208 + if (timeout != PR_INTERVAL_NO_TIMEOUT) 1.209 + { 1.210 + PRInt32 ticksPerSecond = PR_TicksPerSecond(); 1.211 + tv.tv_sec = remaining / ticksPerSecond; 1.212 + tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); 1.213 + tvp = &tv; 1.214 + } 1.215 + 1.216 + ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp); 1.217 +#else 1.218 + switch (timeout) 1.219 + { 1.220 + case PR_INTERVAL_NO_WAIT: 1.221 + msecs = 0; 1.222 + break; 1.223 + case PR_INTERVAL_NO_TIMEOUT: 1.224 + msecs = -1; 1.225 + break; 1.226 + default: 1.227 + msecs = PR_IntervalToMilliseconds(remaining); 1.228 + } 1.229 + 1.230 + /* compact array */ 1.231 + for( i = rd, j = npds; j < npds+wt; i++,j++ ) 1.232 + socks[i] = socks[j]; 1.233 + for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ ) 1.234 + socks[i] = socks[j]; 1.235 + 1.236 + ready = os2_select(socks, rd, wt, ex, msecs); 1.237 +#endif 1.238 + 1.239 + if (ready == -1 && errno == EINTR) 1.240 + { 1.241 + if (timeout == PR_INTERVAL_NO_TIMEOUT) 1.242 + goto retry; 1.243 + else 1.244 + { 1.245 + elapsed = (PRIntervalTime) (PR_IntervalNow() - start); 1.246 + if (elapsed > timeout) 1.247 + ready = 0; /* timed out */ 1.248 + else 1.249 + { 1.250 + remaining = timeout - elapsed; 1.251 + goto retry; 1.252 + } 1.253 + } 1.254 + } 1.255 + 1.256 + /* 1.257 + ** Now to unravel the select sets back into the client's poll 1.258 + ** descriptor list. Is this possibly an area for pissing away 1.259 + ** a few cycles or what? 1.260 + */ 1.261 + if (ready > 0) 1.262 + { 1.263 + ready = 0; 1.264 + for (pd = pds, epd = pd + npds; pd < epd; pd++) 1.265 + { 1.266 + PRInt16 out_flags = 0; 1.267 + if ((NULL != pd->fd) && (0 != pd->in_flags)) 1.268 + { 1.269 + PRInt32 osfd; 1.270 + bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); 1.271 + PR_ASSERT(NULL != bottom); 1.272 + 1.273 + osfd = bottom->secret->md.osfd; 1.274 + 1.275 +#ifdef BSD_SELECT 1.276 + if (FD_ISSET(osfd, &rd)) 1.277 +#else 1.278 + if( IsSocketSet(osfd, socks, 0, rd) ) 1.279 +#endif 1.280 + { 1.281 + if (pd->out_flags & _PR_POLL_READ_SYS_READ) 1.282 + out_flags |= PR_POLL_READ; 1.283 + if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) 1.284 + out_flags |= PR_POLL_WRITE; 1.285 + } 1.286 + 1.287 +#ifdef BSD_SELECT 1.288 + if (FD_ISSET(osfd, &wt)) 1.289 +#else 1.290 + if( IsSocketSet(osfd, socks, rd, wt) ) 1.291 +#endif 1.292 + { 1.293 + if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) 1.294 + out_flags |= PR_POLL_READ; 1.295 + if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) 1.296 + out_flags |= PR_POLL_WRITE; 1.297 + } 1.298 + 1.299 +#ifdef BSD_SELECT 1.300 + if (FD_ISSET(osfd, &ex)) 1.301 +#else 1.302 + if( IsSocketSet(osfd, socks, rd+wt, ex) ) 1.303 +#endif 1.304 + { 1.305 + out_flags |= PR_POLL_EXCEPT; 1.306 + } 1.307 + } 1.308 + pd->out_flags = out_flags; 1.309 + if (out_flags) ready++; 1.310 + } 1.311 + PR_ASSERT(ready > 0); 1.312 + } 1.313 + else if (ready < 0) 1.314 + { 1.315 + err = _MD_ERRNO(); 1.316 + if (err == EBADF) 1.317 + { 1.318 + /* Find the bad fds */ 1.319 + int optval; 1.320 + int optlen = sizeof(optval); 1.321 + ready = 0; 1.322 + for (pd = pds, epd = pd + npds; pd < epd; pd++) 1.323 + { 1.324 + pd->out_flags = 0; 1.325 + if ((NULL != pd->fd) && (0 != pd->in_flags)) 1.326 + { 1.327 + bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); 1.328 + if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, 1.329 + SO_TYPE, (char *) &optval, &optlen) == -1) 1.330 + { 1.331 + PR_ASSERT(sock_errno() == ENOTSOCK); 1.332 + if (sock_errno() == ENOTSOCK) 1.333 + { 1.334 + pd->out_flags = PR_POLL_NVAL; 1.335 + ready++; 1.336 + } 1.337 + } 1.338 + } 1.339 + } 1.340 + PR_ASSERT(ready > 0); 1.341 + } 1.342 + else 1.343 + _PR_MD_MAP_SELECT_ERROR(err); 1.344 + } 1.345 + 1.346 +#ifndef BSD_SELECT 1.347 + PR_Free(socks); 1.348 +#endif 1.349 + return ready; 1.350 +} 1.351 +