LCOV - code coverage report
Current view: top level - nsprpub/pr/src/md/unix - unix.c (source / functions) Hit Total Coverage
Test: output.info Lines: 142 265 53.6 %
Date: 2017-07-14 16:53:18 Functions: 20 33 60.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13