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 #include "primpl.h"
7 
8 #include <string.h>
9 #include <signal.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 #include <sys/ioctl.h>
16 #include <sys/mman.h>
17 #include <unistd.h>
18 #include <sys/utsname.h>
19 
20 #ifdef _PR_POLL_AVAILABLE
21 #include <poll.h>
22 #endif
23 
24 #if defined(ANDROID)
25 #include <android/api-level.h>
26 #endif
27 
28 /* To get FIONREAD */
29 #if defined(UNIXWARE)
30 #include <sys/filio.h>
31 #endif
32 
33 #if defined(NTO)
34 #include <sys/statvfs.h>
35 #endif
36 
37 /*
38  * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
39  * PRInt32* pointer to a _PRSockLen_t* pointer.
40  */
41 #if defined(HAVE_SOCKLEN_T) \
42     || (defined(__GLIBC__) && __GLIBC__ >= 2)
43 #define _PRSockLen_t socklen_t
44 #elif defined(HPUX) || defined(SOLARIS) \
45     || defined(AIX4_1) || defined(LINUX) \
46     || defined(BSDI) || defined(SCO) \
47     || defined(DARWIN) \
48     || defined(QNX)
49 #define _PRSockLen_t int
50 #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
51     || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) \
52     || defined(NTO) || defined(RISCOS)
53 #define _PRSockLen_t size_t
54 #else
55 #error "Cannot determine architecture"
56 #endif
57 
58 /*
59 ** Global lock variable used to bracket calls into rusty libraries that
60 ** aren't thread safe (like libc, libX, etc).
61 */
62 static PRLock *_pr_unix_rename_lock = NULL;
63 static PRMonitor *_pr_Xfe_mon = NULL;
64 
65 static PRInt64 minus_one;
66 
67 sigset_t timer_set;
68 
69 #if !defined(_PR_PTHREADS)
70 
71 static sigset_t empty_set;
72 
73 #ifdef SOLARIS
74 #include <sys/file.h>
75 #include <sys/filio.h>
76 #endif
77 
78 #ifndef PIPE_BUF
79 #define PIPE_BUF 512
80 #endif
81 
82 /*
83  * _nspr_noclock - if set clock interrupts are disabled
84  */
85 int _nspr_noclock = 1;
86 
87 /*
88  * There is an assertion in this code that NSPR's definition of PRIOVec
89  * is bit compatible with UNIX' definition of a struct iovec. This is
90  * applicable to the 'writev()' operations where the types are casually
91  * cast to avoid warnings.
92  */
93 
94 int _pr_md_pipefd[2] = { -1, -1 };
95 static char _pr_md_pipebuf[PIPE_BUF];
96 static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag,
97                              PRIntervalTime timeout);
98 
99 _PRInterruptTable _pr_interruptTable[] = {
100     {
101         "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt,
102     },
103     {
104         0
105     }
106 };
107 
_MD_unix_init_running_cpu(_PRCPU * cpu)108 void _MD_unix_init_running_cpu(_PRCPU *cpu)
109 {
110     PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));
111     cpu->md.md_unix.ioq_max_osfd = -1;
112     cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
113 }
114 
_MD_open_dir(_MDDir * d,const char * name)115 PRStatus _MD_open_dir(_MDDir *d, const char *name)
116 {
117     int err;
118 
119     d->d = opendir(name);
120     if (!d->d) {
121         err = _MD_ERRNO();
122         _PR_MD_MAP_OPENDIR_ERROR(err);
123         return PR_FAILURE;
124     }
125     return PR_SUCCESS;
126 }
127 
_MD_close_dir(_MDDir * d)128 PRInt32 _MD_close_dir(_MDDir *d)
129 {
130     int rv = 0, err;
131 
132     if (d->d) {
133         rv = closedir(d->d);
134         if (rv == -1) {
135             err = _MD_ERRNO();
136             _PR_MD_MAP_CLOSEDIR_ERROR(err);
137         }
138     }
139     return rv;
140 }
141 
_MD_read_dir(_MDDir * d,PRIntn flags)142 char * _MD_read_dir(_MDDir *d, PRIntn flags)
143 {
144     struct dirent *de;
145     int err;
146 
147     for (;;) {
148         /*
149           * XXX: readdir() is not MT-safe. There is an MT-safe version
150           * readdir_r() on some systems.
151           */
152         _MD_ERRNO() = 0;
153         de = readdir(d->d);
154         if (!de) {
155             err = _MD_ERRNO();
156             _PR_MD_MAP_READDIR_ERROR(err);
157             return 0;
158         }
159         if ((flags & PR_SKIP_DOT) &&
160             (de->d_name[0] == '.') && (de->d_name[1] == 0)) {
161             continue;
162         }
163         if ((flags & PR_SKIP_DOT_DOT) &&
164             (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
165             (de->d_name[2] == 0)) {
166             continue;
167         }
168         if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.')) {
169             continue;
170         }
171         break;
172     }
173     return de->d_name;
174 }
175 
_MD_delete(const char * name)176 PRInt32 _MD_delete(const char *name)
177 {
178     PRInt32 rv, err;
179 #ifdef UNIXWARE
180     sigset_t set, oset;
181 #endif
182 
183 #ifdef UNIXWARE
184     sigfillset(&set);
185     sigprocmask(SIG_SETMASK, &set, &oset);
186 #endif
187     rv = unlink(name);
188 #ifdef UNIXWARE
189     sigprocmask(SIG_SETMASK, &oset, NULL);
190 #endif
191     if (rv == -1) {
192         err = _MD_ERRNO();
193         _PR_MD_MAP_UNLINK_ERROR(err);
194     }
195     return(rv);
196 }
197 
_MD_rename(const char * from,const char * to)198 PRInt32 _MD_rename(const char *from, const char *to)
199 {
200     PRInt32 rv = -1, err;
201 
202     /*
203     ** This is trying to enforce the semantics of WINDOZE' rename
204     ** operation. That means one is not allowed to rename over top
205     ** of an existing file. Holding a lock across these two function
206     ** and the open function is known to be a bad idea, but ....
207     */
208     if (NULL != _pr_unix_rename_lock) {
209         PR_Lock(_pr_unix_rename_lock);
210     }
211     if (0 == access(to, F_OK)) {
212         PR_SetError(PR_FILE_EXISTS_ERROR, 0);
213     }
214     else
215     {
216         rv = rename(from, to);
217         if (rv < 0) {
218             err = _MD_ERRNO();
219             _PR_MD_MAP_RENAME_ERROR(err);
220         }
221     }
222     if (NULL != _pr_unix_rename_lock) {
223         PR_Unlock(_pr_unix_rename_lock);
224     }
225     return rv;
226 }
227 
_MD_access(const char * name,PRAccessHow how)228 PRInt32 _MD_access(const char *name, PRAccessHow how)
229 {
230     PRInt32 rv, err;
231     int amode;
232 
233     switch (how) {
234         case PR_ACCESS_WRITE_OK:
235             amode = W_OK;
236             break;
237         case PR_ACCESS_READ_OK:
238             amode = R_OK;
239             break;
240         case PR_ACCESS_EXISTS:
241             amode = F_OK;
242             break;
243         default:
244             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
245             rv = -1;
246             goto done;
247     }
248     rv = access(name, amode);
249 
250     if (rv < 0) {
251         err = _MD_ERRNO();
252         _PR_MD_MAP_ACCESS_ERROR(err);
253     }
254 
255 done:
256     return(rv);
257 }
258 
_MD_mkdir(const char * name,PRIntn mode)259 PRInt32 _MD_mkdir(const char *name, PRIntn mode)
260 {
261     int rv, err;
262 
263     /*
264     ** This lock is used to enforce rename semantics as described
265     ** in PR_Rename. Look there for more fun details.
266     */
267     if (NULL !=_pr_unix_rename_lock) {
268         PR_Lock(_pr_unix_rename_lock);
269     }
270     rv = mkdir(name, mode);
271     if (rv < 0) {
272         err = _MD_ERRNO();
273         _PR_MD_MAP_MKDIR_ERROR(err);
274     }
275     if (NULL !=_pr_unix_rename_lock) {
276         PR_Unlock(_pr_unix_rename_lock);
277     }
278     return rv;
279 }
280 
_MD_rmdir(const char * name)281 PRInt32 _MD_rmdir(const char *name)
282 {
283     int rv, err;
284 
285     rv = rmdir(name);
286     if (rv == -1) {
287         err = _MD_ERRNO();
288         _PR_MD_MAP_RMDIR_ERROR(err);
289     }
290     return rv;
291 }
292 
_MD_read(PRFileDesc * fd,void * buf,PRInt32 amount)293 PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)
294 {
295     PRThread *me = _PR_MD_CURRENT_THREAD();
296     PRInt32 rv, err;
297 #ifndef _PR_USE_POLL
298     fd_set rd;
299 #else
300     struct pollfd pfd;
301 #endif /* _PR_USE_POLL */
302     PRInt32 osfd = fd->secret->md.osfd;
303 
304 #ifndef _PR_USE_POLL
305     FD_ZERO(&rd);
306     FD_SET(osfd, &rd);
307 #else
308     pfd.fd = osfd;
309     pfd.events = POLLIN;
310 #endif /* _PR_USE_POLL */
311     while ((rv = read(osfd,buf,amount)) == -1) {
312         err = _MD_ERRNO();
313         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
314             if (fd->secret->nonblocking) {
315                 break;
316             }
317             if (!_PR_IS_NATIVE_THREAD(me)) {
318                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ,
319                                         PR_INTERVAL_NO_TIMEOUT)) < 0) {
320                     goto done;
321                 }
322             } else {
323 #ifndef _PR_USE_POLL
324                 while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
325                        == -1 && (err = _MD_ERRNO()) == EINTR) {
326                     /* retry _MD_SELECT() if it is interrupted */
327                 }
328 #else /* _PR_USE_POLL */
329                 while ((rv = _MD_POLL(&pfd, 1, -1))
330                        == -1 && (err = _MD_ERRNO()) == EINTR) {
331                     /* retry _MD_POLL() if it is interrupted */
332                 }
333 #endif /* _PR_USE_POLL */
334                 if (rv == -1) {
335                     break;
336                 }
337             }
338             if (_PR_PENDING_INTERRUPT(me)) {
339                 break;
340             }
341         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
342             continue;
343         } else {
344             break;
345         }
346     }
347     if (rv < 0) {
348         if (_PR_PENDING_INTERRUPT(me)) {
349             me->flags &= ~_PR_INTERRUPT;
350             PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
351         } else {
352             _PR_MD_MAP_READ_ERROR(err);
353         }
354     }
355 done:
356     return(rv);
357 }
358 
_MD_write(PRFileDesc * fd,const void * buf,PRInt32 amount)359 PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
360 {
361     PRThread *me = _PR_MD_CURRENT_THREAD();
362     PRInt32 rv, err;
363 #ifndef _PR_USE_POLL
364     fd_set wd;
365 #else
366     struct pollfd pfd;
367 #endif /* _PR_USE_POLL */
368     PRInt32 osfd = fd->secret->md.osfd;
369 
370 #ifndef _PR_USE_POLL
371     FD_ZERO(&wd);
372     FD_SET(osfd, &wd);
373 #else
374     pfd.fd = osfd;
375     pfd.events = POLLOUT;
376 #endif /* _PR_USE_POLL */
377     while ((rv = write(osfd,buf,amount)) == -1) {
378         err = _MD_ERRNO();
379         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
380             if (fd->secret->nonblocking) {
381                 break;
382             }
383             if (!_PR_IS_NATIVE_THREAD(me)) {
384                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE,
385                                         PR_INTERVAL_NO_TIMEOUT)) < 0) {
386                     goto done;
387                 }
388             } else {
389 #ifndef _PR_USE_POLL
390                 while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
391                        == -1 && (err = _MD_ERRNO()) == EINTR) {
392                     /* retry _MD_SELECT() if it is interrupted */
393                 }
394 #else /* _PR_USE_POLL */
395                 while ((rv = _MD_POLL(&pfd, 1, -1))
396                        == -1 && (err = _MD_ERRNO()) == EINTR) {
397                     /* retry _MD_POLL() if it is interrupted */
398                 }
399 #endif /* _PR_USE_POLL */
400                 if (rv == -1) {
401                     break;
402                 }
403             }
404             if (_PR_PENDING_INTERRUPT(me)) {
405                 break;
406             }
407         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
408             continue;
409         } else {
410             break;
411         }
412     }
413     if (rv < 0) {
414         if (_PR_PENDING_INTERRUPT(me)) {
415             me->flags &= ~_PR_INTERRUPT;
416             PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
417         } else {
418             _PR_MD_MAP_WRITE_ERROR(err);
419         }
420     }
421 done:
422     return(rv);
423 }
424 
_MD_fsync(PRFileDesc * fd)425 PRInt32 _MD_fsync(PRFileDesc *fd)
426 {
427     PRInt32 rv, err;
428 
429     rv = fsync(fd->secret->md.osfd);
430     if (rv == -1) {
431         err = _MD_ERRNO();
432         _PR_MD_MAP_FSYNC_ERROR(err);
433     }
434     return(rv);
435 }
436 
_MD_close(PRInt32 osfd)437 PRInt32 _MD_close(PRInt32 osfd)
438 {
439     PRInt32 rv, err;
440 
441     rv = close(osfd);
442     if (rv == -1) {
443         err = _MD_ERRNO();
444         _PR_MD_MAP_CLOSE_ERROR(err);
445     }
446     return(rv);
447 }
448 
_MD_socket(PRInt32 domain,PRInt32 type,PRInt32 proto)449 PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
450 {
451     PRInt32 osfd, err;
452 
453     osfd = socket(domain, type, proto);
454 
455     if (osfd == -1) {
456         err = _MD_ERRNO();
457         _PR_MD_MAP_SOCKET_ERROR(err);
458         return(osfd);
459     }
460 
461     return(osfd);
462 }
463 
_MD_socketavailable(PRFileDesc * fd)464 PRInt32 _MD_socketavailable(PRFileDesc *fd)
465 {
466     PRInt32 result;
467 
468     if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
469         _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
470         return -1;
471     }
472     return result;
473 }
474 
_MD_socketavailable64(PRFileDesc * fd)475 PRInt64 _MD_socketavailable64(PRFileDesc *fd)
476 {
477     PRInt64 result;
478     LL_I2L(result, _MD_socketavailable(fd));
479     return result;
480 }  /* _MD_socketavailable64 */
481 
482 #define READ_FD        1
483 #define WRITE_FD    2
484 
485 /*
486  * socket_io_wait --
487  *
488  * wait for socket i/o, periodically checking for interrupt
489  *
490  * The first implementation uses select(), for platforms without
491  * poll().  The second (preferred) implementation uses poll().
492  */
493 
494 #ifndef _PR_USE_POLL
495 
socket_io_wait(PRInt32 osfd,PRInt32 fd_type,PRIntervalTime timeout)496 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
497                               PRIntervalTime timeout)
498 {
499     PRInt32 rv = -1;
500     struct timeval tv;
501     PRThread *me = _PR_MD_CURRENT_THREAD();
502     PRIntervalTime epoch, now, elapsed, remaining;
503     PRBool wait_for_remaining;
504     PRInt32 syserror;
505     fd_set rd_wr;
506 
507     switch (timeout) {
508         case PR_INTERVAL_NO_WAIT:
509             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
510             break;
511         case PR_INTERVAL_NO_TIMEOUT:
512             /*
513              * This is a special case of the 'default' case below.
514              * Please see the comments there.
515              */
516             tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
517             tv.tv_usec = 0;
518             FD_ZERO(&rd_wr);
519             do {
520                 FD_SET(osfd, &rd_wr);
521                 if (fd_type == READ_FD) {
522                     rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
523                 }
524                 else {
525                     rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
526                 }
527                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
528                     _PR_MD_MAP_SELECT_ERROR(syserror);
529                     break;
530                 }
531                 if (_PR_PENDING_INTERRUPT(me)) {
532                     me->flags &= ~_PR_INTERRUPT;
533                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
534                     rv = -1;
535                     break;
536                 }
537             } while (rv == 0 || (rv == -1 && syserror == EINTR));
538             break;
539         default:
540             now = epoch = PR_IntervalNow();
541             remaining = timeout;
542             FD_ZERO(&rd_wr);
543             do {
544                 /*
545                  * We block in _MD_SELECT for at most
546                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
547                  * so that there is an upper limit on the delay
548                  * before the interrupt bit is checked.
549                  */
550                 wait_for_remaining = PR_TRUE;
551                 tv.tv_sec = PR_IntervalToSeconds(remaining);
552                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
553                     wait_for_remaining = PR_FALSE;
554                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
555                     tv.tv_usec = 0;
556                 } else {
557                     tv.tv_usec = PR_IntervalToMicroseconds(
558                                      remaining -
559                                      PR_SecondsToInterval(tv.tv_sec));
560                 }
561                 FD_SET(osfd, &rd_wr);
562                 if (fd_type == READ_FD) {
563                     rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
564                 }
565                 else {
566                     rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
567                 }
568                 /*
569                  * we don't consider EINTR a real error
570                  */
571                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
572                     _PR_MD_MAP_SELECT_ERROR(syserror);
573                     break;
574                 }
575                 if (_PR_PENDING_INTERRUPT(me)) {
576                     me->flags &= ~_PR_INTERRUPT;
577                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
578                     rv = -1;
579                     break;
580                 }
581                 /*
582                  * We loop again if _MD_SELECT timed out or got interrupted
583                  * by a signal, and the timeout deadline has not passed yet.
584                  */
585                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
586                     /*
587                      * If _MD_SELECT timed out, we know how much time
588                      * we spent in blocking, so we can avoid a
589                      * PR_IntervalNow() call.
590                      */
591                     if (rv == 0) {
592                         if (wait_for_remaining) {
593                             now += remaining;
594                         } else {
595                             now += PR_SecondsToInterval(tv.tv_sec)
596                                    + PR_MicrosecondsToInterval(tv.tv_usec);
597                         }
598                     } else {
599                         now = PR_IntervalNow();
600                     }
601                     elapsed = (PRIntervalTime) (now - epoch);
602                     if (elapsed >= timeout) {
603                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
604                         rv = -1;
605                         break;
606                     } else {
607                         remaining = timeout - elapsed;
608                     }
609                 }
610             } while (rv == 0 || (rv == -1 && syserror == EINTR));
611             break;
612     }
613     return(rv);
614 }
615 
616 #else /* _PR_USE_POLL */
617 
socket_io_wait(PRInt32 osfd,PRInt32 fd_type,PRIntervalTime timeout)618 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
619                               PRIntervalTime timeout)
620 {
621     PRInt32 rv = -1;
622     int msecs;
623     PRThread *me = _PR_MD_CURRENT_THREAD();
624     PRIntervalTime epoch, now, elapsed, remaining;
625     PRBool wait_for_remaining;
626     PRInt32 syserror;
627     struct pollfd pfd;
628 
629     switch (timeout) {
630         case PR_INTERVAL_NO_WAIT:
631             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
632             break;
633         case PR_INTERVAL_NO_TIMEOUT:
634             /*
635              * This is a special case of the 'default' case below.
636              * Please see the comments there.
637              */
638             msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
639             pfd.fd = osfd;
640             if (fd_type == READ_FD) {
641                 pfd.events = POLLIN;
642             } else {
643                 pfd.events = POLLOUT;
644             }
645             do {
646                 rv = _MD_POLL(&pfd, 1, msecs);
647                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
648                     _PR_MD_MAP_POLL_ERROR(syserror);
649                     break;
650                 }
651                 /*
652                  * If POLLERR is set, don't process it; retry the operation
653                  */
654                 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
655                     rv = -1;
656                     _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
657                     break;
658                 }
659                 if (_PR_PENDING_INTERRUPT(me)) {
660                     me->flags &= ~_PR_INTERRUPT;
661                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
662                     rv = -1;
663                     break;
664                 }
665             } while (rv == 0 || (rv == -1 && syserror == EINTR));
666             break;
667         default:
668             now = epoch = PR_IntervalNow();
669             remaining = timeout;
670             pfd.fd = osfd;
671             if (fd_type == READ_FD) {
672                 pfd.events = POLLIN;
673             } else {
674                 pfd.events = POLLOUT;
675             }
676             do {
677                 /*
678                  * We block in _MD_POLL for at most
679                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
680                  * so that there is an upper limit on the delay
681                  * before the interrupt bit is checked.
682                  */
683                 wait_for_remaining = PR_TRUE;
684                 msecs = PR_IntervalToMilliseconds(remaining);
685                 if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
686                     wait_for_remaining = PR_FALSE;
687                     msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
688                 }
689                 rv = _MD_POLL(&pfd, 1, msecs);
690                 /*
691                  * we don't consider EINTR a real error
692                  */
693                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
694                     _PR_MD_MAP_POLL_ERROR(syserror);
695                     break;
696                 }
697                 if (_PR_PENDING_INTERRUPT(me)) {
698                     me->flags &= ~_PR_INTERRUPT;
699                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
700                     rv = -1;
701                     break;
702                 }
703                 /*
704                  * If POLLERR is set, don't process it; retry the operation
705                  */
706                 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
707                     rv = -1;
708                     _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
709                     break;
710                 }
711                 /*
712                  * We loop again if _MD_POLL timed out or got interrupted
713                  * by a signal, and the timeout deadline has not passed yet.
714                  */
715                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
716                     /*
717                      * If _MD_POLL timed out, we know how much time
718                      * we spent in blocking, so we can avoid a
719                      * PR_IntervalNow() call.
720                      */
721                     if (rv == 0) {
722                         if (wait_for_remaining) {
723                             now += remaining;
724                         } else {
725                             now += PR_MillisecondsToInterval(msecs);
726                         }
727                     } else {
728                         now = PR_IntervalNow();
729                     }
730                     elapsed = (PRIntervalTime) (now - epoch);
731                     if (elapsed >= timeout) {
732                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
733                         rv = -1;
734                         break;
735                     } else {
736                         remaining = timeout - elapsed;
737                     }
738                 }
739             } while (rv == 0 || (rv == -1 && syserror == EINTR));
740             break;
741     }
742     return(rv);
743 }
744 
745 #endif /* _PR_USE_POLL */
746 
local_io_wait(PRInt32 osfd,PRInt32 wait_flag,PRIntervalTime timeout)747 static PRInt32 local_io_wait(
748     PRInt32 osfd,
749     PRInt32 wait_flag,
750     PRIntervalTime timeout)
751 {
752     _PRUnixPollDesc pd;
753     PRInt32 rv;
754 
755     PR_LOG(_pr_io_lm, PR_LOG_MIN,
756            ("waiting to %s on osfd=%d",
757             (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write",
758             osfd));
759 
760     if (timeout == PR_INTERVAL_NO_WAIT) {
761         return 0;
762     }
763 
764     pd.osfd = osfd;
765     pd.in_flags = wait_flag;
766     pd.out_flags = 0;
767 
768     rv = _PR_WaitForMultipleFDs(&pd, 1, timeout);
769 
770     if (rv == 0) {
771         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
772         rv = -1;
773     }
774     return rv;
775 }
776 
777 
_MD_recv(PRFileDesc * fd,void * buf,PRInt32 amount,PRInt32 flags,PRIntervalTime timeout)778 PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
779                  PRInt32 flags, PRIntervalTime timeout)
780 {
781     PRInt32 osfd = fd->secret->md.osfd;
782     PRInt32 rv, err;
783     PRThread *me = _PR_MD_CURRENT_THREAD();
784 
785     /*
786      * Many OS's (Solaris, Unixware) have a broken recv which won't read
787      * from socketpairs.  As long as we don't use flags on socketpairs, this
788      * is a decent fix. - mikep
789      */
790 #if defined(UNIXWARE) || defined(SOLARIS)
791     while ((rv = read(osfd,buf,amount)) == -1) {
792 #else
793     while ((rv = recv(osfd,buf,amount,flags)) == -1) {
794 #endif
795         err = _MD_ERRNO();
796         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
797             if (fd->secret->nonblocking) {
798                 break;
799             }
800             if (!_PR_IS_NATIVE_THREAD(me)) {
801                 if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0) {
802                     goto done;
803                 }
804             } else {
805                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) {
806                     goto done;
807                 }
808             }
809         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
810             continue;
811         } else {
812             break;
813         }
814     }
815     if (rv < 0) {
816         _PR_MD_MAP_RECV_ERROR(err);
817     }
818 done:
819     return(rv);
820 }
821 
822 PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
823                      PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
824                      PRIntervalTime timeout)
825 {
826     PRInt32 osfd = fd->secret->md.osfd;
827     PRInt32 rv, err;
828     PRThread *me = _PR_MD_CURRENT_THREAD();
829 
830     while ((*addrlen = PR_NETADDR_SIZE(addr)),
831            ((rv = recvfrom(osfd, buf, amount, flags,
832                            (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {
833         err = _MD_ERRNO();
834         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
835             if (fd->secret->nonblocking) {
836                 break;
837             }
838             if (!_PR_IS_NATIVE_THREAD(me)) {
839                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) {
840                     goto done;
841                 }
842             } else {
843                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) {
844                     goto done;
845                 }
846             }
847         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
848             continue;
849         } else {
850             break;
851         }
852     }
853     if (rv < 0) {
854         _PR_MD_MAP_RECVFROM_ERROR(err);
855     }
856 done:
857 #ifdef _PR_HAVE_SOCKADDR_LEN
858     if (rv != -1) {
859         /* ignore the sa_len field of struct sockaddr */
860         if (addr) {
861             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
862         }
863     }
864 #endif /* _PR_HAVE_SOCKADDR_LEN */
865     return(rv);
866 }
867 
868 PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
869                  PRInt32 flags, PRIntervalTime timeout)
870 {
871     PRInt32 osfd = fd->secret->md.osfd;
872     PRInt32 rv, err;
873     PRThread *me = _PR_MD_CURRENT_THREAD();
874 #if defined(SOLARIS)
875     PRInt32 tmp_amount = amount;
876 #endif
877 
878     /*
879      * On pre-2.6 Solaris, send() is much slower than write().
880      * On 2.6 and beyond, with in-kernel sockets, send() and
881      * write() are fairly equivalent in performance.
882      */
883 #if defined(SOLARIS)
884     PR_ASSERT(0 == flags);
885     while ((rv = write(osfd,buf,tmp_amount)) == -1) {
886 #else
887     while ((rv = send(osfd,buf,amount,flags)) == -1) {
888 #endif
889         err = _MD_ERRNO();
890         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
891             if (fd->secret->nonblocking) {
892                 break;
893             }
894             if (!_PR_IS_NATIVE_THREAD(me)) {
895                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) {
896                     goto done;
897                 }
898             } else {
899                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) {
900                     goto done;
901                 }
902             }
903         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
904             continue;
905         } else {
906 #if defined(SOLARIS)
907             /*
908              * The write system call has been reported to return the ERANGE
909              * error on occasion. Try to write in smaller chunks to workaround
910              * this bug.
911              */
912             if (err == ERANGE) {
913                 if (tmp_amount > 1) {
914                     tmp_amount = tmp_amount/2;  /* half the bytes */
915                     continue;
916                 }
917             }
918 #endif
919             break;
920         }
921     }
922     /*
923      * optimization; if bytes sent is less than "amount" call
924      * select before returning. This is because it is likely that
925      * the next send() call will return EWOULDBLOCK.
926      */
927     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
928         && (timeout != PR_INTERVAL_NO_WAIT)) {
929         if (_PR_IS_NATIVE_THREAD(me)) {
930             if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
931                 rv = -1;
932                 goto done;
933             }
934         } else {
935             if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
936                 rv = -1;
937                 goto done;
938             }
939         }
940     }
941     if (rv < 0) {
942         _PR_MD_MAP_SEND_ERROR(err);
943     }
944 done:
945     return(rv);
946 }
947 
948 PRInt32 _MD_sendto(
949     PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
950     const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
951 {
952     PRInt32 osfd = fd->secret->md.osfd;
953     PRInt32 rv, err;
954     PRThread *me = _PR_MD_CURRENT_THREAD();
955 #ifdef _PR_HAVE_SOCKADDR_LEN
956     PRNetAddr addrCopy;
957 
958     addrCopy = *addr;
959     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
960     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
961 
962     while ((rv = sendto(osfd, buf, amount, flags,
963                         (struct sockaddr *) &addrCopy, addrlen)) == -1) {
964 #else
965     while ((rv = sendto(osfd, buf, amount, flags,
966                         (struct sockaddr *) addr, addrlen)) == -1) {
967 #endif
968         err = _MD_ERRNO();
969         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
970             if (fd->secret->nonblocking) {
971                 break;
972             }
973             if (!_PR_IS_NATIVE_THREAD(me)) {
974                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) {
975                     goto done;
976                 }
977             } else {
978                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) {
979                     goto done;
980                 }
981             }
982         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
983             continue;
984         } else {
985             break;
986         }
987     }
988     if (rv < 0) {
989         _PR_MD_MAP_SENDTO_ERROR(err);
990     }
991 done:
992     return(rv);
993 }
994 
995 PRInt32 _MD_writev(
996     PRFileDesc *fd, const PRIOVec *iov,
997     PRInt32 iov_size, PRIntervalTime timeout)
998 {
999     PRInt32 rv, err;
1000     PRThread *me = _PR_MD_CURRENT_THREAD();
1001     PRInt32 index, amount = 0;
1002     PRInt32 osfd = fd->secret->md.osfd;
1003 
1004     /*
1005      * Calculate the total number of bytes to be sent; needed for
1006      * optimization later.
1007      * We could avoid this if this number was passed in; but it is
1008      * probably not a big deal because iov_size is usually small (less than
1009      * 3)
1010      */
1011     if (!fd->secret->nonblocking) {
1012         for (index=0; index<iov_size; index++) {
1013             amount += iov[index].iov_len;
1014         }
1015     }
1016 
1017     while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
1018         err = _MD_ERRNO();
1019         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
1020             if (fd->secret->nonblocking) {
1021                 break;
1022             }
1023             if (!_PR_IS_NATIVE_THREAD(me)) {
1024                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) {
1025                     goto done;
1026                 }
1027             } else {
1028                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) {
1029                     goto done;
1030                 }
1031             }
1032         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
1033             continue;
1034         } else {
1035             break;
1036         }
1037     }
1038     /*
1039      * optimization; if bytes sent is less than "amount" call
1040      * select before returning. This is because it is likely that
1041      * the next writev() call will return EWOULDBLOCK.
1042      */
1043     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
1044         && (timeout != PR_INTERVAL_NO_WAIT)) {
1045         if (_PR_IS_NATIVE_THREAD(me)) {
1046             if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
1047                 rv = -1;
1048                 goto done;
1049             }
1050         } else {
1051             if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
1052                 rv = -1;
1053                 goto done;
1054             }
1055         }
1056     }
1057     if (rv < 0) {
1058         _PR_MD_MAP_WRITEV_ERROR(err);
1059     }
1060 done:
1061     return(rv);
1062 }
1063 
1064 PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr,
1065                    PRUint32 *addrlen, PRIntervalTime timeout)
1066 {
1067     PRInt32 osfd = fd->secret->md.osfd;
1068     PRInt32 rv, err;
1069     PRThread *me = _PR_MD_CURRENT_THREAD();
1070 
1071     while ((rv = accept(osfd, (struct sockaddr *) addr,
1072                         (_PRSockLen_t *)addrlen)) == -1) {
1073         err = _MD_ERRNO();
1074         if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) {
1075             if (fd->secret->nonblocking) {
1076                 break;
1077             }
1078             if (!_PR_IS_NATIVE_THREAD(me)) {
1079                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) {
1080                     goto done;
1081                 }
1082             } else {
1083                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) {
1084                     goto done;
1085                 }
1086             }
1087         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
1088             continue;
1089         } else {
1090             break;
1091         }
1092     }
1093     if (rv < 0) {
1094         _PR_MD_MAP_ACCEPT_ERROR(err);
1095     }
1096 done:
1097 #ifdef _PR_HAVE_SOCKADDR_LEN
1098     if (rv != -1) {
1099         /* ignore the sa_len field of struct sockaddr */
1100         if (addr) {
1101             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
1102         }
1103     }
1104 #endif /* _PR_HAVE_SOCKADDR_LEN */
1105     return(rv);
1106 }
1107 
1108 extern int _connect (int s, const struct sockaddr *name, int namelen);
1109 PRInt32 _MD_connect(
1110     PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
1111 {
1112     PRInt32 rv, err;
1113     PRThread *me = _PR_MD_CURRENT_THREAD();
1114     PRInt32 osfd = fd->secret->md.osfd;
1115 #ifdef _PR_HAVE_SOCKADDR_LEN
1116     PRNetAddr addrCopy;
1117 
1118     addrCopy = *addr;
1119     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
1120     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
1121 #endif
1122 
1123     /*
1124      * We initiate the connection setup by making a nonblocking connect()
1125      * call.  If the connect() call fails, there are two cases we handle
1126      * specially:
1127      * 1. The connect() call was interrupted by a signal.  In this case
1128      *    we simply retry connect().
1129      * 2. The NSPR socket is nonblocking and connect() fails with
1130      *    EINPROGRESS.  We first wait until the socket becomes writable.
1131      *    Then we try to find out whether the connection setup succeeded
1132      *    or failed.
1133      */
1134 
1135 retry:
1136 #ifdef _PR_HAVE_SOCKADDR_LEN
1137     if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
1138 #else
1139     if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
1140 #endif
1141         err = _MD_ERRNO();
1142 
1143         if (err == EINTR) {
1144             if (_PR_PENDING_INTERRUPT(me)) {
1145                 me->flags &= ~_PR_INTERRUPT;
1146                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
1147                 return -1;
1148             }
1149             goto retry;
1150         }
1151 
1152         if (!fd->secret->nonblocking && (err == EINPROGRESS)) {
1153             if (!_PR_IS_NATIVE_THREAD(me)) {
1154 
1155                 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) {
1156                     return -1;
1157                 }
1158             } else {
1159                 /*
1160                  * socket_io_wait() may return -1 or 1.
1161                  */
1162 
1163                 rv = socket_io_wait(osfd, WRITE_FD, timeout);
1164                 if (rv == -1) {
1165                     return -1;
1166                 }
1167             }
1168 
1169             PR_ASSERT(rv == 1);
1170             if (_PR_PENDING_INTERRUPT(me)) {
1171                 me->flags &= ~_PR_INTERRUPT;
1172                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
1173                 return -1;
1174             }
1175             err = _MD_unix_get_nonblocking_connect_error(osfd);
1176             if (err != 0) {
1177                 _PR_MD_MAP_CONNECT_ERROR(err);
1178                 return -1;
1179             }
1180             return 0;
1181         }
1182 
1183         _PR_MD_MAP_CONNECT_ERROR(err);
1184     }
1185 
1186     return rv;
1187 }  /* _MD_connect */
1188 
1189 PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
1190 {
1191     PRInt32 rv, err;
1192 #ifdef _PR_HAVE_SOCKADDR_LEN
1193     PRNetAddr addrCopy;
1194 
1195     addrCopy = *addr;
1196     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
1197     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
1198     rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
1199 #else
1200     rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
1201 #endif
1202     if (rv < 0) {
1203         err = _MD_ERRNO();
1204         _PR_MD_MAP_BIND_ERROR(err);
1205     }
1206     return(rv);
1207 }
1208 
1209 PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
1210 {
1211     PRInt32 rv, err;
1212 
1213     rv = listen(fd->secret->md.osfd, backlog);
1214     if (rv < 0) {
1215         err = _MD_ERRNO();
1216         _PR_MD_MAP_LISTEN_ERROR(err);
1217     }
1218     return(rv);
1219 }
1220 
1221 PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how)
1222 {
1223     PRInt32 rv, err;
1224 
1225     rv = shutdown(fd->secret->md.osfd, how);
1226     if (rv < 0) {
1227         err = _MD_ERRNO();
1228         _PR_MD_MAP_SHUTDOWN_ERROR(err);
1229     }
1230     return(rv);
1231 }
1232 
1233 PRInt32 _MD_socketpair(int af, int type, int flags,
1234                        PRInt32 *osfd)
1235 {
1236     PRInt32 rv, err;
1237 
1238     rv = socketpair(af, type, flags, osfd);
1239     if (rv < 0) {
1240         err = _MD_ERRNO();
1241         _PR_MD_MAP_SOCKETPAIR_ERROR(err);
1242     }
1243     return rv;
1244 }
1245 
1246 PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
1247                          PRUint32 *addrlen)
1248 {
1249     PRInt32 rv, err;
1250 
1251     rv = getsockname(fd->secret->md.osfd,
1252                      (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
1253 #ifdef _PR_HAVE_SOCKADDR_LEN
1254     if (rv == 0) {
1255         /* ignore the sa_len field of struct sockaddr */
1256         if (addr) {
1257             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
1258         }
1259     }
1260 #endif /* _PR_HAVE_SOCKADDR_LEN */
1261     if (rv < 0) {
1262         err = _MD_ERRNO();
1263         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
1264     }
1265     return rv==0?PR_SUCCESS:PR_FAILURE;
1266 }
1267 
1268 PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
1269                          PRUint32 *addrlen)
1270 {
1271     PRInt32 rv, err;
1272 
1273     rv = getpeername(fd->secret->md.osfd,
1274                      (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
1275 #ifdef _PR_HAVE_SOCKADDR_LEN
1276     if (rv == 0) {
1277         /* ignore the sa_len field of struct sockaddr */
1278         if (addr) {
1279             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
1280         }
1281     }
1282 #endif /* _PR_HAVE_SOCKADDR_LEN */
1283     if (rv < 0) {
1284         err = _MD_ERRNO();
1285         _PR_MD_MAP_GETPEERNAME_ERROR(err);
1286     }
1287     return rv==0?PR_SUCCESS:PR_FAILURE;
1288 }
1289 
1290 PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
1291                         PRInt32 optname, char* optval, PRInt32* optlen)
1292 {
1293     PRInt32 rv, err;
1294 
1295     rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);
1296     if (rv < 0) {
1297         err = _MD_ERRNO();
1298         _PR_MD_MAP_GETSOCKOPT_ERROR(err);
1299     }
1300     return rv==0?PR_SUCCESS:PR_FAILURE;
1301 }
1302 
1303 PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,
1304                         PRInt32 optname, const char* optval, PRInt32 optlen)
1305 {
1306     PRInt32 rv, err;
1307 
1308     rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
1309     if (rv < 0) {
1310         err = _MD_ERRNO();
1311         _PR_MD_MAP_SETSOCKOPT_ERROR(err);
1312     }
1313     return rv==0?PR_SUCCESS:PR_FAILURE;
1314 }
1315 
1316 PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable)
1317 {
1318     int rv;
1319 
1320     rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
1321     if (-1 == rv) {
1322         PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
1323         return PR_FAILURE;
1324     }
1325     return PR_SUCCESS;
1326 }
1327 
1328 void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported)
1329 {
1330     if (imported) {
1331         fd->secret->inheritable = _PR_TRI_UNKNOWN;
1332     } else {
1333         /* By default, a Unix fd is not closed on exec. */
1334 #ifdef DEBUG
1335         {
1336             int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
1337             PR_ASSERT(0 == flags);
1338         }
1339 #endif
1340         fd->secret->inheritable = _PR_TRI_TRUE;
1341     }
1342 }
1343 
1344 /************************************************************************/
1345 #if !defined(_PR_USE_POLL)
1346 
1347 /*
1348 ** Scan through io queue and find any bad fd's that triggered the error
1349 ** from _MD_SELECT
1350 */
1351 static void FindBadFDs(void)
1352 {
1353     PRCList *q;
1354     PRThread *me = _MD_CURRENT_THREAD();
1355 
1356     PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
1357     q = (_PR_IOQ(me->cpu)).next;
1358     _PR_IOQ_MAX_OSFD(me->cpu) = -1;
1359     _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
1360     while (q != &_PR_IOQ(me->cpu)) {
1361         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
1362         PRBool notify = PR_FALSE;
1363         _PRUnixPollDesc *pds = pq->pds;
1364         _PRUnixPollDesc *epds = pds + pq->npds;
1365         PRInt32 pq_max_osfd = -1;
1366 
1367         q = q->next;
1368         for (; pds < epds; pds++) {
1369             PRInt32 osfd = pds->osfd;
1370             pds->out_flags = 0;
1371             PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
1372             if (pds->in_flags == 0) {
1373                 continue;  /* skip this fd */
1374             }
1375             if (fcntl(osfd, F_GETFL, 0) == -1) {
1376                 /* Found a bad descriptor, remove it from the fd_sets. */
1377                 PR_LOG(_pr_io_lm, PR_LOG_MAX,
1378                        ("file descriptor %d is bad", osfd));
1379                 pds->out_flags = _PR_UNIX_POLL_NVAL;
1380                 notify = PR_TRUE;
1381             }
1382             if (osfd > pq_max_osfd) {
1383                 pq_max_osfd = osfd;
1384             }
1385         }
1386 
1387         if (notify) {
1388             PRIntn pri;
1389             PR_REMOVE_LINK(&pq->links);
1390             pq->on_ioq = PR_FALSE;
1391 
1392             /*
1393             * Decrement the count of descriptors for each desciptor/event
1394             * because this I/O request is being removed from the
1395             * ioq
1396             */
1397             pds = pq->pds;
1398             for (; pds < epds; pds++) {
1399                 PRInt32 osfd = pds->osfd;
1400                 PRInt16 in_flags = pds->in_flags;
1401                 PR_ASSERT(osfd >= 0 || in_flags == 0);
1402                 if (in_flags & _PR_UNIX_POLL_READ) {
1403                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) {
1404                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
1405                     }
1406                 }
1407                 if (in_flags & _PR_UNIX_POLL_WRITE) {
1408                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) {
1409                         FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
1410                     }
1411                 }
1412                 if (in_flags & _PR_UNIX_POLL_EXCEPT) {
1413                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) {
1414                         FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
1415                     }
1416                 }
1417             }
1418 
1419             _PR_THREAD_LOCK(pq->thr);
1420             if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
1421                 _PRCPU *cpu = pq->thr->cpu;
1422                 _PR_SLEEPQ_LOCK(pq->thr->cpu);
1423                 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
1424                 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
1425 
1426                 if (pq->thr->flags & _PR_SUSPENDING) {
1427                     /*
1428                      * set thread state to SUSPENDED;
1429                      * a Resume operation on the thread
1430                      * will move it to the runQ
1431                      */
1432                     pq->thr->state = _PR_SUSPENDED;
1433                     _PR_MISCQ_LOCK(pq->thr->cpu);
1434                     _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
1435                     _PR_MISCQ_UNLOCK(pq->thr->cpu);
1436                 } else {
1437                     pri = pq->thr->priority;
1438                     pq->thr->state = _PR_RUNNABLE;
1439 
1440                     _PR_RUNQ_LOCK(cpu);
1441                     _PR_ADD_RUNQ(pq->thr, cpu, pri);
1442                     _PR_RUNQ_UNLOCK(cpu);
1443                 }
1444             }
1445             _PR_THREAD_UNLOCK(pq->thr);
1446         } else {
1447             if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) {
1448                 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
1449             }
1450             if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) {
1451                 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
1452             }
1453         }
1454     }
1455     if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1456         if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) {
1457             _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
1458         }
1459     }
1460 }
1461 #endif  /* !defined(_PR_USE_POLL) */
1462 
1463 /************************************************************************/
1464 
1465 /*
1466 ** Called by the scheduler when there is nothing to do. This means that
1467 ** all threads are blocked on some monitor somewhere.
1468 **
1469 ** Note: this code doesn't release the scheduler lock.
1470 */
1471 /*
1472 ** Pause the current CPU. longjmp to the cpu's pause stack
1473 **
1474 ** This must be called with the scheduler locked
1475 */
1476 void _MD_PauseCPU(PRIntervalTime ticks)
1477 {
1478     PRThread *me = _MD_CURRENT_THREAD();
1479 #ifdef _PR_USE_POLL
1480     int timeout;
1481     struct pollfd *pollfds;    /* an array of pollfd structures */
1482     struct pollfd *pollfdPtr;    /* a pointer that steps through the array */
1483     unsigned long npollfds;     /* number of pollfd structures in array */
1484     unsigned long pollfds_size;
1485     int nfd;                    /* to hold the return value of poll() */
1486 #else
1487     struct timeval timeout, *tvp;
1488     fd_set r, w, e;
1489     fd_set *rp, *wp, *ep;
1490     PRInt32 max_osfd, nfd;
1491 #endif  /* _PR_USE_POLL */
1492     PRInt32 rv;
1493     PRCList *q;
1494     PRUint32 min_timeout;
1495     sigset_t oldset;
1496 
1497     PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
1498 
1499     _PR_MD_IOQ_LOCK();
1500 
1501 #ifdef _PR_USE_POLL
1502     /* Build up the pollfd structure array to wait on */
1503 
1504     /* Find out how many pollfd structures are needed */
1505     npollfds = _PR_IOQ_OSFD_CNT(me->cpu);
1506     PR_ASSERT(npollfds >= 0);
1507 
1508     /*
1509      * We use a pipe to wake up a native thread.  An fd is needed
1510      * for the pipe and we poll it for reading.
1511      */
1512     if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1513         npollfds++;
1514     }
1515 
1516     /*
1517      * if the cpu's pollfd array is not big enough, release it and allocate a new one
1518      */
1519     if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
1520         if (_PR_IOQ_POLLFDS(me->cpu) != NULL) {
1521             PR_DELETE(_PR_IOQ_POLLFDS(me->cpu));
1522         }
1523         pollfds_size =  PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
1524         pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
1525         _PR_IOQ_POLLFDS(me->cpu) = pollfds;
1526         _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
1527     } else {
1528         pollfds = _PR_IOQ_POLLFDS(me->cpu);
1529     }
1530     pollfdPtr = pollfds;
1531 
1532     /*
1533      * If we need to poll the pipe for waking up a native thread,
1534      * the pipe's fd is the first element in the pollfds array.
1535      */
1536     if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1537         pollfdPtr->fd = _pr_md_pipefd[0];
1538         pollfdPtr->events = POLLIN;
1539         pollfdPtr++;
1540     }
1541 
1542     min_timeout = PR_INTERVAL_NO_TIMEOUT;
1543     for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
1544         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
1545         _PRUnixPollDesc *pds = pq->pds;
1546         _PRUnixPollDesc *epds = pds + pq->npds;
1547 
1548         if (pq->timeout < min_timeout) {
1549             min_timeout = pq->timeout;
1550         }
1551         for (; pds < epds; pds++, pollfdPtr++) {
1552             /*
1553             * Assert that the pollfdPtr pointer does not go
1554             * beyond the end of the pollfds array
1555             */
1556             PR_ASSERT(pollfdPtr < pollfds + npollfds);
1557             pollfdPtr->fd = pds->osfd;
1558             /* direct copy of poll flags */
1559             pollfdPtr->events = pds->in_flags;
1560         }
1561     }
1562     _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;
1563 #else
1564     /*
1565      * assigment of fd_sets
1566      */
1567     r = _PR_FD_READ_SET(me->cpu);
1568     w = _PR_FD_WRITE_SET(me->cpu);
1569     e = _PR_FD_EXCEPTION_SET(me->cpu);
1570 
1571     rp = &r;
1572     wp = &w;
1573     ep = &e;
1574 
1575     max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
1576     min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
1577 #endif  /* _PR_USE_POLL */
1578     /*
1579     ** Compute the minimum timeout value: make it the smaller of the
1580     ** timeouts specified by the i/o pollers or the timeout of the first
1581     ** sleeping thread.
1582     */
1583     q = _PR_SLEEPQ(me->cpu).next;
1584 
1585     if (q != &_PR_SLEEPQ(me->cpu)) {
1586         PRThread *t = _PR_THREAD_PTR(q);
1587 
1588         if (t->sleep < min_timeout) {
1589             min_timeout = t->sleep;
1590         }
1591     }
1592     if (min_timeout > ticks) {
1593         min_timeout = ticks;
1594     }
1595 
1596 #ifdef _PR_USE_POLL
1597     if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
1598         timeout = -1;
1599     }
1600     else {
1601         timeout = PR_IntervalToMilliseconds(min_timeout);
1602     }
1603 #else
1604     if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
1605         tvp = NULL;
1606     } else {
1607         timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
1608         timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
1609                           % PR_USEC_PER_SEC;
1610         tvp = &timeout;
1611     }
1612 #endif  /* _PR_USE_POLL */
1613 
1614     _PR_MD_IOQ_UNLOCK();
1615     _MD_CHECK_FOR_EXIT();
1616     /*
1617      * check for i/o operations
1618      */
1619 #ifndef _PR_NO_CLOCK_TIMER
1620     /*
1621      * Disable the clock interrupts while we are in select, if clock interrupts
1622      * are enabled. Otherwise, when the select/poll calls are interrupted, the
1623      * timer value starts ticking from zero again when the system call is restarted.
1624      */
1625     if (!_nspr_noclock) {
1626         PR_ASSERT(sigismember(&timer_set, SIGALRM));
1627     }
1628     sigprocmask(SIG_BLOCK, &timer_set, &oldset);
1629 #endif  /* !_PR_NO_CLOCK_TIMER */
1630 
1631 #ifndef _PR_USE_POLL
1632     PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));
1633     nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
1634 #else
1635     nfd = _MD_POLL(pollfds, npollfds, timeout);
1636 #endif  /* !_PR_USE_POLL */
1637 
1638 #ifndef _PR_NO_CLOCK_TIMER
1639     if (!_nspr_noclock) {
1640         sigprocmask(SIG_SETMASK, &oldset, 0);
1641     }
1642 #endif  /* !_PR_NO_CLOCK_TIMER */
1643 
1644     _MD_CHECK_FOR_EXIT();
1645 
1646     _PR_MD_primordial_cpu();
1647 
1648     _PR_MD_IOQ_LOCK();
1649     /*
1650     ** Notify monitors that are associated with the selected descriptors.
1651     */
1652 #ifdef _PR_USE_POLL
1653     if (nfd > 0) {
1654         pollfdPtr = pollfds;
1655         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1656             /*
1657              * Assert that the pipe is the first element in the
1658              * pollfds array.
1659              */
1660             PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);
1661             if ((pollfds[0].revents & POLLIN) && (nfd == 1)) {
1662                 /*
1663                  * woken up by another thread; read all the data
1664                  * in the pipe to empty the pipe
1665                  */
1666                 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,
1667                                   PIPE_BUF)) == PIPE_BUF) {
1668                 }
1669                 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));
1670             }
1671             pollfdPtr++;
1672         }
1673         for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
1674             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
1675             PRBool notify = PR_FALSE;
1676             _PRUnixPollDesc *pds = pq->pds;
1677             _PRUnixPollDesc *epds = pds + pq->npds;
1678 
1679             for (; pds < epds; pds++, pollfdPtr++) {
1680                 /*
1681                   * Assert that the pollfdPtr pointer does not go beyond
1682                   * the end of the pollfds array.
1683                   */
1684                 PR_ASSERT(pollfdPtr < pollfds + npollfds);
1685                 /*
1686                  * Assert that the fd's in the pollfds array (stepped
1687                  * through by pollfdPtr) are in the same order as
1688                  * the fd's in _PR_IOQ() (stepped through by q and pds).
1689                  * This is how the pollfds array was created earlier.
1690                  */
1691                 PR_ASSERT(pollfdPtr->fd == pds->osfd);
1692                 pds->out_flags = pollfdPtr->revents;
1693                 /* Negative fd's are ignored by poll() */
1694                 if (pds->osfd >= 0 && pds->out_flags) {
1695                     notify = PR_TRUE;
1696                 }
1697             }
1698             if (notify) {
1699                 PRIntn pri;
1700                 PRThread *thred;
1701 
1702                 PR_REMOVE_LINK(&pq->links);
1703                 pq->on_ioq = PR_FALSE;
1704 
1705                 thred = pq->thr;
1706                 _PR_THREAD_LOCK(thred);
1707                 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
1708                     _PRCPU *cpu = pq->thr->cpu;
1709                     _PR_SLEEPQ_LOCK(pq->thr->cpu);
1710                     _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
1711                     _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
1712 
1713                     if (pq->thr->flags & _PR_SUSPENDING) {
1714                         /*
1715                          * set thread state to SUSPENDED;
1716                          * a Resume operation on the thread
1717                          * will move it to the runQ
1718                          */
1719                         pq->thr->state = _PR_SUSPENDED;
1720                         _PR_MISCQ_LOCK(pq->thr->cpu);
1721                         _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
1722                         _PR_MISCQ_UNLOCK(pq->thr->cpu);
1723                     } else {
1724                         pri = pq->thr->priority;
1725                         pq->thr->state = _PR_RUNNABLE;
1726 
1727                         _PR_RUNQ_LOCK(cpu);
1728                         _PR_ADD_RUNQ(pq->thr, cpu, pri);
1729                         _PR_RUNQ_UNLOCK(cpu);
1730                         if (_pr_md_idle_cpus > 1) {
1731                             _PR_MD_WAKEUP_WAITER(thred);
1732                         }
1733                     }
1734                 }
1735                 _PR_THREAD_UNLOCK(thred);
1736                 _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;
1737                 PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
1738             }
1739         }
1740     } else if (nfd == -1) {
1741         PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
1742     }
1743 
1744 #else
1745     if (nfd > 0) {
1746         q = _PR_IOQ(me->cpu).next;
1747         _PR_IOQ_MAX_OSFD(me->cpu) = -1;
1748         _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
1749         while (q != &_PR_IOQ(me->cpu)) {
1750             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
1751             PRBool notify = PR_FALSE;
1752             _PRUnixPollDesc *pds = pq->pds;
1753             _PRUnixPollDesc *epds = pds + pq->npds;
1754             PRInt32 pq_max_osfd = -1;
1755 
1756             q = q->next;
1757             for (; pds < epds; pds++) {
1758                 PRInt32 osfd = pds->osfd;
1759                 PRInt16 in_flags = pds->in_flags;
1760                 PRInt16 out_flags = 0;
1761                 PR_ASSERT(osfd >= 0 || in_flags == 0);
1762                 if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) {
1763                     out_flags |= _PR_UNIX_POLL_READ;
1764                 }
1765                 if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) {
1766                     out_flags |= _PR_UNIX_POLL_WRITE;
1767                 }
1768                 if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
1769                     out_flags |= _PR_UNIX_POLL_EXCEPT;
1770                 }
1771                 pds->out_flags = out_flags;
1772                 if (out_flags) {
1773                     notify = PR_TRUE;
1774                 }
1775                 if (osfd > pq_max_osfd) {
1776                     pq_max_osfd = osfd;
1777                 }
1778             }
1779             if (notify == PR_TRUE) {
1780                 PRIntn pri;
1781                 PRThread *thred;
1782 
1783                 PR_REMOVE_LINK(&pq->links);
1784                 pq->on_ioq = PR_FALSE;
1785 
1786                 /*
1787                  * Decrement the count of descriptors for each desciptor/event
1788                  * because this I/O request is being removed from the
1789                  * ioq
1790                  */
1791                 pds = pq->pds;
1792                 for (; pds < epds; pds++) {
1793                     PRInt32 osfd = pds->osfd;
1794                     PRInt16 in_flags = pds->in_flags;
1795                     PR_ASSERT(osfd >= 0 || in_flags == 0);
1796                     if (in_flags & _PR_UNIX_POLL_READ) {
1797                         if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) {
1798                             FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
1799                         }
1800                     }
1801                     if (in_flags & _PR_UNIX_POLL_WRITE) {
1802                         if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) {
1803                             FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
1804                         }
1805                     }
1806                     if (in_flags & _PR_UNIX_POLL_EXCEPT) {
1807                         if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) {
1808                             FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
1809                         }
1810                     }
1811                 }
1812 
1813                 /*
1814                  * Because this thread can run on a different cpu right
1815                  * after being added to the run queue, do not dereference
1816                  * pq
1817                  */
1818                 thred = pq->thr;
1819                 _PR_THREAD_LOCK(thred);
1820                 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
1821                     _PRCPU *cpu = thred->cpu;
1822                     _PR_SLEEPQ_LOCK(pq->thr->cpu);
1823                     _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
1824                     _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
1825 
1826                     if (pq->thr->flags & _PR_SUSPENDING) {
1827                         /*
1828                          * set thread state to SUSPENDED;
1829                          * a Resume operation on the thread
1830                          * will move it to the runQ
1831                          */
1832                         pq->thr->state = _PR_SUSPENDED;
1833                         _PR_MISCQ_LOCK(pq->thr->cpu);
1834                         _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
1835                         _PR_MISCQ_UNLOCK(pq->thr->cpu);
1836                     } else {
1837                         pri = pq->thr->priority;
1838                         pq->thr->state = _PR_RUNNABLE;
1839 
1840                         pq->thr->cpu = cpu;
1841                         _PR_RUNQ_LOCK(cpu);
1842                         _PR_ADD_RUNQ(pq->thr, cpu, pri);
1843                         _PR_RUNQ_UNLOCK(cpu);
1844                         if (_pr_md_idle_cpus > 1) {
1845                             _PR_MD_WAKEUP_WAITER(thred);
1846                         }
1847                     }
1848                 }
1849                 _PR_THREAD_UNLOCK(thred);
1850             } else {
1851                 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) {
1852                     _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
1853                 }
1854                 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) {
1855                     _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
1856                 }
1857             }
1858         }
1859         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1860             if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {
1861                 /*
1862                 * woken up by another thread; read all the data
1863                 * in the pipe to empty the pipe
1864                 */
1865                 while ((rv =
1866                             read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
1867                        == PIPE_BUF) {
1868                 }
1869                 PR_ASSERT((rv > 0) ||
1870                           ((rv == -1) && (errno == EAGAIN)));
1871             }
1872             if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) {
1873                 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
1874             }
1875         }
1876     } else if (nfd < 0) {
1877         if (errno == EBADF) {
1878             FindBadFDs();
1879         } else {
1880             PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
1881                                            errno));
1882         }
1883     } else {
1884         PR_ASSERT(nfd == 0);
1885         /*
1886          * compute the new value of _PR_IOQ_TIMEOUT
1887          */
1888         q = _PR_IOQ(me->cpu).next;
1889         _PR_IOQ_MAX_OSFD(me->cpu) = -1;
1890         _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
1891         while (q != &_PR_IOQ(me->cpu)) {
1892             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
1893             _PRUnixPollDesc *pds = pq->pds;
1894             _PRUnixPollDesc *epds = pds + pq->npds;
1895             PRInt32 pq_max_osfd = -1;
1896 
1897             q = q->next;
1898             for (; pds < epds; pds++) {
1899                 if (pds->osfd > pq_max_osfd) {
1900                     pq_max_osfd = pds->osfd;
1901                 }
1902             }
1903             if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) {
1904                 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
1905             }
1906             if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) {
1907                 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
1908             }
1909         }
1910         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
1911             if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) {
1912                 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
1913             }
1914         }
1915     }
1916 #endif  /* _PR_USE_POLL */
1917     _PR_MD_IOQ_UNLOCK();
1918 }
1919 
1920 void _MD_Wakeup_CPUs()
1921 {
1922     PRInt32 rv, data;
1923 
1924     data = 0;
1925     rv = write(_pr_md_pipefd[1], &data, 1);
1926 
1927     while ((rv < 0) && (errno == EAGAIN)) {
1928         /*
1929          * pipe full, read all data in pipe to empty it
1930          */
1931         while ((rv =
1932                     read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
1933                == PIPE_BUF) {
1934         }
1935         PR_ASSERT((rv > 0) ||
1936                   ((rv == -1) && (errno == EAGAIN)));
1937         rv = write(_pr_md_pipefd[1], &data, 1);
1938     }
1939 }
1940 
1941 
1942 void _MD_InitCPUS()
1943 {
1944     PRInt32 rv, flags;
1945     PRThread *me = _MD_CURRENT_THREAD();
1946 
1947     rv = pipe(_pr_md_pipefd);
1948     PR_ASSERT(rv == 0);
1949     _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
1950 #ifndef _PR_USE_POLL
1951     FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
1952 #endif
1953 
1954     flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
1955     fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
1956     flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
1957     fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
1958 }
1959 
1960 /*
1961 ** Unix SIGALRM (clock) signal handler
1962 */
1963 static void ClockInterruptHandler()
1964 {
1965     int olderrno;
1966     PRUintn pri;
1967     _PRCPU *cpu = _PR_MD_CURRENT_CPU();
1968     PRThread *me = _MD_CURRENT_THREAD();
1969 
1970 #ifdef SOLARIS
1971     if (!me || _PR_IS_NATIVE_THREAD(me)) {
1972         _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;
1973         return;
1974     }
1975 #endif
1976 
1977     if (_PR_MD_GET_INTSOFF() != 0) {
1978         cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
1979         return;
1980     }
1981     _PR_MD_SET_INTSOFF(1);
1982 
1983     olderrno = errno;
1984     _PR_ClockInterrupt();
1985     errno = olderrno;
1986 
1987     /*
1988     ** If the interrupt wants a resched or if some other thread at
1989     ** the same priority needs the cpu, reschedule.
1990     */
1991     pri = me->priority;
1992     if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {
1993 #ifdef _PR_NO_PREEMPT
1994         cpu->resched = PR_TRUE;
1995         if (pr_interruptSwitchHook) {
1996             (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);
1997         }
1998 #else /* _PR_NO_PREEMPT */
1999         /*
2000         ** Re-enable unix interrupts (so that we can use
2001         ** setjmp/longjmp for context switching without having to
2002         ** worry about the signal state)
2003         */
2004         sigprocmask(SIG_SETMASK, &empty_set, 0);
2005         PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));
2006 
2007         if(!(me->flags & _PR_IDLE_THREAD)) {
2008             _PR_THREAD_LOCK(me);
2009             me->state = _PR_RUNNABLE;
2010             me->cpu = cpu;
2011             _PR_RUNQ_LOCK(cpu);
2012             _PR_ADD_RUNQ(me, cpu, pri);
2013             _PR_RUNQ_UNLOCK(cpu);
2014             _PR_THREAD_UNLOCK(me);
2015         } else {
2016             me->state = _PR_RUNNABLE;
2017         }
2018         _MD_SWITCH_CONTEXT(me);
2019         PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));
2020 #endif /* _PR_NO_PREEMPT */
2021     }
2022     /*
2023      * Because this thread could be running on a different cpu after
2024      * a context switch the current cpu should be accessed and the
2025      * value of the 'cpu' variable should not be used.
2026      */
2027     _PR_MD_SET_INTSOFF(0);
2028 }
2029 
2030 /*
2031  * On HP-UX 9, we have to use the sigvector() interface to restart
2032  * interrupted system calls, because sigaction() does not have the
2033  * SA_RESTART flag.
2034  */
2035 
2036 #ifdef HPUX9
2037 static void HPUX9_ClockInterruptHandler(
2038     int sig,
2039     int code,
2040     struct sigcontext *scp)
2041 {
2042     ClockInterruptHandler();
2043     scp->sc_syscall_action = SIG_RESTART;
2044 }
2045 #endif /* HPUX9 */
2046 
2047 /* # of milliseconds per clock tick that we will use */
2048 #define MSEC_PER_TICK    50
2049 
2050 
2051 void _MD_StartInterrupts()
2052 {
2053     char *eval;
2054 
2055     if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {
2056         if (atoi(eval) == 0) {
2057             _nspr_noclock = 0;
2058         }
2059         else {
2060             _nspr_noclock = 1;
2061         }
2062     }
2063 
2064 #ifndef _PR_NO_CLOCK_TIMER
2065     if (!_nspr_noclock) {
2066         _MD_EnableClockInterrupts();
2067     }
2068 #endif
2069 }
2070 
2071 void _MD_StopInterrupts()
2072 {
2073     sigprocmask(SIG_BLOCK, &timer_set, 0);
2074 }
2075 
2076 void _MD_EnableClockInterrupts()
2077 {
2078     struct itimerval itval;
2079     extern PRUintn _pr_numCPU;
2080 #ifdef HPUX9
2081     struct sigvec vec;
2082 
2083     vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler;
2084     vec.sv_mask = 0;
2085     vec.sv_flags = 0;
2086     sigvector(SIGALRM, &vec, 0);
2087 #else
2088     struct sigaction vtact;
2089 
2090     vtact.sa_handler = (void (*)()) ClockInterruptHandler;
2091     sigemptyset(&vtact.sa_mask);
2092     vtact.sa_flags = SA_RESTART;
2093     sigaction(SIGALRM, &vtact, 0);
2094 #endif /* HPUX9 */
2095 
2096     PR_ASSERT(_pr_numCPU == 1);
2097     itval.it_interval.tv_sec = 0;
2098     itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
2099     itval.it_value = itval.it_interval;
2100     setitimer(ITIMER_REAL, &itval, 0);
2101 }
2102 
2103 void _MD_DisableClockInterrupts()
2104 {
2105     struct itimerval itval;
2106     extern PRUintn _pr_numCPU;
2107 
2108     PR_ASSERT(_pr_numCPU == 1);
2109     itval.it_interval.tv_sec = 0;
2110     itval.it_interval.tv_usec = 0;
2111     itval.it_value = itval.it_interval;
2112     setitimer(ITIMER_REAL, &itval, 0);
2113 }
2114 
2115 void _MD_BlockClockInterrupts()
2116 {
2117     sigprocmask(SIG_BLOCK, &timer_set, 0);
2118 }
2119 
2120 void _MD_UnblockClockInterrupts()
2121 {
2122     sigprocmask(SIG_UNBLOCK, &timer_set, 0);
2123 }
2124 
2125 void _MD_MakeNonblock(PRFileDesc *fd)
2126 {
2127     PRInt32 osfd = fd->secret->md.osfd;
2128     int flags;
2129 
2130     if (osfd <= 2) {
2131         /* Don't mess around with stdin, stdout or stderr */
2132         return;
2133     }
2134     flags = fcntl(osfd, F_GETFL, 0);
2135 
2136     /*
2137      * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible.
2138      * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O),
2139      * otherwise connect() still blocks and can be interrupted by SIGALRM.
2140      */
2141 
2142     fcntl(osfd, F_SETFL, flags | O_NONBLOCK);
2143 }
2144 
2145 PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode)
2146 {
2147     PRInt32 osflags;
2148     PRInt32 rv, err;
2149 
2150     if (flags & PR_RDWR) {
2151         osflags = O_RDWR;
2152     } else if (flags & PR_WRONLY) {
2153         osflags = O_WRONLY;
2154     } else {
2155         osflags = O_RDONLY;
2156     }
2157 
2158     if (flags & PR_EXCL) {
2159         osflags |= O_EXCL;
2160     }
2161     if (flags & PR_APPEND) {
2162         osflags |= O_APPEND;
2163     }
2164     if (flags & PR_TRUNCATE) {
2165         osflags |= O_TRUNC;
2166     }
2167     if (flags & PR_SYNC) {
2168 #if defined(O_SYNC)
2169         osflags |= O_SYNC;
2170 #elif defined(O_FSYNC)
2171         osflags |= O_FSYNC;
2172 #else
2173 #error "Neither O_SYNC nor O_FSYNC is defined on this platform"
2174 #endif
2175     }
2176 
2177     /*
2178     ** On creations we hold the 'create' lock in order to enforce
2179     ** the semantics of PR_Rename. (see the latter for more details)
2180     */
2181     if (flags & PR_CREATE_FILE)
2182     {
2183         osflags |= O_CREAT;
2184         if (NULL !=_pr_unix_rename_lock) {
2185             PR_Lock(_pr_unix_rename_lock);
2186         }
2187     }
2188 
2189 #if defined(ANDROID)
2190     osflags |= O_LARGEFILE;
2191 #endif
2192 
2193     rv = _md_iovector._open64(name, osflags, mode);
2194 
2195     if (rv < 0) {
2196         err = _MD_ERRNO();
2197         _PR_MD_MAP_OPEN_ERROR(err);
2198     }
2199 
2200     if ((flags & PR_CREATE_FILE) && (NULL !=_pr_unix_rename_lock)) {
2201         PR_Unlock(_pr_unix_rename_lock);
2202     }
2203     return rv;
2204 }
2205 
2206 PRIntervalTime intr_timeout_ticks;
2207 
2208 #if defined(SOLARIS)
2209 static void sigsegvhandler() {
2210     fprintf(stderr,"Received SIGSEGV\n");
2211     fflush(stderr);
2212     pause();
2213 }
2214 
2215 static void sigaborthandler() {
2216     fprintf(stderr,"Received SIGABRT\n");
2217     fflush(stderr);
2218     pause();
2219 }
2220 
2221 static void sigbushandler() {
2222     fprintf(stderr,"Received SIGBUS\n");
2223     fflush(stderr);
2224     pause();
2225 }
2226 #endif /* SOLARIS */
2227 
2228 #endif  /* !defined(_PR_PTHREADS) */
2229 
2230 void _MD_query_fd_inheritable(PRFileDesc *fd)
2231 {
2232     int flags;
2233 
2234     PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
2235     flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
2236     PR_ASSERT(-1 != flags);
2237     fd->secret->inheritable = (flags & FD_CLOEXEC) ?
2238                               _PR_TRI_FALSE : _PR_TRI_TRUE;
2239 }
2240 
2241 PROffset32 _MD_lseek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
2242 {
2243     PROffset32 rv, where;
2244 
2245     switch (whence) {
2246         case PR_SEEK_SET:
2247             where = SEEK_SET;
2248             break;
2249         case PR_SEEK_CUR:
2250             where = SEEK_CUR;
2251             break;
2252         case PR_SEEK_END:
2253             where = SEEK_END;
2254             break;
2255         default:
2256             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
2257             rv = -1;
2258             goto done;
2259     }
2260     rv = lseek(fd->secret->md.osfd,offset,where);
2261     if (rv == -1)
2262     {
2263         PRInt32 syserr = _MD_ERRNO();
2264         _PR_MD_MAP_LSEEK_ERROR(syserr);
2265     }
2266 done:
2267     return(rv);
2268 }
2269 
2270 PROffset64 _MD_lseek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
2271 {
2272     PRInt32 where;
2273     PROffset64 rv;
2274 
2275     switch (whence)
2276     {
2277         case PR_SEEK_SET:
2278             where = SEEK_SET;
2279             break;
2280         case PR_SEEK_CUR:
2281             where = SEEK_CUR;
2282             break;
2283         case PR_SEEK_END:
2284             where = SEEK_END;
2285             break;
2286         default:
2287             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
2288             rv = minus_one;
2289             goto done;
2290     }
2291     rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where);
2292     if (LL_EQ(rv, minus_one))
2293     {
2294         PRInt32 syserr = _MD_ERRNO();
2295         _PR_MD_MAP_LSEEK_ERROR(syserr);
2296     }
2297 done:
2298     return rv;
2299 }  /* _MD_lseek64 */
2300 
2301 /*
2302 ** _MD_set_fileinfo_times --
2303 **     Set the modifyTime and creationTime of the PRFileInfo
2304 **     structure using the values in struct stat.
2305 **
2306 ** _MD_set_fileinfo64_times --
2307 **     Set the modifyTime and creationTime of the PRFileInfo64
2308 **     structure using the values in _MDStat64.
2309 */
2310 
2311 #if defined(_PR_STAT_HAS_ST_ATIM)
2312 /*
2313 ** struct stat has st_atim, st_mtim, and st_ctim fields of
2314 ** type timestruc_t.
2315 */
2316 static void _MD_set_fileinfo_times(
2317     const struct stat *sb,
2318     PRFileInfo *info)
2319 {
2320     PRInt64 us, s2us;
2321 
2322     LL_I2L(s2us, PR_USEC_PER_SEC);
2323     LL_I2L(info->modifyTime, sb->st_mtim.tv_sec);
2324     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2325     LL_I2L(us, sb->st_mtim.tv_nsec / 1000);
2326     LL_ADD(info->modifyTime, info->modifyTime, us);
2327     LL_I2L(info->creationTime, sb->st_ctim.tv_sec);
2328     LL_MUL(info->creationTime, info->creationTime, s2us);
2329     LL_I2L(us, sb->st_ctim.tv_nsec / 1000);
2330     LL_ADD(info->creationTime, info->creationTime, us);
2331 }
2332 
2333 static void _MD_set_fileinfo64_times(
2334     const _MDStat64 *sb,
2335     PRFileInfo64 *info)
2336 {
2337     PRInt64 us, s2us;
2338 
2339     LL_I2L(s2us, PR_USEC_PER_SEC);
2340     LL_I2L(info->modifyTime, sb->st_mtim.tv_sec);
2341     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2342     LL_I2L(us, sb->st_mtim.tv_nsec / 1000);
2343     LL_ADD(info->modifyTime, info->modifyTime, us);
2344     LL_I2L(info->creationTime, sb->st_ctim.tv_sec);
2345     LL_MUL(info->creationTime, info->creationTime, s2us);
2346     LL_I2L(us, sb->st_ctim.tv_nsec / 1000);
2347     LL_ADD(info->creationTime, info->creationTime, us);
2348 }
2349 #elif defined(_PR_STAT_HAS_ST_ATIM_UNION)
2350 /*
2351 ** The st_atim, st_mtim, and st_ctim fields in struct stat are
2352 ** unions with a st__tim union member of type timestruc_t.
2353 */
2354 static void _MD_set_fileinfo_times(
2355     const struct stat *sb,
2356     PRFileInfo *info)
2357 {
2358     PRInt64 us, s2us;
2359 
2360     LL_I2L(s2us, PR_USEC_PER_SEC);
2361     LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec);
2362     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2363     LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000);
2364     LL_ADD(info->modifyTime, info->modifyTime, us);
2365     LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec);
2366     LL_MUL(info->creationTime, info->creationTime, s2us);
2367     LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000);
2368     LL_ADD(info->creationTime, info->creationTime, us);
2369 }
2370 
2371 static void _MD_set_fileinfo64_times(
2372     const _MDStat64 *sb,
2373     PRFileInfo64 *info)
2374 {
2375     PRInt64 us, s2us;
2376 
2377     LL_I2L(s2us, PR_USEC_PER_SEC);
2378     LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec);
2379     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2380     LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000);
2381     LL_ADD(info->modifyTime, info->modifyTime, us);
2382     LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec);
2383     LL_MUL(info->creationTime, info->creationTime, s2us);
2384     LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000);
2385     LL_ADD(info->creationTime, info->creationTime, us);
2386 }
2387 #elif defined(_PR_STAT_HAS_ST_ATIMESPEC)
2388 /*
2389 ** struct stat has st_atimespec, st_mtimespec, and st_ctimespec
2390 ** fields of type struct timespec.
2391 */
2392 #if defined(_PR_TIMESPEC_HAS_TS_SEC)
2393 static void _MD_set_fileinfo_times(
2394     const struct stat *sb,
2395     PRFileInfo *info)
2396 {
2397     PRInt64 us, s2us;
2398 
2399     LL_I2L(s2us, PR_USEC_PER_SEC);
2400     LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
2401     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2402     LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
2403     LL_ADD(info->modifyTime, info->modifyTime, us);
2404     LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
2405     LL_MUL(info->creationTime, info->creationTime, s2us);
2406     LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
2407     LL_ADD(info->creationTime, info->creationTime, us);
2408 }
2409 
2410 static void _MD_set_fileinfo64_times(
2411     const _MDStat64 *sb,
2412     PRFileInfo64 *info)
2413 {
2414     PRInt64 us, s2us;
2415 
2416     LL_I2L(s2us, PR_USEC_PER_SEC);
2417     LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
2418     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2419     LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
2420     LL_ADD(info->modifyTime, info->modifyTime, us);
2421     LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
2422     LL_MUL(info->creationTime, info->creationTime, s2us);
2423     LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
2424     LL_ADD(info->creationTime, info->creationTime, us);
2425 }
2426 #else /* _PR_TIMESPEC_HAS_TS_SEC */
2427 /*
2428 ** The POSIX timespec structure has tv_sec and tv_nsec.
2429 */
2430 static void _MD_set_fileinfo_times(
2431     const struct stat *sb,
2432     PRFileInfo *info)
2433 {
2434     PRInt64 us, s2us;
2435 
2436     LL_I2L(s2us, PR_USEC_PER_SEC);
2437     LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
2438     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2439     LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
2440     LL_ADD(info->modifyTime, info->modifyTime, us);
2441     LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
2442     LL_MUL(info->creationTime, info->creationTime, s2us);
2443     LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
2444     LL_ADD(info->creationTime, info->creationTime, us);
2445 }
2446 
2447 static void _MD_set_fileinfo64_times(
2448     const _MDStat64 *sb,
2449     PRFileInfo64 *info)
2450 {
2451     PRInt64 us, s2us;
2452 
2453     LL_I2L(s2us, PR_USEC_PER_SEC);
2454     LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
2455     LL_MUL(info->modifyTime, info->modifyTime, s2us);
2456     LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
2457     LL_ADD(info->modifyTime, info->modifyTime, us);
2458     LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
2459     LL_MUL(info->creationTime, info->creationTime, s2us);
2460     LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
2461     LL_ADD(info->creationTime, info->creationTime, us);
2462 }
2463 #endif /* _PR_TIMESPEC_HAS_TS_SEC */
2464 #elif defined(_PR_STAT_HAS_ONLY_ST_ATIME)
2465 /*
2466 ** struct stat only has st_atime, st_mtime, and st_ctime fields
2467 ** of type time_t.
2468 */
2469 static void _MD_set_fileinfo_times(
2470     const struct stat *sb,
2471     PRFileInfo *info)
2472 {
2473     PRInt64 s, s2us;
2474     LL_I2L(s2us, PR_USEC_PER_SEC);
2475     LL_I2L(s, sb->st_mtime);
2476     LL_MUL(s, s, s2us);
2477     info->modifyTime = s;
2478     LL_I2L(s, sb->st_ctime);
2479     LL_MUL(s, s, s2us);
2480     info->creationTime = s;
2481 }
2482 
2483 static void _MD_set_fileinfo64_times(
2484     const _MDStat64 *sb,
2485     PRFileInfo64 *info)
2486 {
2487     PRInt64 s, s2us;
2488     LL_I2L(s2us, PR_USEC_PER_SEC);
2489     LL_I2L(s, sb->st_mtime);
2490     LL_MUL(s, s, s2us);
2491     info->modifyTime = s;
2492     LL_I2L(s, sb->st_ctime);
2493     LL_MUL(s, s, s2us);
2494     info->creationTime = s;
2495 }
2496 #else
2497 #error "I don't know yet"
2498 #endif
2499 
2500 static int _MD_convert_stat_to_fileinfo(
2501     const struct stat *sb,
2502     PRFileInfo *info)
2503 {
2504     if (S_IFREG & sb->st_mode) {
2505         info->type = PR_FILE_FILE;
2506     }
2507     else if (S_IFDIR & sb->st_mode) {
2508         info->type = PR_FILE_DIRECTORY;
2509     }
2510     else {
2511         info->type = PR_FILE_OTHER;
2512     }
2513 
2514 #if defined(_PR_HAVE_LARGE_OFF_T)
2515     if (0x7fffffffL < sb->st_size)
2516     {
2517         PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
2518         return -1;
2519     }
2520 #endif /* defined(_PR_HAVE_LARGE_OFF_T) */
2521     info->size = sb->st_size;
2522 
2523     _MD_set_fileinfo_times(sb, info);
2524     return 0;
2525 }  /* _MD_convert_stat_to_fileinfo */
2526 
2527 static int _MD_convert_stat64_to_fileinfo64(
2528     const _MDStat64 *sb,
2529     PRFileInfo64 *info)
2530 {
2531     if (S_IFREG & sb->st_mode) {
2532         info->type = PR_FILE_FILE;
2533     }
2534     else if (S_IFDIR & sb->st_mode) {
2535         info->type = PR_FILE_DIRECTORY;
2536     }
2537     else {
2538         info->type = PR_FILE_OTHER;
2539     }
2540 
2541     LL_I2L(info->size, sb->st_size);
2542 
2543     _MD_set_fileinfo64_times(sb, info);
2544     return 0;
2545 }  /* _MD_convert_stat64_to_fileinfo64 */
2546 
2547 PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info)
2548 {
2549     PRInt32 rv;
2550     struct stat sb;
2551 
2552     rv = stat(fn, &sb);
2553     if (rv < 0) {
2554         _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
2555     }
2556     else if (NULL != info) {
2557         rv = _MD_convert_stat_to_fileinfo(&sb, info);
2558     }
2559     return rv;
2560 }
2561 
2562 PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
2563 {
2564     _MDStat64 sb;
2565     PRInt32 rv = _md_iovector._stat64(fn, &sb);
2566     if (rv < 0) {
2567         _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
2568     }
2569     else if (NULL != info) {
2570         rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
2571     }
2572     return rv;
2573 }
2574 
2575 PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
2576 {
2577     struct stat sb;
2578     PRInt32 rv = fstat(fd->secret->md.osfd, &sb);
2579     if (rv < 0) {
2580         _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
2581     }
2582     else if (NULL != info) {
2583         rv = _MD_convert_stat_to_fileinfo(&sb, info);
2584     }
2585     return rv;
2586 }
2587 
2588 PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
2589 {
2590     _MDStat64 sb;
2591     PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb);
2592     if (rv < 0) {
2593         _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
2594     }
2595     else if (NULL != info) {
2596         rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
2597     }
2598     return rv;
2599 }
2600 
2601 /*
2602  * _md_iovector._open64 must be initialized to 'open' so that _PR_InitLog can
2603  * open the log file during NSPR initialization, before _md_iovector is
2604  * initialized by _PR_MD_FINAL_INIT.  This means the log file cannot be a
2605  * large file on some platforms.
2606  */
2607 struct _MD_IOVector _md_iovector = { open };
2608 
2609 /*
2610 ** These implementations are to emulate large file routines on systems that
2611 ** don't have them. Their goal is to check in case overflow occurs. Otherwise
2612 ** they will just operate as normal using 32-bit file routines.
2613 **
2614 ** The checking might be pre- or post-op, depending on the semantics.
2615 */
2616 
2617 #if defined(SOLARIS2_5)
2618 
2619 static PRIntn _MD_solaris25_fstat64(PRIntn osfd, _MDStat64 *buf)
2620 {
2621     PRInt32 rv;
2622     struct stat sb;
2623 
2624     rv = fstat(osfd, &sb);
2625     if (rv >= 0)
2626     {
2627         /*
2628         ** I'm only copying the fields that are immediately needed.
2629         ** If somebody else calls this function, some of the fields
2630         ** may not be defined.
2631         */
2632         (void)memset(buf, 0, sizeof(_MDStat64));
2633         buf->st_mode = sb.st_mode;
2634         buf->st_ctim = sb.st_ctim;
2635         buf->st_mtim = sb.st_mtim;
2636         buf->st_size = sb.st_size;
2637     }
2638     return rv;
2639 }  /* _MD_solaris25_fstat64 */
2640 
2641 static PRIntn _MD_solaris25_stat64(const char *fn, _MDStat64 *buf)
2642 {
2643     PRInt32 rv;
2644     struct stat sb;
2645 
2646     rv = stat(fn, &sb);
2647     if (rv >= 0)
2648     {
2649         /*
2650         ** I'm only copying the fields that are immediately needed.
2651         ** If somebody else calls this function, some of the fields
2652         ** may not be defined.
2653         */
2654         (void)memset(buf, 0, sizeof(_MDStat64));
2655         buf->st_mode = sb.st_mode;
2656         buf->st_ctim = sb.st_ctim;
2657         buf->st_mtim = sb.st_mtim;
2658         buf->st_size = sb.st_size;
2659     }
2660     return rv;
2661 }  /* _MD_solaris25_stat64 */
2662 #endif /* defined(SOLARIS2_5) */
2663 
2664 #if defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5)
2665 
2666 static PROffset64 _MD_Unix_lseek64(PRIntn osfd, PROffset64 offset, PRIntn whence)
2667 {
2668     PRUint64 maxoff;
2669     PROffset64 rv = minus_one;
2670     LL_I2L(maxoff, 0x7fffffff);
2671     if (LL_CMP(offset, <=, maxoff))
2672     {
2673         off_t off;
2674         LL_L2I(off, offset);
2675         LL_I2L(rv, lseek(osfd, off, whence));
2676     }
2677     else {
2678         errno = EFBIG;    /* we can't go there */
2679     }
2680     return rv;
2681 }  /* _MD_Unix_lseek64 */
2682 
2683 static void* _MD_Unix_mmap64(
2684     void *addr, PRSize len, PRIntn prot, PRIntn flags,
2685     PRIntn fildes, PRInt64 offset)
2686 {
2687     PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
2688     return NULL;
2689 }  /* _MD_Unix_mmap64 */
2690 #endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */
2691 
2692 /* NDK non-unified headers for API < 21 don't have mmap64. However,
2693  * NDK unified headers do provide mmap64 for all API versions when building
2694  * with clang. Therefore, we should provide mmap64 here for API < 21 if we're
2695  * not using clang or if we're using non-unified headers. We check for
2696  * non-unified headers by the lack of __ANDROID_API_L__ macro. */
2697 #if defined(ANDROID) && __ANDROID_API__ < 21 && \
2698     (!defined(__clang__) || !defined(__ANDROID_API_L__))
2699 PR_IMPORT(void) *__mmap2(void *, size_t, int, int, int, size_t);
2700 
2701 #define ANDROID_PAGE_SIZE 4096
2702 
2703 static void *
2704 mmap64(void *addr, size_t len, int prot, int flags, int fd, loff_t offset)
2705 {
2706     if (offset & (ANDROID_PAGE_SIZE - 1)) {
2707         errno = EINVAL;
2708         return MAP_FAILED;
2709     }
2710     return __mmap2(addr, len, prot, flags, fd, offset / ANDROID_PAGE_SIZE);
2711 }
2712 #endif
2713 
2714 static void _PR_InitIOV(void)
2715 {
2716 #if defined(SOLARIS2_5)
2717     PRLibrary *lib;
2718     void *open64_func;
2719 
2720     open64_func = PR_FindSymbolAndLibrary("open64", &lib);
2721     if (NULL != open64_func)
2722     {
2723         PR_ASSERT(NULL != lib);
2724         _md_iovector._open64 = (_MD_Open64)open64_func;
2725         _md_iovector._mmap64 = (_MD_Mmap64)PR_FindSymbol(lib, "mmap64");
2726         _md_iovector._fstat64 = (_MD_Fstat64)PR_FindSymbol(lib, "fstat64");
2727         _md_iovector._stat64 = (_MD_Stat64)PR_FindSymbol(lib, "stat64");
2728         _md_iovector._lseek64 = (_MD_Lseek64)PR_FindSymbol(lib, "lseek64");
2729         (void)PR_UnloadLibrary(lib);
2730     }
2731     else
2732     {
2733         _md_iovector._open64 = open;
2734         _md_iovector._mmap64 = _MD_Unix_mmap64;
2735         _md_iovector._fstat64 = _MD_solaris25_fstat64;
2736         _md_iovector._stat64 = _MD_solaris25_stat64;
2737         _md_iovector._lseek64 = _MD_Unix_lseek64;
2738     }
2739 #elif defined(_PR_NO_LARGE_FILES)
2740     _md_iovector._open64 = open;
2741     _md_iovector._mmap64 = _MD_Unix_mmap64;
2742     _md_iovector._fstat64 = fstat;
2743     _md_iovector._stat64 = stat;
2744     _md_iovector._lseek64 = _MD_Unix_lseek64;
2745 #elif defined(_PR_HAVE_OFF64_T)
2746 #if (defined(ANDROID) && __ANDROID_API__ < 21)
2747     /*
2748      * Android < 21 doesn't have open64.  We pass the O_LARGEFILE flag to open
2749      * in _MD_open.
2750      */
2751     _md_iovector._open64 = open;
2752 #else
2753     _md_iovector._open64 = open64;
2754 #endif
2755     _md_iovector._mmap64 = mmap64;
2756 #if (defined(ANDROID) && __ANDROID_API__ < 21)
2757     /* Same as the open64 case for Android. */
2758     _md_iovector._fstat64 = fstat;
2759     _md_iovector._stat64 = stat;
2760 #else
2761     _md_iovector._fstat64 = fstat64;
2762     _md_iovector._stat64 = stat64;
2763 #endif
2764     _md_iovector._lseek64 = lseek64;
2765 #elif defined(_PR_HAVE_LARGE_OFF_T)
2766     _md_iovector._open64 = open;
2767     _md_iovector._mmap64 = mmap;
2768     _md_iovector._fstat64 = fstat;
2769     _md_iovector._stat64 = stat;
2770     _md_iovector._lseek64 = lseek;
2771 #else
2772 #error "I don't know yet"
2773 #endif
2774     LL_I2L(minus_one, -1);
2775 }  /* _PR_InitIOV */
2776 
2777 void _PR_UnixInit(void)
2778 {
2779     struct sigaction sigact;
2780     int rv;
2781 
2782     sigemptyset(&timer_set);
2783 
2784 #if !defined(_PR_PTHREADS)
2785 
2786     sigaddset(&timer_set, SIGALRM);
2787     sigemptyset(&empty_set);
2788     intr_timeout_ticks =
2789         PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);
2790 
2791 #if defined(SOLARIS)
2792 
2793     if (getenv("NSPR_SIGSEGV_HANDLE")) {
2794         sigact.sa_handler = sigsegvhandler;
2795         sigact.sa_flags = 0;
2796         sigact.sa_mask = timer_set;
2797         sigaction(SIGSEGV, &sigact, 0);
2798     }
2799 
2800     if (getenv("NSPR_SIGABRT_HANDLE")) {
2801         sigact.sa_handler = sigaborthandler;
2802         sigact.sa_flags = 0;
2803         sigact.sa_mask = timer_set;
2804         sigaction(SIGABRT, &sigact, 0);
2805     }
2806 
2807     if (getenv("NSPR_SIGBUS_HANDLE")) {
2808         sigact.sa_handler = sigbushandler;
2809         sigact.sa_flags = 0;
2810         sigact.sa_mask = timer_set;
2811         sigaction(SIGBUS, &sigact, 0);
2812     }
2813 
2814 #endif
2815 #endif  /* !defined(_PR_PTHREADS) */
2816 
2817     sigact.sa_handler = SIG_IGN;
2818     sigemptyset(&sigact.sa_mask);
2819     sigact.sa_flags = 0;
2820     rv = sigaction(SIGPIPE, &sigact, 0);
2821     PR_ASSERT(0 == rv);
2822 
2823     _pr_unix_rename_lock = PR_NewLock();
2824     PR_ASSERT(NULL != _pr_unix_rename_lock);
2825     _pr_Xfe_mon = PR_NewMonitor();
2826     PR_ASSERT(NULL != _pr_Xfe_mon);
2827 
2828     _PR_InitIOV();  /* one last hack */
2829 }
2830 
2831 void _PR_UnixCleanup(void)
2832 {
2833     if (_pr_unix_rename_lock) {
2834         PR_DestroyLock(_pr_unix_rename_lock);
2835         _pr_unix_rename_lock = NULL;
2836     }
2837     if (_pr_Xfe_mon) {
2838         PR_DestroyMonitor(_pr_Xfe_mon);
2839         _pr_Xfe_mon = NULL;
2840     }
2841 }
2842 
2843 #if !defined(_PR_PTHREADS)
2844 
2845 /*
2846  * Variables used by the GC code, initialized in _MD_InitSegs().
2847  */
2848 static PRInt32 _pr_zero_fd = -1;
2849 static PRLock *_pr_md_lock = NULL;
2850 
2851 /*
2852  * _MD_InitSegs --
2853  *
2854  * This is Unix's version of _PR_MD_INIT_SEGS(), which is
2855  * called by _PR_InitSegs(), which in turn is called by
2856  * PR_Init().
2857  */
2858 void _MD_InitSegs(void)
2859 {
2860 #ifdef DEBUG
2861     /*
2862     ** Disable using mmap(2) if NSPR_NO_MMAP is set
2863     */
2864     if (getenv("NSPR_NO_MMAP")) {
2865         _pr_zero_fd = -2;
2866         return;
2867     }
2868 #endif
2869     _pr_zero_fd = open("/dev/zero",O_RDWR, 0);
2870     /* Prevent the fd from being inherited by child processes */
2871     fcntl(_pr_zero_fd, F_SETFD, FD_CLOEXEC);
2872     _pr_md_lock = PR_NewLock();
2873 }
2874 
2875 PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
2876 {
2877     static char *lastaddr = (char*) _PR_STACK_VMBASE;
2878     PRStatus retval = PR_SUCCESS;
2879     int prot;
2880     void *rv;
2881 
2882     PR_ASSERT(seg != 0);
2883     PR_ASSERT(size != 0);
2884 
2885     PR_Lock(_pr_md_lock);
2886     if (_pr_zero_fd < 0) {
2887 from_heap:
2888         seg->vaddr = PR_MALLOC(size);
2889         if (!seg->vaddr) {
2890             retval = PR_FAILURE;
2891         }
2892         else {
2893             seg->size = size;
2894         }
2895         goto exit;
2896     }
2897 
2898     prot = PROT_READ|PROT_WRITE;
2899     /*
2900      * On Alpha Linux, the user-level thread stack needs
2901      * to be made executable because longjmp/signal seem
2902      * to put machine instructions on the stack.
2903      */
2904 #if defined(LINUX) && defined(__alpha)
2905     prot |= PROT_EXEC;
2906 #endif
2907     rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,
2908               _MD_MMAP_FLAGS,
2909               _pr_zero_fd, 0);
2910     if (rv == (void*)-1) {
2911         goto from_heap;
2912     }
2913     lastaddr += size;
2914     seg->vaddr = rv;
2915     seg->size = size;
2916     seg->flags = _PR_SEG_VM;
2917 
2918 exit:
2919     PR_Unlock(_pr_md_lock);
2920     return retval;
2921 }
2922 
2923 void _MD_FreeSegment(PRSegment *seg)
2924 {
2925     if (seg->flags & _PR_SEG_VM) {
2926         (void) munmap(seg->vaddr, seg->size);
2927     }
2928     else {
2929         PR_DELETE(seg->vaddr);
2930     }
2931 }
2932 
2933 #endif /* _PR_PTHREADS */
2934 
2935 /*
2936  *-----------------------------------------------------------------------
2937  *
2938  * PR_Now --
2939  *
2940  *     Returns the current time in microseconds since the epoch.
2941  *     The epoch is midnight January 1, 1970 GMT.
2942  *     The implementation is machine dependent.  This is the Unix
2943  *     implementation.
2944  *     Cf. time_t time(time_t *tp)
2945  *
2946  *-----------------------------------------------------------------------
2947  */
2948 
2949 PR_IMPLEMENT(PRTime)
2950 PR_Now(void)
2951 {
2952     struct timeval tv;
2953     PRInt64 s, us, s2us;
2954 
2955     GETTIMEOFDAY(&tv);
2956     LL_I2L(s2us, PR_USEC_PER_SEC);
2957     LL_I2L(s, tv.tv_sec);
2958     LL_I2L(us, tv.tv_usec);
2959     LL_MUL(s, s, s2us);
2960     LL_ADD(s, s, us);
2961     return s;
2962 }
2963 
2964 #if defined(_MD_INTERVAL_USE_GTOD)
2965 /*
2966  * This version of interval times is based on the time of day
2967  * capability offered by the system. This isn't valid for two reasons:
2968  * 1) The time of day is neither linear nor montonically increasing
2969  * 2) The units here are milliseconds. That's not appropriate for our use.
2970  */
2971 PRIntervalTime _PR_UNIX_GetInterval()
2972 {
2973     struct timeval time;
2974     PRIntervalTime ticks;
2975 
2976     (void)GETTIMEOFDAY(&time);  /* fallicy of course */
2977     ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC;  /* that's in milliseconds */
2978     ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC;  /* so's that */
2979     return ticks;
2980 }  /* _PR_UNIX_GetInterval */
2981 
2982 PRIntervalTime _PR_UNIX_TicksPerSecond()
2983 {
2984     return 1000;  /* this needs some work :) */
2985 }
2986 #endif
2987 
2988 #if defined(_PR_HAVE_CLOCK_MONOTONIC)
2989 PRIntervalTime _PR_UNIX_GetInterval2()
2990 {
2991     struct timespec time;
2992     PRIntervalTime ticks;
2993 
2994     if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {
2995         fprintf(stderr, "clock_gettime failed: %d\n", errno);
2996         abort();
2997     }
2998 
2999     ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC;
3000     ticks += (PRUint32)time.tv_nsec / PR_NSEC_PER_MSEC;
3001     return ticks;
3002 }
3003 
3004 PRIntervalTime _PR_UNIX_TicksPerSecond2()
3005 {
3006     return 1000;
3007 }
3008 #endif
3009 
3010 #if !defined(_PR_PTHREADS)
3011 /*
3012  * Wait for I/O on multiple descriptors.
3013  *
3014  * Return 0 if timed out, return -1 if interrupted,
3015  * else return the number of ready descriptors.
3016  */
3017 PRInt32 _PR_WaitForMultipleFDs(
3018     _PRUnixPollDesc *unixpds,
3019     PRInt32 pdcnt,
3020     PRIntervalTime timeout)
3021 {
3022     PRPollQueue pq;
3023     PRIntn is;
3024     PRInt32 rv;
3025     _PRCPU *io_cpu;
3026     _PRUnixPollDesc *unixpd, *eunixpd;
3027     PRThread *me = _PR_MD_CURRENT_THREAD();
3028 
3029     PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
3030 
3031     if (_PR_PENDING_INTERRUPT(me)) {
3032         me->flags &= ~_PR_INTERRUPT;
3033         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
3034         return -1;
3035     }
3036 
3037     pq.pds = unixpds;
3038     pq.npds = pdcnt;
3039 
3040     _PR_INTSOFF(is);
3041     _PR_MD_IOQ_LOCK();
3042     _PR_THREAD_LOCK(me);
3043 
3044     pq.thr = me;
3045     io_cpu = me->cpu;
3046     pq.on_ioq = PR_TRUE;
3047     pq.timeout = timeout;
3048     _PR_ADD_TO_IOQ(pq, me->cpu);
3049 
3050 #if !defined(_PR_USE_POLL)
3051     eunixpd = unixpds + pdcnt;
3052     for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
3053         PRInt32 osfd = unixpd->osfd;
3054         if (unixpd->in_flags & _PR_UNIX_POLL_READ) {
3055             FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
3056             _PR_FD_READ_CNT(me->cpu)[osfd]++;
3057         }
3058         if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) {
3059             FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
3060             (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
3061         }
3062         if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) {
3063             FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
3064             (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
3065         }
3066         if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) {
3067             _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
3068         }
3069     }
3070 #endif  /* !defined(_PR_USE_POLL) */
3071 
3072     if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) {
3073         _PR_IOQ_TIMEOUT(me->cpu) = timeout;
3074     }
3075 
3076     _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;
3077 
3078     _PR_SLEEPQ_LOCK(me->cpu);
3079     _PR_ADD_SLEEPQ(me, timeout);
3080     me->state = _PR_IO_WAIT;
3081     me->io_pending = PR_TRUE;
3082     me->io_suspended = PR_FALSE;
3083     _PR_SLEEPQ_UNLOCK(me->cpu);
3084     _PR_THREAD_UNLOCK(me);
3085     _PR_MD_IOQ_UNLOCK();
3086 
3087     _PR_MD_WAIT(me, timeout);
3088 
3089     me->io_pending = PR_FALSE;
3090     me->io_suspended = PR_FALSE;
3091 
3092     /*
3093      * This thread should run on the same cpu on which it was blocked; when
3094      * the IO request times out the fd sets and fd counts for the
3095      * cpu are updated below.
3096      */
3097     PR_ASSERT(me->cpu == io_cpu);
3098 
3099     /*
3100     ** If we timed out the pollq might still be on the ioq. Remove it
3101     ** before continuing.
3102     */
3103     if (pq.on_ioq) {
3104         _PR_MD_IOQ_LOCK();
3105         /*
3106          * Need to check pq.on_ioq again
3107          */
3108         if (pq.on_ioq) {
3109             PR_REMOVE_LINK(&pq.links);
3110 #ifndef _PR_USE_POLL
3111             eunixpd = unixpds + pdcnt;
3112             for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
3113                 PRInt32 osfd = unixpd->osfd;
3114                 PRInt16 in_flags = unixpd->in_flags;
3115 
3116                 if (in_flags & _PR_UNIX_POLL_READ) {
3117                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) {
3118                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
3119                     }
3120                 }
3121                 if (in_flags & _PR_UNIX_POLL_WRITE) {
3122                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) {
3123                         FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
3124                     }
3125                 }
3126                 if (in_flags & _PR_UNIX_POLL_EXCEPT) {
3127                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) {
3128                         FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
3129                     }
3130                 }
3131             }
3132 #endif  /* _PR_USE_POLL */
3133             PR_ASSERT(pq.npds == pdcnt);
3134             _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;
3135             PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
3136         }
3137         _PR_MD_IOQ_UNLOCK();
3138     }
3139     /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */
3140     if (1 == pdcnt) {
3141         _PR_FAST_INTSON(is);
3142     } else {
3143         _PR_INTSON(is);
3144     }
3145 
3146     if (_PR_PENDING_INTERRUPT(me)) {
3147         me->flags &= ~_PR_INTERRUPT;
3148         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
3149         return -1;
3150     }
3151 
3152     rv = 0;
3153     if (pq.on_ioq == PR_FALSE) {
3154         /* Count the number of ready descriptors */
3155         while (--pdcnt >= 0) {
3156             if (unixpds->out_flags != 0) {
3157                 rv++;
3158             }
3159             unixpds++;
3160         }
3161     }
3162 
3163     return rv;
3164 }
3165 
3166 /*
3167  * Unblock threads waiting for I/O
3168  *    used when interrupting threads
3169  *
3170  * NOTE: The thread lock should held when this function is called.
3171  * On return, the thread lock is released.
3172  */
3173 void _PR_Unblock_IO_Wait(PRThread *thr)
3174 {
3175     int pri = thr->priority;
3176     _PRCPU *cpu = thr->cpu;
3177 
3178     /*
3179      * GLOBAL threads wakeup periodically to check for interrupt
3180      */
3181     if (_PR_IS_NATIVE_THREAD(thr)) {
3182         _PR_THREAD_UNLOCK(thr);
3183         return;
3184     }
3185 
3186     PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
3187     _PR_SLEEPQ_LOCK(cpu);
3188     _PR_DEL_SLEEPQ(thr, PR_TRUE);
3189     _PR_SLEEPQ_UNLOCK(cpu);
3190 
3191     PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
3192     thr->state = _PR_RUNNABLE;
3193     _PR_RUNQ_LOCK(cpu);
3194     _PR_ADD_RUNQ(thr, cpu, pri);
3195     _PR_RUNQ_UNLOCK(cpu);
3196     _PR_THREAD_UNLOCK(thr);
3197     _PR_MD_WAKEUP_WAITER(thr);
3198 }
3199 #endif  /* !defined(_PR_PTHREADS) */
3200 
3201 /*
3202  * When a nonblocking connect has completed, determine whether it
3203  * succeeded or failed, and if it failed, what the error code is.
3204  *
3205  * The function returns the error code.  An error code of 0 means
3206  * that the nonblocking connect succeeded.
3207  */
3208 
3209 int _MD_unix_get_nonblocking_connect_error(int osfd)
3210 {
3211 #if defined(NTO)
3212     /* Neutrino does not support the SO_ERROR socket option */
3213     PRInt32      rv;
3214     PRNetAddr    addr;
3215     _PRSockLen_t addrlen = sizeof(addr);
3216 
3217     /* Test to see if we are using the Tiny TCP/IP Stack or the Full one. */
3218     struct statvfs superblock;
3219     rv = fstatvfs(osfd, &superblock);
3220     if (rv == 0) {
3221         if (strcmp(superblock.f_basetype, "ttcpip") == 0) {
3222             /* Using the Tiny Stack! */
3223             rv = getpeername(osfd, (struct sockaddr *) &addr,
3224                              (_PRSockLen_t *) &addrlen);
3225             if (rv == -1) {
3226                 int errno_copy = errno;    /* make a copy so I don't
3227                                             * accidentally reset */
3228 
3229                 if (errno_copy == ENOTCONN) {
3230                     struct stat StatInfo;
3231                     rv = fstat(osfd, &StatInfo);
3232                     if (rv == 0) {
3233                         time_t current_time = time(NULL);
3234 
3235                         /*
3236                          * this is a real hack, can't explain why it
3237                          * works it just does
3238                          */
3239                         if (abs(current_time - StatInfo.st_atime) < 5) {
3240                             return ECONNREFUSED;
3241                         } else {
3242                             return ETIMEDOUT;
3243                         }
3244                     } else {
3245                         return ECONNREFUSED;
3246                     }
3247                 } else {
3248                     return errno_copy;
3249                 }
3250             } else {
3251                 /* No Error */
3252                 return 0;
3253             }
3254         } else {
3255             /* Have the FULL Stack which supports SO_ERROR */
3256             /* Hasn't been written yet, never been tested! */
3257             /* Jerry.Kirk@Nexwarecorp.com */
3258 
3259             int err;
3260             _PRSockLen_t optlen = sizeof(err);
3261 
3262             if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
3263                            (char *) &err, &optlen) == -1) {
3264                 return errno;
3265             } else {
3266                 return err;
3267             }
3268         }
3269     } else {
3270         return ECONNREFUSED;
3271     }
3272 #elif defined(UNIXWARE)
3273     /*
3274      * getsockopt() fails with EPIPE, so use getmsg() instead.
3275      */
3276 
3277     int rv;
3278     int flags = 0;
3279     rv = getmsg(osfd, NULL, NULL, &flags);
3280     PR_ASSERT(-1 == rv || 0 == rv);
3281     if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
3282         return errno;
3283     }
3284     return 0; /* no error */
3285 #else
3286     int err;
3287     _PRSockLen_t optlen = sizeof(err);
3288     if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen) == -1) {
3289         return errno;
3290     }
3291     return err;
3292 
3293 #endif
3294 }
3295 
3296 /************************************************************************/
3297 
3298 /*
3299 ** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
3300 ** safe.  Unfortunately, neither is mozilla. To make these programs work
3301 ** in a pre-emptive threaded environment, we need to use a lock.
3302 */
3303 
3304 void _PR_XLock(void)
3305 {
3306     PR_EnterMonitor(_pr_Xfe_mon);
3307 }
3308 
3309 void _PR_XUnlock(void)
3310 {
3311     PR_ExitMonitor(_pr_Xfe_mon);
3312 }
3313 
3314 PRBool _PR_XIsLocked(void)
3315 {
3316     return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
3317 }
3318 
3319 #if defined(HAVE_FCNTL_FILE_LOCKING)
3320 
3321 PRStatus
3322 _MD_LockFile(PRInt32 f)
3323 {
3324     PRInt32 rv;
3325     struct flock arg;
3326 
3327     arg.l_type = F_WRLCK;
3328     arg.l_whence = SEEK_SET;
3329     arg.l_start = 0;
3330     arg.l_len = 0;  /* until EOF */
3331     rv = fcntl(f, F_SETLKW, &arg);
3332     if (rv == 0) {
3333         return PR_SUCCESS;
3334     }
3335     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3336     return PR_FAILURE;
3337 }
3338 
3339 PRStatus
3340 _MD_TLockFile(PRInt32 f)
3341 {
3342     PRInt32 rv;
3343     struct flock arg;
3344 
3345     arg.l_type = F_WRLCK;
3346     arg.l_whence = SEEK_SET;
3347     arg.l_start = 0;
3348     arg.l_len = 0;  /* until EOF */
3349     rv = fcntl(f, F_SETLK, &arg);
3350     if (rv == 0) {
3351         return PR_SUCCESS;
3352     }
3353     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3354     return PR_FAILURE;
3355 }
3356 
3357 PRStatus
3358 _MD_UnlockFile(PRInt32 f)
3359 {
3360     PRInt32 rv;
3361     struct flock arg;
3362 
3363     arg.l_type = F_UNLCK;
3364     arg.l_whence = SEEK_SET;
3365     arg.l_start = 0;
3366     arg.l_len = 0;  /* until EOF */
3367     rv = fcntl(f, F_SETLK, &arg);
3368     if (rv == 0) {
3369         return PR_SUCCESS;
3370     }
3371     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3372     return PR_FAILURE;
3373 }
3374 
3375 #elif defined(HAVE_BSD_FLOCK)
3376 
3377 #include <sys/file.h>
3378 
3379 PRStatus
3380 _MD_LockFile(PRInt32 f)
3381 {
3382     PRInt32 rv;
3383     rv = flock(f, LOCK_EX);
3384     if (rv == 0) {
3385         return PR_SUCCESS;
3386     }
3387     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3388     return PR_FAILURE;
3389 }
3390 
3391 PRStatus
3392 _MD_TLockFile(PRInt32 f)
3393 {
3394     PRInt32 rv;
3395     rv = flock(f, LOCK_EX|LOCK_NB);
3396     if (rv == 0) {
3397         return PR_SUCCESS;
3398     }
3399     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3400     return PR_FAILURE;
3401 }
3402 
3403 PRStatus
3404 _MD_UnlockFile(PRInt32 f)
3405 {
3406     PRInt32 rv;
3407     rv = flock(f, LOCK_UN);
3408     if (rv == 0) {
3409         return PR_SUCCESS;
3410     }
3411     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
3412     return PR_FAILURE;
3413 }
3414 #else
3415 
3416 PRStatus
3417 _MD_LockFile(PRInt32 f)
3418 {
3419     PRInt32 rv;
3420     rv = lockf(f, F_LOCK, 0);
3421     if (rv == 0) {
3422         return PR_SUCCESS;
3423     }
3424     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
3425     return PR_FAILURE;
3426 }
3427 
3428 PRStatus
3429 _MD_TLockFile(PRInt32 f)
3430 {
3431     PRInt32 rv;
3432     rv = lockf(f, F_TLOCK, 0);
3433     if (rv == 0) {
3434         return PR_SUCCESS;
3435     }
3436     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
3437     return PR_FAILURE;
3438 }
3439 
3440 PRStatus
3441 _MD_UnlockFile(PRInt32 f)
3442 {
3443     PRInt32 rv;
3444     rv = lockf(f, F_ULOCK, 0);
3445     if (rv == 0) {
3446         return PR_SUCCESS;
3447     }
3448     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
3449     return PR_FAILURE;
3450 }
3451 #endif
3452 
3453 PRStatus _MD_gethostname(char *name, PRUint32 namelen)
3454 {
3455     PRIntn rv;
3456 
3457     rv = gethostname(name, namelen);
3458     if (0 == rv) {
3459         return PR_SUCCESS;
3460     }
3461     _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
3462     return PR_FAILURE;
3463 }
3464 
3465 PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen)
3466 {
3467     struct utsname info;
3468 
3469     PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE) ||
3470               (cmd == PR_SI_RELEASE_BUILD));
3471 
3472     if (uname(&info) == -1) {
3473         _PR_MD_MAP_DEFAULT_ERROR(errno);
3474         return PR_FAILURE;
3475     }
3476     if (PR_SI_SYSNAME == cmd) {
3477         (void)PR_snprintf(name, namelen, info.sysname);
3478     }
3479     else if (PR_SI_RELEASE == cmd) {
3480         (void)PR_snprintf(name, namelen, info.release);
3481     }
3482     else if (PR_SI_RELEASE_BUILD == cmd) {
3483         (void)PR_snprintf(name, namelen, info.version);
3484     }
3485     else {
3486         return PR_FAILURE;
3487     }
3488     return PR_SUCCESS;
3489 }
3490 
3491 /*
3492  *******************************************************************
3493  *
3494  * Memory-mapped files
3495  *
3496  *******************************************************************
3497  */
3498 
3499 PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
3500 {
3501     PRFileInfo info;
3502     PRUint32 sz;
3503 
3504     LL_L2UI(sz, size);
3505     if (sz) {
3506         if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) {
3507             return PR_FAILURE;
3508         }
3509         if (sz > info.size) {
3510             /*
3511              * Need to extend the file
3512              */
3513             if (fmap->prot != PR_PROT_READWRITE) {
3514                 PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
3515                 return PR_FAILURE;
3516             }
3517             if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) {
3518                 return PR_FAILURE;
3519             }
3520             if (PR_Write(fmap->fd, "", 1) != 1) {
3521                 return PR_FAILURE;
3522             }
3523         }
3524     }
3525     if (fmap->prot == PR_PROT_READONLY) {
3526         fmap->md.prot = PROT_READ;
3527 #if defined(DARWIN) || defined(ANDROID)
3528         /*
3529          * This is needed on OS X because its implementation of
3530          * POSIX shared memory returns an error for MAP_PRIVATE, even
3531          * when the mapping is read-only.
3532          *
3533          * And this is needed on Android, because mapping ashmem with
3534          * MAP_PRIVATE creates a mapping of zeroed memory instead of
3535          * the shm contents.
3536          */
3537         fmap->md.flags = MAP_SHARED;
3538 #else
3539         fmap->md.flags = MAP_PRIVATE;
3540 #endif
3541     } else if (fmap->prot == PR_PROT_READWRITE) {
3542         fmap->md.prot = PROT_READ | PROT_WRITE;
3543         fmap->md.flags = MAP_SHARED;
3544     } else {
3545         PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
3546         fmap->md.prot = PROT_READ | PROT_WRITE;
3547         fmap->md.flags = MAP_PRIVATE;
3548     }
3549     return PR_SUCCESS;
3550 }
3551 
3552 void * _MD_MemMap(
3553     PRFileMap *fmap,
3554     PRInt64 offset,
3555     PRUint32 len)
3556 {
3557     PRInt32 off;
3558     void *addr;
3559 
3560     LL_L2I(off, offset);
3561     if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags,
3562                      fmap->fd->secret->md.osfd, off)) == (void *) -1) {
3563         _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
3564         addr = NULL;
3565     }
3566     return addr;
3567 }
3568 
3569 PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
3570 {
3571     if (munmap(addr, len) == 0) {
3572         return PR_SUCCESS;
3573     }
3574     _PR_MD_MAP_DEFAULT_ERROR(errno);
3575     return PR_FAILURE;
3576 }
3577 
3578 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
3579 {
3580     if ( PR_TRUE == fmap->md.isAnonFM ) {
3581         PRStatus rc = PR_Close( fmap->fd );
3582         if ( PR_FAILURE == rc ) {
3583             PR_LOG( _pr_io_lm, PR_LOG_DEBUG,
3584                     ("_MD_CloseFileMap(): error closing anonymnous file map osfd"));
3585             return PR_FAILURE;
3586         }
3587     }
3588     PR_DELETE(fmap);
3589     return PR_SUCCESS;
3590 }
3591 
3592 PRStatus _MD_SyncMemMap(
3593     PRFileDesc *fd,
3594     void *addr,
3595     PRUint32 len)
3596 {
3597     /* msync(..., MS_SYNC) alone is sufficient to flush modified data to disk
3598      * synchronously. It is not necessary to call fsync. */
3599     if (msync(addr, len, MS_SYNC) == 0) {
3600         return PR_SUCCESS;
3601     }
3602     _PR_MD_MAP_DEFAULT_ERROR(errno);
3603     return PR_FAILURE;
3604 }
3605 
3606 #if defined(_PR_NEED_FAKE_POLL)
3607 
3608 /*
3609  * Some platforms don't have poll().  For easier porting of code
3610  * that calls poll(), we emulate poll() using select().
3611  */
3612 
3613 int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
3614 {
3615     int i;
3616     int rv;
3617     int maxfd;
3618     fd_set rd, wr, ex;
3619     struct timeval tv, *tvp;
3620 
3621     if (timeout < 0 && timeout != -1) {
3622         errno = EINVAL;
3623         return -1;
3624     }
3625 
3626     if (timeout == -1) {
3627         tvp = NULL;
3628     } else {
3629         tv.tv_sec = timeout / 1000;
3630         tv.tv_usec = (timeout % 1000) * 1000;
3631         tvp = &tv;
3632     }
3633 
3634     maxfd = -1;
3635     FD_ZERO(&rd);
3636     FD_ZERO(&wr);
3637     FD_ZERO(&ex);
3638 
3639     for (i = 0; i < nfds; i++) {
3640         int osfd = filedes[i].fd;
3641         int events = filedes[i].events;
3642         PRBool fdHasEvent = PR_FALSE;
3643 
3644         if (osfd < 0) {
3645             continue;  /* Skip this osfd. */
3646         }
3647 
3648         /*
3649          * Map the poll events to the select fd_sets.
3650          *     POLLIN, POLLRDNORM  ===> readable
3651          *     POLLOUT, POLLWRNORM ===> writable
3652          *     POLLPRI, POLLRDBAND ===> exception
3653          *     POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
3654          *     are ignored.
3655          *
3656          * The output events POLLERR and POLLHUP are never turned on.
3657          * POLLNVAL may be turned on.
3658          */
3659 
3660         if (events & (POLLIN | POLLRDNORM)) {
3661             FD_SET(osfd, &rd);
3662             fdHasEvent = PR_TRUE;
3663         }
3664         if (events & (POLLOUT | POLLWRNORM)) {
3665             FD_SET(osfd, &wr);
3666             fdHasEvent = PR_TRUE;
3667         }
3668         if (events & (POLLPRI | POLLRDBAND)) {
3669             FD_SET(osfd, &ex);
3670             fdHasEvent = PR_TRUE;
3671         }
3672         if (fdHasEvent && osfd > maxfd) {
3673             maxfd = osfd;
3674         }
3675     }
3676 
3677     rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
3678 
3679     /* Compute poll results */
3680     if (rv > 0) {
3681         rv = 0;
3682         for (i = 0; i < nfds; i++) {
3683             PRBool fdHasEvent = PR_FALSE;
3684 
3685             filedes[i].revents = 0;
3686             if (filedes[i].fd < 0) {
3687                 continue;
3688             }
3689             if (FD_ISSET(filedes[i].fd, &rd)) {
3690                 if (filedes[i].events & POLLIN) {
3691                     filedes[i].revents |= POLLIN;
3692                 }
3693                 if (filedes[i].events & POLLRDNORM) {
3694                     filedes[i].revents |= POLLRDNORM;
3695                 }
3696                 fdHasEvent = PR_TRUE;
3697             }
3698             if (FD_ISSET(filedes[i].fd, &wr)) {
3699                 if (filedes[i].events & POLLOUT) {
3700                     filedes[i].revents |= POLLOUT;
3701                 }
3702                 if (filedes[i].events & POLLWRNORM) {
3703                     filedes[i].revents |= POLLWRNORM;
3704                 }
3705                 fdHasEvent = PR_TRUE;
3706             }
3707             if (FD_ISSET(filedes[i].fd, &ex)) {
3708                 if (filedes[i].events & POLLPRI) {
3709                     filedes[i].revents |= POLLPRI;
3710                 }
3711                 if (filedes[i].events & POLLRDBAND) {
3712                     filedes[i].revents |= POLLRDBAND;
3713                 }
3714                 fdHasEvent = PR_TRUE;
3715             }
3716             if (fdHasEvent) {
3717                 rv++;
3718             }
3719         }
3720         PR_ASSERT(rv > 0);
3721     } else if (rv == -1 && errno == EBADF) {
3722         rv = 0;
3723         for (i = 0; i < nfds; i++) {
3724             filedes[i].revents = 0;
3725             if (filedes[i].fd < 0) {
3726                 continue;
3727             }
3728             if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
3729                 filedes[i].revents = POLLNVAL;
3730                 rv++;
3731             }
3732         }
3733         PR_ASSERT(rv > 0);
3734     }
3735     PR_ASSERT(-1 != timeout || rv != 0);
3736 
3737     return rv;
3738 }
3739 #endif /* _PR_NEED_FAKE_POLL */
3740