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