Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/md/unix/uxwrap.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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/. */ | |
5 | |
6 /* | |
7 *------------------------------------------------------------------------ | |
8 * File: uxwrap.c | |
9 * | |
10 * Our wrapped versions of the Unix select() and poll() system calls. | |
11 * | |
12 *------------------------------------------------------------------------ | |
13 */ | |
14 | |
15 #include "primpl.h" | |
16 | |
17 #if defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(QNX) | |
18 /* Do not wrap select() and poll(). */ | |
19 #else /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */ | |
20 /* The include files for select() */ | |
21 #ifdef IRIX | |
22 #include <unistd.h> | |
23 #include <bstring.h> | |
24 #endif | |
25 | |
26 #include <string.h> | |
27 #include <sys/types.h> | |
28 #include <sys/time.h> | |
29 | |
30 #define ZAP_SET(_to, _width) \ | |
31 PR_BEGIN_MACRO \ | |
32 memset(_to, 0, \ | |
33 ((_width + 8*sizeof(int)-1) / (8*sizeof(int))) \ | |
34 * sizeof(int) \ | |
35 ); \ | |
36 PR_END_MACRO | |
37 | |
38 /* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */ | |
39 static int _pr_xt_hack_fd = -1; | |
40 | |
41 int PR_XGetXtHackFD(void) | |
42 { | |
43 int fds[2]; | |
44 | |
45 if (_pr_xt_hack_fd == -1) { | |
46 if (!pipe(fds)) { | |
47 _pr_xt_hack_fd = fds[0]; | |
48 } | |
49 } | |
50 return _pr_xt_hack_fd; | |
51 } | |
52 | |
53 static int (*_pr_xt_hack_okayToReleaseXLock)(void) = 0; | |
54 | |
55 void PR_SetXtHackOkayToReleaseXLockFn(int (*fn)(void)) | |
56 { | |
57 _pr_xt_hack_okayToReleaseXLock = fn; | |
58 } | |
59 | |
60 | |
61 /* | |
62 *----------------------------------------------------------------------- | |
63 * select() -- | |
64 * | |
65 * Wrap up the select system call so that we can deschedule | |
66 * a thread that tries to wait for i/o. | |
67 * | |
68 *----------------------------------------------------------------------- | |
69 */ | |
70 | |
71 #if defined(HPUX9) | |
72 int select(size_t width, int *rl, int *wl, int *el, const struct timeval *tv) | |
73 #elif defined(AIX_RENAME_SELECT) | |
74 int wrap_select(unsigned long width, void *rl, void *wl, void *el, | |
75 struct timeval *tv) | |
76 #elif defined(_PR_SELECT_CONST_TIMEVAL) | |
77 int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, | |
78 const struct timeval *tv) | |
79 #else | |
80 int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv) | |
81 #endif | |
82 { | |
83 int osfd; | |
84 _PRUnixPollDesc *unixpds, *unixpd, *eunixpd; | |
85 PRInt32 pdcnt; | |
86 PRIntervalTime timeout; | |
87 int retVal; | |
88 #if defined(HPUX9) || defined(AIX_RENAME_SELECT) | |
89 fd_set *rd = (fd_set*) rl; | |
90 fd_set *wr = (fd_set*) wl; | |
91 fd_set *ex = (fd_set*) el; | |
92 #endif | |
93 | |
94 #if 0 | |
95 /* | |
96 * Easy special case: zero timeout. Simply call the native | |
97 * select() with no fear of blocking. | |
98 */ | |
99 if (tv != NULL && tv->tv_sec == 0 && tv->tv_usec == 0) { | |
100 #if defined(HPUX9) || defined(AIX_RENAME_SELECT) | |
101 return _MD_SELECT(width, rl, wl, el, tv); | |
102 #else | |
103 return _MD_SELECT(width, rd, wr, ex, tv); | |
104 #endif | |
105 } | |
106 #endif | |
107 | |
108 if (!_pr_initialized) { | |
109 _PR_ImplicitInitialization(); | |
110 } | |
111 | |
112 #ifndef _PR_LOCAL_THREADS_ONLY | |
113 if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) { | |
114 return _MD_SELECT(width, rd, wr, ex, tv); | |
115 } | |
116 #endif | |
117 | |
118 if (width < 0 || width > FD_SETSIZE) { | |
119 errno = EINVAL; | |
120 return -1; | |
121 } | |
122 | |
123 /* Compute timeout */ | |
124 if (tv) { | |
125 /* | |
126 * These acceptable ranges for t_sec and t_usec are taken | |
127 * from the select() man pages. | |
128 */ | |
129 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 | |
130 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) { | |
131 errno = EINVAL; | |
132 return -1; | |
133 } | |
134 | |
135 /* Convert microseconds to ticks */ | |
136 timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec); | |
137 } else { | |
138 /* tv being a NULL pointer means blocking indefinitely */ | |
139 timeout = PR_INTERVAL_NO_TIMEOUT; | |
140 } | |
141 | |
142 /* Check for no descriptors case (just doing a timeout) */ | |
143 if ((!rd && !wr && !ex) || !width) { | |
144 PR_Sleep(timeout); | |
145 return 0; | |
146 } | |
147 | |
148 /* | |
149 * Set up for PR_Poll(). The PRPollDesc array is allocated | |
150 * dynamically. If this turns out to have high performance | |
151 * penalty, one can change to use a large PRPollDesc array | |
152 * on the stack, and allocate dynamically only when it turns | |
153 * out to be not large enough. | |
154 * | |
155 * I allocate an array of size 'width', which is the maximum | |
156 * number of fds we may need to poll. | |
157 */ | |
158 unixpds = (_PRUnixPollDesc *) PR_CALLOC(width * sizeof(_PRUnixPollDesc)); | |
159 if (!unixpds) { | |
160 errno = ENOMEM; | |
161 return -1; | |
162 } | |
163 | |
164 pdcnt = 0; | |
165 unixpd = unixpds; | |
166 for (osfd = 0; osfd < width; osfd++) { | |
167 int in_flags = 0; | |
168 if (rd && FD_ISSET(osfd, rd)) { | |
169 in_flags |= _PR_UNIX_POLL_READ; | |
170 } | |
171 if (wr && FD_ISSET(osfd, wr)) { | |
172 in_flags |= _PR_UNIX_POLL_WRITE; | |
173 } | |
174 if (ex && FD_ISSET(osfd, ex)) { | |
175 in_flags |= _PR_UNIX_POLL_EXCEPT; | |
176 } | |
177 if (in_flags) { | |
178 unixpd->osfd = osfd; | |
179 unixpd->in_flags = in_flags; | |
180 unixpd->out_flags = 0; | |
181 unixpd++; | |
182 pdcnt++; | |
183 } | |
184 } | |
185 | |
186 /* | |
187 * see comments in mozilla/cmd/xfe/mozilla.c (look for | |
188 * "PR_XGetXtHackFD") | |
189 */ | |
190 { | |
191 int needToLockXAgain; | |
192 | |
193 needToLockXAgain = 0; | |
194 if (rd && (_pr_xt_hack_fd != -1) | |
195 && FD_ISSET(_pr_xt_hack_fd, rd) && PR_XIsLocked() | |
196 && (!_pr_xt_hack_okayToReleaseXLock | |
197 || _pr_xt_hack_okayToReleaseXLock())) { | |
198 PR_XUnlock(); | |
199 needToLockXAgain = 1; | |
200 } | |
201 | |
202 /* This is the potentially blocking step */ | |
203 retVal = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout); | |
204 | |
205 if (needToLockXAgain) { | |
206 PR_XLock(); | |
207 } | |
208 } | |
209 | |
210 if (retVal > 0) { | |
211 /* Compute select results */ | |
212 if (rd) ZAP_SET(rd, width); | |
213 if (wr) ZAP_SET(wr, width); | |
214 if (ex) ZAP_SET(ex, width); | |
215 | |
216 /* | |
217 * The return value can be either the number of ready file | |
218 * descriptors or the number of set bits in the three fd_set's. | |
219 */ | |
220 retVal = 0; /* we're going to recompute */ | |
221 eunixpd = unixpds + pdcnt; | |
222 for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { | |
223 if (unixpd->out_flags) { | |
224 int nbits = 0; /* The number of set bits on for this fd */ | |
225 | |
226 if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) { | |
227 errno = EBADF; | |
228 PR_LOG(_pr_io_lm, PR_LOG_ERROR, | |
229 ("select returns EBADF for %d", unixpd->osfd)); | |
230 retVal = -1; | |
231 break; | |
232 } | |
233 /* | |
234 * If a socket has a pending error, it is considered | |
235 * both readable and writable. (See W. Richard Stevens, | |
236 * Unix Network Programming, Vol. 1, 2nd Ed., Section 6.3, | |
237 * pp. 153-154.) We also consider a socket readable if | |
238 * it has a hangup condition. | |
239 */ | |
240 if (rd && (unixpd->in_flags & _PR_UNIX_POLL_READ) | |
241 && (unixpd->out_flags & (_PR_UNIX_POLL_READ | |
242 | _PR_UNIX_POLL_ERR | _PR_UNIX_POLL_HUP))) { | |
243 FD_SET(unixpd->osfd, rd); | |
244 nbits++; | |
245 } | |
246 if (wr && (unixpd->in_flags & _PR_UNIX_POLL_WRITE) | |
247 && (unixpd->out_flags & (_PR_UNIX_POLL_WRITE | |
248 | _PR_UNIX_POLL_ERR))) { | |
249 FD_SET(unixpd->osfd, wr); | |
250 nbits++; | |
251 } | |
252 if (ex && (unixpd->in_flags & _PR_UNIX_POLL_WRITE) | |
253 && (unixpd->out_flags & PR_POLL_EXCEPT)) { | |
254 FD_SET(unixpd->osfd, ex); | |
255 nbits++; | |
256 } | |
257 PR_ASSERT(nbits > 0); | |
258 #if defined(HPUX) || defined(SOLARIS) || defined(OSF1) || defined(AIX) | |
259 retVal += nbits; | |
260 #else /* IRIX */ | |
261 retVal += 1; | |
262 #endif | |
263 } | |
264 } | |
265 } | |
266 | |
267 PR_ASSERT(tv || retVal != 0); | |
268 PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal)); | |
269 PR_DELETE(unixpds); | |
270 | |
271 return retVal; | |
272 } | |
273 | |
274 /* | |
275 * Redefine poll, when supported on platforms, for local threads | |
276 */ | |
277 | |
278 /* | |
279 * I am commenting out the poll() wrapper for Linux for now | |
280 * because it is difficult to define _MD_POLL that works on all | |
281 * Linux varieties. People reported that glibc 2.0.7 on Debian | |
282 * 2.0 Linux machines doesn't have the __syscall_poll symbol | |
283 * defined. (WTC 30 Nov. 1998) | |
284 */ | |
285 #if defined(_PR_POLL_AVAILABLE) && !defined(LINUX) | |
286 | |
287 /* | |
288 *----------------------------------------------------------------------- | |
289 * poll() -- | |
290 * | |
291 * RETURN VALUES: | |
292 * -1: fails, errno indicates the error. | |
293 * 0: timed out, the revents bitmasks are not set. | |
294 * positive value: the number of file descriptors for which poll() | |
295 * has set the revents bitmask. | |
296 * | |
297 *----------------------------------------------------------------------- | |
298 */ | |
299 | |
300 #include <poll.h> | |
301 | |
302 #if defined(AIX_RENAME_SELECT) | |
303 int wrap_poll(void *listptr, unsigned long nfds, long timeout) | |
304 #elif (defined(AIX) && !defined(AIX_RENAME_SELECT)) | |
305 int poll(void *listptr, unsigned long nfds, long timeout) | |
306 #elif defined(OSF1) || (defined(HPUX) && !defined(HPUX9)) | |
307 int poll(struct pollfd filedes[], unsigned int nfds, int timeout) | |
308 #elif defined(HPUX9) | |
309 int poll(struct pollfd filedes[], int nfds, int timeout) | |
310 #elif defined(NETBSD) | |
311 int poll(struct pollfd *filedes, nfds_t nfds, int timeout) | |
312 #elif defined(OPENBSD) | |
313 int poll(struct pollfd filedes[], nfds_t nfds, int timeout) | |
314 #elif defined(FREEBSD) | |
315 int poll(struct pollfd *filedes, unsigned nfds, int timeout) | |
316 #else | |
317 int poll(struct pollfd *filedes, unsigned long nfds, int timeout) | |
318 #endif | |
319 { | |
320 #ifdef AIX | |
321 struct pollfd *filedes = (struct pollfd *) listptr; | |
322 #endif | |
323 struct pollfd *pfd, *epfd; | |
324 _PRUnixPollDesc *unixpds, *unixpd, *eunixpd; | |
325 PRIntervalTime ticks; | |
326 PRInt32 pdcnt; | |
327 int ready; | |
328 | |
329 /* | |
330 * Easy special case: zero timeout. Simply call the native | |
331 * poll() with no fear of blocking. | |
332 */ | |
333 if (timeout == 0) { | |
334 #if defined(AIX) | |
335 return _MD_POLL(listptr, nfds, timeout); | |
336 #else | |
337 return _MD_POLL(filedes, nfds, timeout); | |
338 #endif | |
339 } | |
340 | |
341 if (!_pr_initialized) { | |
342 _PR_ImplicitInitialization(); | |
343 } | |
344 | |
345 #ifndef _PR_LOCAL_THREADS_ONLY | |
346 if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) { | |
347 return _MD_POLL(filedes, nfds, timeout); | |
348 } | |
349 #endif | |
350 | |
351 /* We do not support the pollmsg structures on AIX */ | |
352 #ifdef AIX | |
353 PR_ASSERT((nfds & 0xff00) == 0); | |
354 #endif | |
355 | |
356 if (timeout < 0 && timeout != -1) { | |
357 errno = EINVAL; | |
358 return -1; | |
359 } | |
360 | |
361 /* Convert timeout from miliseconds to ticks */ | |
362 if (timeout == -1) { | |
363 ticks = PR_INTERVAL_NO_TIMEOUT; | |
364 } else { | |
365 ticks = PR_MillisecondsToInterval(timeout); | |
366 } | |
367 | |
368 /* Check for no descriptor case (just do a timeout) */ | |
369 if (nfds == 0) { | |
370 PR_Sleep(ticks); | |
371 return 0; | |
372 } | |
373 | |
374 unixpds = (_PRUnixPollDesc *) | |
375 PR_MALLOC(nfds * sizeof(_PRUnixPollDesc)); | |
376 if (NULL == unixpds) { | |
377 errno = EAGAIN; | |
378 return -1; | |
379 } | |
380 | |
381 pdcnt = 0; | |
382 epfd = filedes + nfds; | |
383 unixpd = unixpds; | |
384 for (pfd = filedes; pfd < epfd; pfd++) { | |
385 /* | |
386 * poll() ignores negative fd's. | |
387 */ | |
388 if (pfd->fd >= 0) { | |
389 unixpd->osfd = pfd->fd; | |
390 #ifdef _PR_USE_POLL | |
391 unixpd->in_flags = pfd->events; | |
392 #else | |
393 /* | |
394 * Map the poll events to one of the three that can be | |
395 * represented by the select fd_sets: | |
396 * POLLIN, POLLRDNORM ===> readable | |
397 * POLLOUT, POLLWRNORM ===> writable | |
398 * POLLPRI, POLLRDBAND ===> exception | |
399 * POLLNORM, POLLWRBAND (and POLLMSG on some platforms) | |
400 * are ignored. | |
401 * | |
402 * The output events POLLERR and POLLHUP are never turned on. | |
403 * POLLNVAL may be turned on. | |
404 */ | |
405 unixpd->in_flags = 0; | |
406 if (pfd->events & (POLLIN | |
407 #ifdef POLLRDNORM | |
408 | POLLRDNORM | |
409 #endif | |
410 )) { | |
411 unixpd->in_flags |= _PR_UNIX_POLL_READ; | |
412 } | |
413 if (pfd->events & (POLLOUT | |
414 #ifdef POLLWRNORM | |
415 | POLLWRNORM | |
416 #endif | |
417 )) { | |
418 unixpd->in_flags |= _PR_UNIX_POLL_WRITE; | |
419 } | |
420 if (pfd->events & (POLLPRI | |
421 #ifdef POLLRDBAND | |
422 | POLLRDBAND | |
423 #endif | |
424 )) { | |
425 unixpd->in_flags |= PR_POLL_EXCEPT; | |
426 } | |
427 #endif /* _PR_USE_POLL */ | |
428 unixpd->out_flags = 0; | |
429 unixpd++; | |
430 pdcnt++; | |
431 } | |
432 } | |
433 | |
434 ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, ticks); | |
435 if (-1 == ready) { | |
436 if (PR_GetError() == PR_PENDING_INTERRUPT_ERROR) { | |
437 errno = EINTR; /* XXX we aren't interrupted by a signal, but... */ | |
438 } else { | |
439 errno = PR_GetOSError(); | |
440 } | |
441 } | |
442 if (ready <= 0) { | |
443 goto done; | |
444 } | |
445 | |
446 /* | |
447 * Copy the out_flags from the _PRUnixPollDesc structures to the | |
448 * user's pollfd structures and free the allocated memory | |
449 */ | |
450 unixpd = unixpds; | |
451 for (pfd = filedes; pfd < epfd; pfd++) { | |
452 pfd->revents = 0; | |
453 if (pfd->fd >= 0) { | |
454 #ifdef _PR_USE_POLL | |
455 pfd->revents = unixpd->out_flags; | |
456 #else | |
457 if (0 != unixpd->out_flags) { | |
458 if (unixpd->out_flags & _PR_UNIX_POLL_READ) { | |
459 if (pfd->events & POLLIN) { | |
460 pfd->revents |= POLLIN; | |
461 } | |
462 #ifdef POLLRDNORM | |
463 if (pfd->events & POLLRDNORM) { | |
464 pfd->revents |= POLLRDNORM; | |
465 } | |
466 #endif | |
467 } | |
468 if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) { | |
469 if (pfd->events & POLLOUT) { | |
470 pfd->revents |= POLLOUT; | |
471 } | |
472 #ifdef POLLWRNORM | |
473 if (pfd->events & POLLWRNORM) { | |
474 pfd->revents |= POLLWRNORM; | |
475 } | |
476 #endif | |
477 } | |
478 if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) { | |
479 if (pfd->events & POLLPRI) { | |
480 pfd->revents |= POLLPRI; | |
481 } | |
482 #ifdef POLLRDBAND | |
483 if (pfd->events & POLLRDBAND) { | |
484 pfd->revents |= POLLRDBAND; | |
485 } | |
486 #endif | |
487 } | |
488 if (unixpd->out_flags & _PR_UNIX_POLL_ERR) { | |
489 pfd->revents |= POLLERR; | |
490 } | |
491 if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) { | |
492 pfd->revents |= POLLNVAL; | |
493 } | |
494 if (unixpd->out_flags & _PR_UNIX_POLL_HUP) { | |
495 pfd->revents |= POLLHUP; | |
496 } | |
497 } | |
498 #endif /* _PR_USE_POLL */ | |
499 unixpd++; | |
500 } | |
501 } | |
502 | |
503 done: | |
504 PR_DELETE(unixpds); | |
505 return ready; | |
506 } | |
507 | |
508 #endif /* !defined(LINUX) */ | |
509 | |
510 #endif /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */ | |
511 | |
512 /* uxwrap.c */ | |
513 |