LCOV - app.info - nsprpub/pr/src/md/unix/unix.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/md/unix - unix.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 260 | 36 | 13.8 %
| Date: | 2012-04-07 | Functions: | 33 | 5 | 15.2 %

           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               0 : PROffset32 _MD_lseek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
        2311                 : {
        2312                 :     PROffset32 rv, where;
        2313                 :
        2314               0 :     switch (whence) {
        2315                 :         case PR_SEEK_SET:
        2316               0 :             where = SEEK_SET;
        2317               0 :             break;
        2318                 :         case PR_SEEK_CUR:
        2319               0 :             where = SEEK_CUR;
        2320               0 :             break;
        2321                 :         case PR_SEEK_END:
        2322               0 :             where = SEEK_END;
        2323               0 :             break;
        2324                 :         default:
        2325               0 :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        2326               0 :             rv = -1;
        2327               0 :             goto done;
        2328                 :     }
        2329               0 :     rv = lseek(fd->secret->md.osfd,offset,where);
        2330               0 :     if (rv == -1)
        2331                 :     {
        2332               0 :         PRInt32 syserr = _MD_ERRNO();
        2333               0 :         _PR_MD_MAP_LSEEK_ERROR(syserr);
        2334                 :     }
        2335                 : done:
        2336               0 :     return(rv);
        2337                 : }
        2338                 :
        2339               0 : PROffset64 _MD_lseek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
        2340                 : {
        2341                 :     PRInt32 where;
        2342                 :     PROffset64 rv;
        2343                 :
        2344               0 :     switch (whence)
        2345                 :     {
        2346                 :         case PR_SEEK_SET:
        2347               0 :             where = SEEK_SET;
        2348               0 :             break;
        2349                 :         case PR_SEEK_CUR:
        2350               0 :             where = SEEK_CUR;
        2351               0 :             break;
        2352                 :         case PR_SEEK_END:
        2353               0 :             where = SEEK_END;
        2354               0 :             break;
        2355                 :         default:
        2356               0 :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        2357               0 :             rv = minus_one;
        2358               0 :             goto done;
        2359                 :     }
        2360               0 :     rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where);
        2361               0 :     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               0 :     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               0 : static void _MD_set_fileinfo_times(
        2539                 :     const struct stat *sb,
        2540                 :     PRFileInfo *info)
        2541                 : {
        2542                 :     PRInt64 s, s2us;
        2543               0 :     LL_I2L(s2us, PR_USEC_PER_SEC);
        2544               0 :     LL_I2L(s, sb->st_mtime);
        2545               0 :     LL_MUL(s, s, s2us);
        2546               0 :     info->modifyTime = s;
        2547               0 :     LL_I2L(s, sb->st_ctime);
        2548               0 :     LL_MUL(s, s, s2us);
        2549               0 :     info->creationTime = s;
        2550               0 : }
        2551                 :
        2552               0 : static void _MD_set_fileinfo64_times(
        2553                 :     const _MDStat64 *sb,
        2554                 :     PRFileInfo64 *info)
        2555                 : {
        2556                 :     PRInt64 s, s2us;
        2557               0 :     LL_I2L(s2us, PR_USEC_PER_SEC);
        2558               0 :     LL_I2L(s, sb->st_mtime);
        2559               0 :     LL_MUL(s, s, s2us);
        2560               0 :     info->modifyTime = s;
        2561               0 :     LL_I2L(s, sb->st_ctime);
        2562               0 :     LL_MUL(s, s, s2us);
        2563               0 :     info->creationTime = s;
        2564               0 : }
        2565                 : #else
        2566                 : #error "I don't know yet"
        2567                 : #endif
        2568                 :
        2569               0 : static int _MD_convert_stat_to_fileinfo(
        2570                 :     const struct stat *sb,
        2571                 :     PRFileInfo *info)
        2572                 : {
        2573               0 :     if (S_IFREG & sb->st_mode)
        2574               0 :         info->type = PR_FILE_FILE;
        2575               0 :     else if (S_IFDIR & sb->st_mode)
        2576               0 :         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               0 :     info->size = sb->st_size;
        2588                 :
        2589               0 :     _MD_set_fileinfo_times(sb, info);
        2590               0 :     return 0;
        2591                 : }  /* _MD_convert_stat_to_fileinfo */
        2592                 :
        2593               0 : static int _MD_convert_stat64_to_fileinfo64(
        2594                 :     const _MDStat64 *sb,
        2595                 :     PRFileInfo64 *info)
        2596                 : {
        2597               0 :     if (S_IFREG & sb->st_mode)
        2598               0 :         info->type = PR_FILE_FILE;
        2599               0 :     else if (S_IFDIR & sb->st_mode)
        2600               0 :         info->type = PR_FILE_DIRECTORY;
        2601                 :     else
        2602               0 :         info->type = PR_FILE_OTHER;
        2603                 :
        2604               0 :     LL_I2L(info->size, sb->st_size);
        2605                 :
        2606               0 :     _MD_set_fileinfo64_times(sb, info);
        2607               0 :     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               0 : PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
        2624                 : {
        2625                 :     _MDStat64 sb;
        2626               0 :     PRInt32 rv = _md_iovector._stat64(fn, &sb);
        2627               0 :     if (rv < 0)
        2628               0 :         _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
        2629               0 :     else if (NULL != info)
        2630               0 :         rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
        2631               0 :     return rv;
        2632                 : }
        2633                 :
        2634               0 : PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
        2635                 : {
        2636                 :     struct stat sb;
        2637               0 :     PRInt32 rv = fstat(fd->secret->md.osfd, &sb);
        2638               0 :     if (rv < 0)
        2639               0 :         _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
        2640               0 :     else if (NULL != info)
        2641               0 :         rv = _MD_convert_stat_to_fileinfo(&sb, info);
        2642               0 :     return rv;
        2643                 : }
        2644                 :
        2645               0 : PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
        2646                 : {
        2647                 :     _MDStat64 sb;
        2648               0 :     PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb);
        2649               0 :     if (rv < 0)
        2650               0 :         _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
        2651               0 :     else if (NULL != info)
        2652               0 :         rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
        2653               0 :     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           18667 : 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           18667 :     _md_iovector._open64 = open64;
        2828                 : #endif
        2829           18667 :     _md_iovector._mmap64 = mmap64;
        2830           18667 :     _md_iovector._fstat64 = fstat64;
        2831           18667 :     _md_iovector._stat64 = stat64;
        2832           18667 :     _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           18667 :     LL_I2L(minus_one, -1);
        2848           18667 : }  /* _PR_InitIOV */
        2849                 :
        2850           18667 : void _PR_UnixInit(void)
        2851                 : {
        2852                 :     struct sigaction sigact;
        2853                 :     int rv;
        2854                 :
        2855           18667 :     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           18667 :     sigact.sa_handler = SIG_IGN;
        2907           18667 :     sigemptyset(&sigact.sa_mask);
        2908           18667 :     sigact.sa_flags = 0;
        2909           18667 :     rv = sigaction(SIGPIPE, &sigact, 0);
        2910           18667 :     PR_ASSERT(0 == rv);
        2911                 : #endif /* HPUX && _PR_DCETHREADS */
        2912                 :
        2913           18667 :     _pr_rename_lock = PR_NewLock();
        2914           18667 :     PR_ASSERT(NULL != _pr_rename_lock);
        2915           18667 :     _pr_Xfe_mon = PR_NewMonitor();
        2916           18667 :     PR_ASSERT(NULL != _pr_Xfe_mon);
        2917                 :
        2918           18667 :     _PR_InitIOV();  /* one last hack */
        2919           18667 : }
        2920                 :
        2921               0 : void _PR_UnixCleanup(void)
        2922                 : {
        2923               0 :     if (_pr_rename_lock) {
        2924               0 :         PR_DestroyLock(_pr_rename_lock);
        2925               0 :         _pr_rename_lock = NULL;
        2926                 :     }
        2927               0 :     if (_pr_Xfe_mon) {
        2928               0 :         PR_DestroyMonitor(_pr_Xfe_mon);
        2929               0 :         _pr_Xfe_mon = NULL;
        2930                 :     }
        2931               0 : }
        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           18667 : PR_Now(void)
        3039                 : {
        3040                 :     struct timeval tv;
        3041                 :     PRInt64 s, us, s2us;
        3042                 :
        3043           18667 :     GETTIMEOFDAY(&tv);
        3044           18667 :     LL_I2L(s2us, PR_USEC_PER_SEC);
        3045           18667 :     LL_I2L(s, tv.tv_sec);
        3046           18667 :     LL_I2L(us, tv.tv_usec);
        3047           18667 :     LL_MUL(s, s, s2us);
        3048           18667 :     LL_ADD(s, s, us);
        3049           18667 :     return s;
        3050                 : }
        3051                 :
        3052           18666 : PRIntervalTime _PR_UNIX_GetInterval()
        3053                 : {
        3054                 :     struct timeval time;
        3055                 :     PRIntervalTime ticks;
        3056                 :
        3057           18666 :     (void)GETTIMEOFDAY(&time);  /* fallicy of course */
        3058           18666 :     ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC;  /* that's in milliseconds */
        3059           18666 :     ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC;  /* so's that */
        3060           18666 :     return ticks;
        3061                 : }  /* _PR_SUNOS_GetInterval */
        3062                 :
        3063           56000 : PRIntervalTime _PR_UNIX_TicksPerSecond()
        3064                 : {
        3065           56000 :     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               0 : 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               0 :     _PRSockLen_t optlen = sizeof(err);
        3343               0 :     if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
        3344               0 :         return errno;
        3345                 :     } else {
        3346               0 :         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               0 : PRStatus _MD_gethostname(char *name, PRUint32 namelen)
        3515                 : {
        3516                 :     PRIntn rv;
        3517                 :
        3518               0 :     rv = gethostname(name, namelen);
        3519               0 :     if (0 == rv) {
        3520               0 :         return PR_SUCCESS;
        3521                 :     }
        3522               0 :     _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
        3523               0 :     return PR_FAILURE;
        3524                 : }
        3525                 :
        3526               0 : PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen)
        3527                 : {
        3528                 :         struct utsname info;
        3529                 :
        3530               0 :         PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE));
        3531                 :
        3532               0 :         if (uname(&info) == -1) {
        3533               0 :                 _PR_MD_MAP_DEFAULT_ERROR(errno);
        3534               0 :         return PR_FAILURE;
        3535                 :         }
        3536               0 :         if (PR_SI_SYSNAME == cmd)
        3537               0 :                 (void)PR_snprintf(name, namelen, info.sysname);
        3538               0 :         else if (PR_SI_RELEASE == cmd)
        3539               0 :                 (void)PR_snprintf(name, namelen, info.release);
        3540                 :         else
        3541               0 :                 return PR_FAILURE;
        3542               0 :     return PR_SUCCESS;
        3543                 : }
        3544                 :
        3545                 : /*
        3546                 :  *******************************************************************
        3547                 :  *
        3548                 :  * Memory-mapped files
        3549                 :  *
        3550                 :  *******************************************************************
        3551                 :  */
        3552                 :
        3553               0 : PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
        3554                 : {
        3555                 :     PRFileInfo info;
        3556                 :     PRUint32 sz;
        3557                 :
        3558               0 :     LL_L2UI(sz, size);
        3559               0 :     if (sz) {
        3560               0 :         if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) {
        3561               0 :             return PR_FAILURE;
        3562                 :         }
        3563               0 :         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               0 :     if (fmap->prot == PR_PROT_READONLY) {
        3580               0 :         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               0 :         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               0 :     return PR_SUCCESS;
        3601                 : }
        3602                 :
        3603               0 : void * _MD_MemMap(
        3604                 :     PRFileMap *fmap,
        3605                 :     PRInt64 offset,
        3606                 :     PRUint32 len)
        3607                 : {
        3608                 :     PRInt32 off;
        3609                 :     void *addr;
        3610                 :
        3611               0 :     LL_L2I(off, offset);
        3612               0 :     if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags,
        3613               0 :         fmap->fd->secret->md.osfd, off)) == (void *) -1) {
        3614               0 :             _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
        3615               0 :         addr = NULL;
        3616                 :     }
        3617               0 :     return addr;
        3618                 : }
        3619                 :
        3620               0 : PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
        3621                 : {
        3622               0 :     if (munmap(addr, len) == 0) {
        3623               0 :         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               0 : PRStatus _MD_CloseFileMap(PRFileMap *fmap)
        3635                 : {
        3636               0 :     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               0 :     PR_DELETE(fmap);
        3645               0 :     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