LCOV - code coverage report
Current view: directory - nsprpub/pr/src/md/unix - unix.c (source / functions) Found Hit Coverage
Test: app.info Lines: 260 157 60.4 %
Date: 2012-06-02 Functions: 33 22 66.7 %

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

Generated by: LCOV version 1.7