home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / unix / unix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  80.4 KB  |  3,211 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "primpl.h"
  20.  
  21. #include <signal.h>
  22. #include <unistd.h>
  23. #include <memory.h>
  24. #include <fcntl.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/time.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/mman.h>
  30.  
  31. /* To get FIONREAD */
  32. #if defined(NCR) || defined(UNIXWARE) || defined(NEC) || defined(SNI) \
  33.         || defined(SONY)
  34. #include <sys/filio.h>
  35. #endif
  36.  
  37. /*
  38.  * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
  39.  * PRInt32* pointer to a _PRSockLen_t* pointer.
  40.  */
  41. #if defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \
  42.     || defined(AIX4_1) || defined(LINUX) || defined(SONY) \
  43.     || defined(BSDI) || defined(SCO) || defined(NEC) || defined(SNI) \
  44.     || defined(SUNOS4)
  45. #define _PRSockLen_t int
  46. #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
  47.     || defined(UNIXWARE)
  48. #define _PRSockLen_t size_t
  49. #else
  50. #error "Cannot determine architecture"
  51. #endif
  52.  
  53. /*
  54. ** Global lock variable used to bracket calls into rusty libraries that
  55. ** aren't thread safe (like libc, libX, etc).
  56. */
  57. static PRLock *_pr_rename_lock = NULL;
  58. static PRMonitor *_pr_Xfe_mon = NULL;
  59.  
  60. /*
  61.  * Variables used by the GC code, initialized in _MD_InitSegs().
  62.  * _pr_zero_fd should be a static variable.  Unfortunately, there is
  63.  * still some Unix-specific code left in function PR_GrowSegment()
  64.  * in file memory/prseg.c that references it, so it needs
  65.  * to be a global variable for now.
  66.  */
  67. PRInt32 _pr_zero_fd = -1;
  68. static PRLock *_pr_md_lock = NULL;
  69.  
  70. sigset_t timer_set;
  71.  
  72. #if !defined(_PR_PTHREADS)
  73.  
  74. static sigset_t empty_set;
  75.  
  76. #ifdef SOLARIS
  77. #include <sys/file.h>
  78. #include <sys/filio.h>
  79. #endif
  80.  
  81. #ifndef PIPE_BUF
  82. #define PIPE_BUF 512
  83. #endif
  84.  
  85. #ifndef PROT_NONE
  86. #define PROT_NONE 0
  87. #endif
  88.  
  89. /*
  90.  * _nspr_noclock - if set clock interrupts are disabled
  91.  */
  92. int _nspr_noclock = 0;
  93.  
  94. #ifdef IRIX
  95. extern PRInt32 _nspr_terminate_on_error;
  96. #endif
  97.  
  98. /*
  99.  * There is an assertion in this code that NSPR's definition of PRIOVec
  100.  * is bit compatible with UNIX' definition of a struct iovec. This is
  101.  * applicable to the 'writev()' operations where the types are casually
  102.  * cast to avoid warnings.
  103.  */
  104.  
  105. int _pr_md_pipefd[2] = { -1, -1 };
  106. static char _pr_md_pipebuf[PIPE_BUF];
  107.  
  108. _PRInterruptTable _pr_interruptTable[] = {
  109.     { 
  110.         "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt,     },
  111.     { 
  112.         0     }
  113. };
  114.  
  115. PR_IMPLEMENT(void) _MD_unix_init_running_cpu(_PRCPU *cpu)
  116. {
  117.     PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));
  118.     cpu->md.md_unix.ioq_max_osfd = -1;
  119.     cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
  120. }
  121.  
  122. PRStatus _MD_open_dir(_MDDir *d, const char *name)
  123. {
  124. int err;
  125.  
  126.     d->d = opendir(name);
  127.     if (!d->d) {
  128.         err = _MD_ERRNO();
  129.         _PR_MD_MAP_OPENDIR_ERROR(err);
  130.         return PR_FAILURE;
  131.     }
  132.     return PR_SUCCESS;
  133. }
  134.  
  135. PRInt32 _MD_close_dir(_MDDir *d)
  136. {
  137. int rv = 0, err;
  138.  
  139.     if (d->d) {
  140.         rv = closedir(d->d);
  141.         if (rv == -1) {
  142.                 err = _MD_ERRNO();
  143.                 _PR_MD_MAP_CLOSEDIR_ERROR(err);
  144.         }
  145.     }
  146.     return rv;
  147. }
  148.  
  149. char * _MD_read_dir(_MDDir *d, PRIntn flags)
  150. {
  151. struct dirent *de;
  152. int err;
  153.  
  154.     for (;;) {
  155.         /*
  156.           * XXX: readdir() is not MT-safe. There is an MT-safe version
  157.           * readdir_r() on some systems.
  158.           */
  159.         de = readdir(d->d);
  160.         if (!de) {
  161.             err = _MD_ERRNO();
  162.             _PR_MD_MAP_READDIR_ERROR(err);
  163.             return 0;
  164.         }        
  165.         if ((flags & PR_SKIP_DOT) &&
  166.             (de->d_name[0] == '.') && (de->d_name[1] == 0))
  167.             continue;
  168.         if ((flags & PR_SKIP_DOT_DOT) &&
  169.             (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
  170.             (de->d_name[2] == 0))
  171.             continue;
  172.         if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.'))
  173.             continue;
  174.         break;
  175.     }
  176.     return de->d_name;
  177. }
  178.  
  179. PRInt32 _MD_delete(const char *name)
  180. {
  181. PRInt32 rv, err;
  182. #ifdef UNIXWARE
  183.     sigset_t set, oset;
  184. #endif
  185.  
  186. #ifdef UNIXWARE
  187.     sigfillset(&set);
  188.     sigprocmask(SIG_SETMASK, &set, &oset);
  189. #endif
  190.     rv = unlink(name);
  191. #ifdef UNIXWARE
  192.     sigprocmask(SIG_SETMASK, &oset, NULL);
  193. #endif
  194.     if (rv == -1) {
  195.             err = _MD_ERRNO();
  196.             _PR_MD_MAP_UNLINK_ERROR(err);
  197.     }
  198.     return(rv);
  199. }
  200.  
  201. PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info)
  202. {
  203.     struct stat sb;
  204.     PRInt64 s, s2us;
  205.     PRInt32 rv, err;
  206.  
  207.     rv = stat(fn, &sb);
  208.     if (rv < 0) {
  209.             err = _MD_ERRNO();
  210.             _PR_MD_MAP_STAT_ERROR(err);
  211.     } else if (info) {
  212.         if (S_IFREG & sb.st_mode)
  213.             info->type = PR_FILE_FILE ;
  214.         else if (S_IFDIR & sb.st_mode)
  215.             info->type = PR_FILE_DIRECTORY;
  216.         else
  217.             info->type = PR_FILE_OTHER;
  218.         info->size = sb.st_size;
  219.         LL_I2L(s, sb.st_mtime);
  220.         LL_I2L(s2us, PR_USEC_PER_SEC);
  221.         LL_MUL(s, s, s2us);
  222.         info->modifyTime = s;
  223.         LL_I2L(s, sb.st_ctime);
  224.         LL_MUL(s, s, s2us);
  225.         info->creationTime = s;
  226.     }
  227.     return rv;
  228. }
  229.  
  230. PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
  231. {
  232.     PRFileInfo info32;
  233.     PRInt32 rv = _MD_getfileinfo(fn, &info32);
  234.     if (rv >= 0)
  235.     {
  236.         info->type = info32.type;
  237.         LL_I2L(info->size, info32.size);
  238.         info->modifyTime = info32.modifyTime;
  239.         info->creationTime = info32.creationTime;
  240.     }
  241.     return rv;
  242. }
  243.  
  244. PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
  245. {
  246.     struct stat sb;
  247.     PRInt64 s, s2us;
  248.     PRInt32 rv, err;
  249.  
  250.     rv = fstat(fd->secret->md.osfd, &sb);
  251.     if (rv < 0) {
  252.             err = _MD_ERRNO();
  253.             _PR_MD_MAP_FSTAT_ERROR(err);
  254.     } else if (info) {
  255.         if (info) {
  256.             if (S_IFREG & sb.st_mode)
  257.                 info->type = PR_FILE_FILE ;
  258.             else if (S_IFDIR & sb.st_mode)
  259.                 info->type = PR_FILE_DIRECTORY;
  260.             else
  261.                 info->type = PR_FILE_OTHER;
  262.             info->size = sb.st_size;
  263.             LL_I2L(s, sb.st_mtime);
  264.             LL_I2L(s2us, PR_USEC_PER_SEC);
  265.             LL_MUL(s, s, s2us);
  266.             info->modifyTime = s;
  267.             LL_I2L(s, sb.st_ctime);
  268.             LL_MUL(s, s, s2us);
  269.             info->creationTime = s;
  270.         }
  271.     }
  272.     return rv;
  273. }
  274.  
  275. PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
  276. {
  277.     PRFileInfo info32;
  278.     PRInt32 rv = _MD_getopenfileinfo(fd, &info32);
  279.     if (rv >= 0)
  280.     {
  281.         info->type = info32.type;
  282.         LL_I2L(info->size, info32.size);
  283.         info->modifyTime = info32.modifyTime;
  284.         info->creationTime = info32.creationTime;
  285.     }
  286.     return rv;
  287. }
  288.  
  289. PRInt32 _MD_rename(const char *from, const char *to)
  290. {
  291.     PRInt32 rv = -1, err;
  292.  
  293.     /*
  294.     ** This is trying to enforce the semantics of WINDOZE' rename
  295.     ** operation. That means one is not allowed to rename over top
  296.     ** of an existing file. Holding a lock across these two function
  297.     ** and the open function is known to be a bad idea, but ....
  298.     */
  299.     if (NULL != _pr_rename_lock)
  300.         PR_Lock(_pr_rename_lock);
  301.     if (0 == access(to, F_OK))
  302.         PR_SetError(PR_FILE_EXISTS_ERROR, 0);
  303.     else
  304.     {
  305.         rv = rename(from, to);
  306.         if (rv < 0) {
  307.             err = _MD_ERRNO();
  308.             _PR_MD_MAP_RENAME_ERROR(err);
  309.         }
  310.     }
  311.     if (NULL != _pr_rename_lock)
  312.         PR_Unlock(_pr_rename_lock);
  313.     return rv;
  314. }
  315.  
  316. PRInt32 _MD_access(const char *name, PRIntn how)
  317. {
  318. PRInt32 rv, err;
  319. int amode;
  320.  
  321.     switch (how) {
  322.         case PR_ACCESS_WRITE_OK:
  323.             amode = W_OK;
  324.             break;
  325.         case PR_ACCESS_READ_OK:
  326.             amode = R_OK;
  327.             break;
  328.         case PR_ACCESS_EXISTS:
  329.             amode = F_OK;
  330.             break;
  331.         default:
  332.             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  333.             rv = -1;
  334.             goto done;
  335.     }
  336.     rv = access(name, amode);
  337.  
  338.     if (rv < 0) {
  339.         err = _MD_ERRNO();
  340.         _PR_MD_MAP_ACCESS_ERROR(err);
  341.     }
  342.  
  343. done:
  344.     return(rv);
  345. }
  346.  
  347. PRInt32 _MD_mkdir(const char *name, PRIntn mode)
  348. {
  349. int rv, err;
  350.  
  351.     /*
  352.     ** This lock is used to enforce rename semantics as described
  353.     ** in PR_Rename. Look there for more fun details.
  354.     */
  355.     if (NULL !=_pr_rename_lock)
  356.         PR_Lock(_pr_rename_lock);
  357.     rv = mkdir(name, mode);
  358.     if (rv < 0) {
  359.         err = _MD_ERRNO();
  360.         _PR_MD_MAP_MKDIR_ERROR(err);
  361.     }
  362.     if (NULL !=_pr_rename_lock)
  363.         PR_Unlock(_pr_rename_lock);
  364.     return rv;
  365. }
  366.  
  367. PRInt32 _MD_rmdir(const char *name)
  368. {
  369. int rv, err;
  370.  
  371.     rv = rmdir(name);
  372.     if (rv == -1) {
  373.             err = _MD_ERRNO();
  374.             _PR_MD_MAP_RMDIR_ERROR(err);
  375.     }
  376.     return rv;
  377. }
  378.  
  379. PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)
  380. {
  381. PRThread *me = _PR_MD_CURRENT_THREAD();
  382. PRInt32 rv, err;
  383. fd_set rd;
  384. PRInt32 osfd = fd->secret->md.osfd;
  385.  
  386.     FD_ZERO(&rd);
  387.     FD_SET(osfd, &rd);
  388.     while ((rv = read(osfd,buf,amount)) == -1) {
  389.         err = _MD_ERRNO();
  390.         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
  391.             if (fd->secret->nonblocking) {
  392.                 break;
  393.             }
  394.             if (!_PR_IS_NATIVE_THREAD(me)) {
  395.                 _PR_WaitForFD(osfd, PR_POLL_READ, PR_INTERVAL_NO_TIMEOUT);
  396.             } else {
  397.                 while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
  398.                         == -1 && (err = _MD_ERRNO()) == EINTR) {
  399.                     /* retry _MD_SELECT() if it is interrupted */
  400.                 }
  401.                 if (rv == -1) {
  402.                     break;
  403.                 }
  404.             }
  405.             if (_PR_PENDING_INTERRUPT(me))
  406.                 break;
  407.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  408.             continue;
  409.         } else {
  410.             break;
  411.         }
  412.     }
  413.     if (rv < 0) {
  414.         if (_PR_PENDING_INTERRUPT(me)) {
  415.             me->flags &= ~_PR_INTERRUPT;
  416.             PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  417.         } else {
  418.             _PR_MD_MAP_READ_ERROR(err);
  419.         }
  420.     }
  421.     return(rv);
  422. }
  423.  
  424. PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
  425. {
  426. PRThread *me = _PR_MD_CURRENT_THREAD();
  427. PRInt32 rv, err;
  428. fd_set wd;
  429. PRInt32 osfd = fd->secret->md.osfd;
  430.  
  431.     FD_ZERO(&wd);
  432.     FD_SET(osfd, &wd);
  433.     while ((rv = write(osfd,buf,amount)) == -1) {
  434.         err = _MD_ERRNO();
  435.         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
  436.             if (fd->secret->nonblocking) {
  437.                 break;
  438.             }
  439.             if (!_PR_IS_NATIVE_THREAD(me)) {
  440.                 _PR_WaitForFD(osfd, PR_POLL_WRITE, PR_INTERVAL_NO_TIMEOUT);
  441.             } else {
  442.                 while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
  443.                         == -1 && (err = _MD_ERRNO()) == EINTR) {
  444.                     /* retry _MD_SELECT() if it is interrupted */
  445.                 }
  446.                 if (rv == -1) {
  447.                     break;
  448.                 }
  449.             }
  450.             if (_PR_PENDING_INTERRUPT(me))
  451.                 break;
  452.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  453.             continue;
  454.         } else {
  455.             break;
  456.         }
  457.     }
  458.     if (rv < 0) {
  459.         if (_PR_PENDING_INTERRUPT(me)) {
  460.             me->flags &= ~_PR_INTERRUPT;
  461.             PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  462.         } else {
  463.             _PR_MD_MAP_WRITE_ERROR(err);
  464.         }
  465.     }
  466.     return(rv);
  467. }
  468.  
  469. PRInt32 _MD_lseek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
  470. {
  471. PRInt32 rv, where, err;
  472.  
  473.     switch (whence) {
  474.         case PR_SEEK_SET:
  475.             where = SEEK_SET;
  476.             break;
  477.         case PR_SEEK_CUR:
  478.             where = SEEK_CUR;
  479.             break;
  480.         case PR_SEEK_END:
  481.             where = SEEK_END;
  482.             break;
  483.         default:
  484.             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  485.             rv = -1;
  486.             goto done;
  487.     }
  488.     rv = lseek(fd->secret->md.osfd,offset,where);
  489.     if (rv == -1) {
  490.             err = _MD_ERRNO();
  491.             _PR_MD_MAP_LSEEK_ERROR(err);
  492.     }
  493. done:
  494.     return(rv);
  495. }
  496.  
  497. PRInt64 _MD_lseek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
  498. {
  499.     PRInt32 off, rv;
  500.     PRInt64 on, result = LL_MININT;
  501.     LL_L2I(off, offset);
  502.     LL_I2L(on, off);
  503.     if (LL_EQ(offset, on))
  504.     {
  505.         rv = _MD_lseek(fd, off, whence);
  506.         if (rv >= 0) LL_I2L(result, rv);
  507.     }
  508.     else PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);  /* overflow */
  509.     return result;
  510. }  /* _MD_lseek64 */
  511.  
  512. PRInt32 _MD_fsync(PRFileDesc *fd)
  513. {
  514. PRInt32 rv, err;
  515.  
  516.     rv = fsync(fd->secret->md.osfd);
  517.     if (rv == -1) {
  518.         err = _MD_ERRNO();
  519.         _PR_MD_MAP_FSYNC_ERROR(err);
  520.     }
  521.     return(rv);
  522. }
  523.  
  524. PRInt32 _MD_close(PRInt32 osfd)
  525. {
  526. PRInt32 rv, err;
  527.  
  528.     rv = close(osfd);
  529.     if (rv == -1) {
  530.         err = _MD_ERRNO();
  531.         _PR_MD_MAP_CLOSE_ERROR(err);
  532.     }
  533.     return(rv);
  534. }
  535.  
  536. PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
  537. {
  538.     PRInt32 osfd, err;
  539.  
  540.     osfd = socket(domain, type, proto);
  541.  
  542.     if (osfd == -1) {
  543.         err = _MD_ERRNO();
  544.         _PR_MD_MAP_SOCKET_ERROR(err);
  545.         return(osfd);
  546.     }
  547.  
  548.     return(osfd);
  549. }
  550.  
  551. PRInt32 _MD_socketavailable(PRFileDesc *fd)
  552. {
  553.     PRInt32 result;
  554.  
  555.     if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
  556.         _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
  557.         return -1;
  558.     }
  559.     return result;
  560. }
  561.  
  562. PRInt64 _MD_socketavailable64(PRFileDesc *fd)
  563. {
  564.     PRInt64 result;
  565.     LL_I2L(result, _MD_socketavailable(fd));
  566.     return result;
  567. }  /* _MD_socketavailable64 */
  568.  
  569. #define READ_FD        1
  570. #define WRITE_FD    2
  571.  
  572. /*
  573.  * wait for socket i/o, periodically checking for interrupt
  574.  */
  575.  
  576. static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
  577.                                         PRIntervalTime timeout)
  578. {
  579.     PRInt32 rv = -1;
  580.     struct timeval tv, *tvp;
  581.     PRThread *me = _PR_MD_CURRENT_THREAD();
  582.     PRIntervalTime epoch, now, elapsed, remaining;
  583.     PRInt32 syserror;
  584.     fd_set rd_wr;
  585.  
  586.     switch (timeout) {
  587.         case PR_INTERVAL_NO_WAIT:
  588.             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  589.             break;
  590.         case PR_INTERVAL_NO_TIMEOUT:
  591.             /*
  592.              * This is a special case of the 'default' case below.
  593.              * Please see the comments there.
  594.              */
  595.             tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
  596.             tv.tv_usec = 0;
  597.             tvp = &tv;
  598.             FD_ZERO(&rd_wr);
  599.             do {
  600.                 FD_SET(osfd, &rd_wr);
  601.                 if (fd_type == READ_FD)
  602.                     rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
  603.                 else
  604.                     rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
  605.                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
  606.                     if (syserror == EBADF) {
  607.                         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
  608.                     } else {
  609.                         PR_SetError(PR_UNKNOWN_ERROR, syserror);
  610.                     }
  611.                     break;
  612.                 }
  613.                 if (_PR_PENDING_INTERRUPT(me)) {
  614.                     me->flags &= ~_PR_INTERRUPT;
  615.                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  616.                     rv = -1;
  617.                     break;
  618.                 }
  619.             } while (rv == 0 || (rv == -1 && syserror == EINTR));
  620.             break;
  621.         default:
  622.             now = epoch = PR_IntervalNow();
  623.             remaining = timeout;
  624.             tvp = &tv;
  625.             FD_ZERO(&rd_wr);
  626.             do {
  627.                 /*
  628.                  * We block in _MD_SELECT for at most
  629.                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
  630.                  * so that there is an upper limit on the delay
  631.                  * before the interrupt bit is checked.
  632.                  */
  633.                 tv.tv_sec = PR_IntervalToSeconds(remaining);
  634.                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
  635.                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
  636.                     tv.tv_usec = 0;
  637.                 } else {
  638.                     tv.tv_usec = PR_IntervalToMicroseconds(
  639.                         remaining -
  640.                         PR_SecondsToInterval(tv.tv_sec));
  641.                 }
  642.                 FD_SET(osfd, &rd_wr);
  643.                 if (fd_type == READ_FD)
  644.                     rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
  645.                 else
  646.                     rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
  647.                 /*
  648.                  * we don't consider EINTR a real error
  649.                  */
  650.                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
  651.                     if (syserror == EBADF) {
  652.                         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
  653.                     } else {
  654.                         PR_SetError(PR_UNKNOWN_ERROR, syserror);
  655.                     }
  656.                     break;
  657.                 }
  658.                 if (_PR_PENDING_INTERRUPT(me)) {
  659.                     me->flags &= ~_PR_INTERRUPT;
  660.                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  661.                     rv = -1;
  662.                     break;
  663.                 }
  664.                 /*
  665.                  * We loop again if _MD_SELECT timed out or got interrupted
  666.                  * by a signal, and the timeout deadline has not passed yet.
  667.                  */
  668.                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
  669.                     /*
  670.                      * If _MD_SELECT timed out, we know how much time
  671.                      * we spent in blocking, so we can avoid a
  672.                      * PR_IntervalNow() call.
  673.                      */
  674.                     if (rv == 0) {
  675.                         now += PR_SecondsToInterval(tv.tv_sec)
  676.                             + PR_MicrosecondsToInterval(tv.tv_usec);
  677.                     } else {
  678.                         now = PR_IntervalNow();
  679.                     }
  680.                     elapsed = (PRIntervalTime) (now - epoch);
  681.                     if (elapsed >= timeout) {
  682.                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  683.                         rv = -1;
  684.                         break;
  685.                     } else {
  686.                         remaining = timeout - elapsed;
  687.                     }
  688.                 }
  689.             } while (rv == 0 || (rv == -1 && syserror == EINTR));
  690.             break;
  691.     }
  692.     return(rv);
  693. }
  694.  
  695. PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
  696.                                 PRInt32 flags, PRIntervalTime timeout)
  697. {
  698.     PRInt32 osfd = fd->secret->md.osfd;
  699.     PRInt32 rv, err;
  700.     PRThread *me = _PR_MD_CURRENT_THREAD();
  701.  
  702. /*
  703.  * Many OS's (Solaris, Unixware) have a broken recv which won't read
  704.  * from socketpairs.  As long as we don't use flags on socketpairs, this
  705.  * is a decent fix. - mikep
  706.  */
  707. #if defined(UNIXWARE) || defined(SOLARIS) || defined(NCR)
  708.         while ((rv = read(osfd,buf,amount)) == -1) {
  709. /*
  710.         while ((rv = recv(osfd,buf,amount,flags)) == -1) {
  711. */
  712. #else
  713.     while ((rv = recv(osfd,buf,amount,flags)) == -1) {
  714. #endif
  715.         err = _MD_ERRNO();
  716.         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
  717.             if (fd->secret->nonblocking) {
  718.                 break;
  719.             }
  720.             if (!_PR_IS_NATIVE_THREAD(me)) {
  721.                 if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  722.                     rv = -1;
  723.                     if (_PR_PENDING_INTERRUPT(me)) {
  724.                         me->flags &= ~_PR_INTERRUPT;
  725.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  726.                     } else
  727.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  728.                     goto done;
  729.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  730.                     me->flags &= ~_PR_INTERRUPT;
  731.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  732.                     rv = -1;
  733.                     goto done;
  734.                 }
  735.             } else {
  736.                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
  737.                     goto done;
  738.             }
  739.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  740.             continue;
  741.         } else {
  742.             break;
  743.         }
  744.     }
  745.     if (rv < 0) {
  746.         _PR_MD_MAP_RECV_ERROR(err);
  747.     }
  748. done:
  749.     return(rv);
  750. }
  751.  
  752. PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
  753.                         PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
  754.                         PRIntervalTime timeout)
  755. {
  756.     PRInt32 osfd = fd->secret->md.osfd;
  757.     PRInt32 rv, err;
  758.     PRThread *me = _PR_MD_CURRENT_THREAD();
  759.  
  760.     while ((*addrlen = PR_NETADDR_SIZE(addr)),
  761.                 ((rv = recvfrom(osfd, buf, amount, flags,
  762.                         (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {
  763.         err = _MD_ERRNO();
  764.         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
  765.             if (fd->secret->nonblocking) {
  766.                 break;
  767.             }
  768.             if (!_PR_IS_NATIVE_THREAD(me)) {
  769.                 if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  770.                     rv = -1;
  771.                     if (_PR_PENDING_INTERRUPT(me)) {
  772.                         me->flags &= ~_PR_INTERRUPT;
  773.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  774.                     } else
  775.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  776.                     goto done;
  777.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  778.                     me->flags &= ~_PR_INTERRUPT;
  779.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  780.                     rv = -1;
  781.                     goto done;
  782.                 }
  783.             } else {
  784.                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
  785.                     goto done;
  786.             }
  787.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  788.             continue;
  789.         } else {
  790.             break;
  791.         }
  792.     }
  793.     if (rv < 0) {
  794.         _PR_MD_MAP_RECVFROM_ERROR(err);
  795.     }
  796. done:
  797. #ifdef AIX
  798.     if (rv != -1) {
  799.         /* mask off the first byte of struct sockaddr (the length field) */
  800.         if (addr) {
  801.             addr->inet.family &= 0x00ff;
  802.         }
  803.     }
  804. #endif
  805.     return(rv);
  806. }
  807.  
  808. PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
  809.                             PRInt32 flags, PRIntervalTime timeout)
  810. {
  811.     PRInt32 osfd = fd->secret->md.osfd;
  812.     PRInt32 rv, err;
  813.     PRThread *me = _PR_MD_CURRENT_THREAD();
  814.  
  815.     while ((rv = send(osfd,buf,amount,flags)) == -1) {
  816.         err = _MD_ERRNO();
  817.         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
  818.             if (fd->secret->nonblocking) {
  819.                 break;
  820.             }
  821.             if (!_PR_IS_NATIVE_THREAD(me)) {
  822.                 if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  823.                     rv = -1;
  824.                     if (_PR_PENDING_INTERRUPT(me)) {
  825.                         me->flags &= ~_PR_INTERRUPT;
  826.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  827.                     } else
  828.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  829.                     goto done;
  830.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  831.                     me->flags &= ~_PR_INTERRUPT;
  832.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  833.                     rv = -1;
  834.                     goto done;
  835.                 }
  836.             } else {
  837.                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
  838.                     goto done;
  839.             }
  840.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  841.             continue;
  842.         } else {
  843.             break;
  844.         }
  845.     }
  846.         /*
  847.          * optimization; if bytes sent is less than "amount" call
  848.          * select before returning. This is because it is likely that
  849.          * the next send() call will return EWOULDBLOCK.
  850.          */
  851.     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
  852.             && (timeout != PR_INTERVAL_NO_WAIT)) {
  853.         if (_PR_IS_NATIVE_THREAD(me)) {
  854.             if (socket_io_wait(osfd, WRITE_FD, timeout)< 0)
  855.                     goto done;
  856.         } else {
  857.             if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  858.                     rv = -1;
  859.                     if (_PR_PENDING_INTERRUPT(me)) {
  860.                         me->flags &= ~_PR_INTERRUPT;
  861.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  862.                     } else
  863.                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  864.                     goto done;
  865.             }
  866.         }
  867.     }
  868.     if (rv < 0) {
  869.         _PR_MD_MAP_SEND_ERROR(err);
  870.     }
  871. done:
  872.     return(rv);
  873. }
  874.  
  875. PRInt32 _MD_sendto(
  876.     PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  877.     const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
  878. {
  879.     PRInt32 osfd = fd->secret->md.osfd;
  880.     PRInt32 rv, err;
  881.     PRThread *me = _PR_MD_CURRENT_THREAD();
  882.  
  883.     while ((rv = sendto(osfd, buf, amount, flags,
  884.             (struct sockaddr *) addr, addrlen)) == -1) {
  885.         err = _MD_ERRNO();
  886.         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
  887.             if (fd->secret->nonblocking) {
  888.                 break;
  889.             }
  890.             if (!_PR_IS_NATIVE_THREAD(me)) {
  891.                 if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  892.                     rv = -1;
  893.                     if (_PR_PENDING_INTERRUPT(me)) {
  894.                         me->flags &= ~_PR_INTERRUPT;
  895.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  896.                     } else
  897.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  898.                     goto done;
  899.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  900.                     me->flags &= ~_PR_INTERRUPT;
  901.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  902.                     rv = -1;
  903.                     goto done;
  904.                 }
  905.             } else {
  906.                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
  907.                     goto done;
  908.             }
  909.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  910.             continue;
  911.         } else {
  912.             break;
  913.         }
  914.     }
  915.     if (rv < 0) {
  916.         _PR_MD_MAP_SENDTO_ERROR(err);
  917.     }
  918. done:
  919.     return(rv);
  920. }
  921.  
  922. PRInt32 _MD_writev(PRFileDesc *fd, PRIOVec *iov,
  923.                                     PRInt32 iov_size, PRIntervalTime timeout)
  924. {
  925.     PRInt32 rv, err;
  926.     PRThread *me = _PR_MD_CURRENT_THREAD();
  927.     PRInt32 index, amount = 0;
  928.     PRInt32 osfd = fd->secret->md.osfd;
  929.  
  930.     /*
  931.      * Calculate the total number of bytes to be sent; needed for
  932.      * optimization later.
  933.      * We could avoid this if this number was passed in; but it is
  934.      * probably not a big deal because iov_size is usually small (less than
  935.      * 3)
  936.      */
  937.     if (!fd->secret->nonblocking) {
  938.         for (index=0; index<iov_size; index++) {
  939.             amount += iov[index].iov_len;
  940.         }
  941.     }
  942.  
  943.     while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
  944.         err = _MD_ERRNO();
  945.         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
  946.             if (fd->secret->nonblocking) {
  947.                 break;
  948.             }
  949.             if (!_PR_IS_NATIVE_THREAD(me)) {
  950.                 if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  951.                     rv = -1;
  952.                     if (_PR_PENDING_INTERRUPT(me)) {
  953.                         me->flags &= ~_PR_INTERRUPT;
  954.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  955.                     } else
  956.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  957.                     goto done;
  958.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  959.                     me->flags &= ~_PR_INTERRUPT;
  960.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  961.                     rv = -1;
  962.                     goto done;
  963.                 }
  964.             } else {
  965.                 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
  966.                     goto done;
  967.             }
  968.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  969.             continue;
  970.         } else {
  971.             break;
  972.         }
  973.     }
  974.     /*
  975.      * optimization; if bytes sent is less than "amount" call
  976.      * select before returning. This is because it is likely that
  977.      * the next writev() call will return EWOULDBLOCK.
  978.      */
  979.     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
  980.             && (timeout != PR_INTERVAL_NO_WAIT)) {
  981.         if (_PR_IS_NATIVE_THREAD(me)) {
  982.             if (socket_io_wait(osfd, WRITE_FD, timeout) < 0)
  983.                     goto done;
  984.         } else {
  985.             if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  986.                     rv = -1;
  987.                     if (_PR_PENDING_INTERRUPT(me)) {
  988.                         me->flags &= ~_PR_INTERRUPT;
  989.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  990.                     } else
  991.                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  992.                     goto done;
  993.             }
  994.         }
  995.     }
  996.     if (rv < 0) {
  997.         _PR_MD_MAP_WRITEV_ERROR(err);
  998.     }
  999. done:
  1000.     return(rv);
  1001. }
  1002.  
  1003. PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr,
  1004.                             PRUint32 *addrlen, PRIntervalTime timeout)
  1005. {
  1006.     PRInt32 osfd = fd->secret->md.osfd;
  1007.     PRInt32 rv, err;
  1008.     PRThread *me = _PR_MD_CURRENT_THREAD();
  1009.  
  1010.     while ((rv = accept(osfd, (struct sockaddr *) addr,
  1011.                                         (_PRSockLen_t *)addrlen)) == -1) {
  1012.         err = _MD_ERRNO();
  1013.         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
  1014.             if (fd->secret->nonblocking) {
  1015.                 break;
  1016.             }
  1017.             if (!_PR_IS_NATIVE_THREAD(me)) {
  1018.                 if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  1019.                     rv = -1;
  1020.                     if (_PR_PENDING_INTERRUPT(me)) {
  1021.                         me->flags &= ~_PR_INTERRUPT;
  1022.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  1023.                     } else
  1024.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  1025.                     goto done;
  1026.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  1027.                     me->flags &= ~_PR_INTERRUPT;
  1028.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  1029.                     rv = -1;
  1030.                     goto done;
  1031.                 }
  1032.             } else {
  1033.                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
  1034.                     goto done;
  1035.             }
  1036.         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
  1037.             continue;
  1038.         } else {
  1039.             break;
  1040.         }
  1041.     }
  1042.     if (rv < 0) {
  1043.         _PR_MD_MAP_ACCEPT_ERROR(err);
  1044.     }
  1045. done:
  1046. #ifdef AIX
  1047.     if (rv != -1) {
  1048.         /* mask off the first byte of struct sockaddr (the length field) */
  1049.         if (addr) {
  1050.             addr->inet.family &= 0x00ff;
  1051.         }
  1052.     }
  1053. #endif
  1054.     return(rv);
  1055. }
  1056.  
  1057. extern int _connect (int s, const struct sockaddr *name, int namelen);
  1058. PRInt32 _MD_connect(
  1059.     PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
  1060. {
  1061.     PRInt32 rv, err;
  1062.     PRThread *me = _PR_MD_CURRENT_THREAD();
  1063.     PRInt32 osfd = fd->secret->md.osfd;
  1064. #ifdef IRIX
  1065. extern PRInt32 _MD_irix_connect(
  1066.         PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);
  1067. #endif
  1068.  
  1069.     /*
  1070.      * We initiate the connection setup by making a nonblocking connect()
  1071.      * call.  If the connect() call fails, there are two cases we handle
  1072.      * specially:
  1073.      * 1. The connect() call was interrupted by a signal.  In this case
  1074.      *    we simply retry connect().
  1075.      * 2. The NSPR socket is nonblocking and connect() fails with
  1076.      *    EINPROGRESS.  We first wait until the socket becomes writable.
  1077.      *    Then we try to find out whether the connection setup succeeded
  1078.      *    or failed.
  1079.      */
  1080.  
  1081. retry:
  1082. #ifdef IRIX
  1083.     if ((rv = _MD_irix_connect(osfd, addr, addrlen, timeout)) == -1) {
  1084. #else
  1085.     if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
  1086. #endif
  1087.         err = _MD_ERRNO();
  1088.  
  1089.         if (err == EINTR) {
  1090.             if (_PR_PENDING_INTERRUPT(me)) {
  1091.                 me->flags &= ~_PR_INTERRUPT;
  1092.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  1093.                 return -1;
  1094.             }
  1095.             goto retry;
  1096.         }
  1097.  
  1098.         if (!fd->secret->nonblocking && (err == EINPROGRESS)) {
  1099.             if (!_PR_IS_NATIVE_THREAD(me)) {
  1100.                 /*
  1101.                  * _PR_WaitForFD() may return 0 (timeout or interrupt) or 1.
  1102.                  */
  1103.  
  1104.                 rv = _PR_WaitForFD(osfd, PR_POLL_WRITE, timeout);
  1105.                 if (rv == 0) {
  1106.                     if (_PR_PENDING_INTERRUPT(me)) {
  1107.                         me->flags &= ~_PR_INTERRUPT;
  1108.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  1109.                     } else {
  1110.                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  1111.                     }
  1112.                     return -1;
  1113.                 }
  1114.             } else {
  1115.                 /*
  1116.                  * socket_io_wait() may return -1 or 1.
  1117.                  */
  1118.  
  1119.                 rv = socket_io_wait(osfd, WRITE_FD, timeout);
  1120.                 if (rv == -1) {
  1121.                     return -1;
  1122.                 }
  1123.             }
  1124.  
  1125.             PR_ASSERT(rv == 1);
  1126.             if (_PR_PENDING_INTERRUPT(me)) {
  1127.                 me->flags &= ~_PR_INTERRUPT;
  1128.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  1129.                 return -1;
  1130.             }
  1131.             err = _MD_unix_get_nonblocking_connect_error(osfd);
  1132.             if (err != 0) {
  1133.                 _PR_MD_MAP_CONNECT_ERROR(err);
  1134.                 return -1;
  1135.             }
  1136.             return 0;
  1137.         }
  1138.  
  1139.         _PR_MD_MAP_CONNECT_ERROR(err);
  1140.     }
  1141.  
  1142.     return rv;
  1143. }  /* _MD_connect */
  1144.  
  1145. PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
  1146. {
  1147.     PRInt32 rv, err;
  1148.  
  1149.     rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
  1150.     if (rv < 0) {
  1151.         err = _MD_ERRNO();
  1152.         _PR_MD_MAP_BIND_ERROR(err);
  1153.     }
  1154.     return(rv);
  1155. }
  1156.  
  1157. PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
  1158. {
  1159.     PRInt32 rv, err;
  1160.  
  1161.     rv = listen(fd->secret->md.osfd, backlog);
  1162.     if (rv < 0) {
  1163.         err = _MD_ERRNO();
  1164.         _PR_MD_MAP_LISTEN_ERROR(err);
  1165.     }
  1166.     return(rv);
  1167. }
  1168.  
  1169. PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how)
  1170. {
  1171.     PRInt32 rv, err;
  1172.  
  1173.     rv = shutdown(fd->secret->md.osfd, how);
  1174.     if (rv < 0) {
  1175.         err = _MD_ERRNO();
  1176.         _PR_MD_MAP_SHUTDOWN_ERROR(err);
  1177.     }
  1178.     return(rv);
  1179. }
  1180.  
  1181. PRInt32 _MD_socketpair(int af, int type, int flags,
  1182.                                                         PRInt32 *osfd)
  1183. {
  1184.     PRInt32 rv, err;
  1185.  
  1186.     rv = socketpair(af, type, flags, osfd);
  1187.     if (rv < 0) {
  1188.         err = _MD_ERRNO();
  1189.         _PR_MD_MAP_SOCKETPAIR_ERROR(err);
  1190.     }
  1191.     return rv;
  1192. }
  1193.  
  1194. PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
  1195.                                                 PRUint32 *addrlen)
  1196. {
  1197.     PRInt32 rv, err;
  1198.  
  1199.     rv = getsockname(fd->secret->md.osfd,
  1200.             (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
  1201. #ifdef AIX
  1202.     if (rv == 0) {
  1203.         /* mask off the first byte of struct sockaddr (the length field) */
  1204.         if (addr) {
  1205.             addr->inet.family &= 0x00ff;
  1206.         }
  1207.     }
  1208. #endif
  1209.     if (rv < 0) {
  1210.         err = _MD_ERRNO();
  1211.         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
  1212.     }
  1213.     return rv==0?PR_SUCCESS:PR_FAILURE;
  1214. }
  1215.  
  1216. PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
  1217.                                         PRUint32 *addrlen)
  1218. {
  1219.     PRInt32 rv, err;
  1220.  
  1221.     rv = getpeername(fd->secret->md.osfd,
  1222.             (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
  1223. #ifdef AIX
  1224.     if (rv == 0) {
  1225.         /* mask off the first byte of struct sockaddr (the length field) */
  1226.         if (addr) {
  1227.             addr->inet.family &= 0x00ff;
  1228.         }
  1229.     }
  1230. #endif
  1231.     if (rv < 0) {
  1232.         err = _MD_ERRNO();
  1233.         _PR_MD_MAP_GETPEERNAME_ERROR(err);
  1234.     }
  1235.     return rv==0?PR_SUCCESS:PR_FAILURE;
  1236. }
  1237.  
  1238. PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
  1239.                         PRInt32 optname, char* optval, PRInt32* optlen)
  1240. {
  1241.     PRInt32 rv, err;
  1242.  
  1243.     rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);
  1244.     if (rv < 0) {
  1245.         err = _MD_ERRNO();
  1246.         _PR_MD_MAP_GETSOCKOPT_ERROR(err);
  1247.     }
  1248.     return rv==0?PR_SUCCESS:PR_FAILURE;
  1249. }
  1250.  
  1251. PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,   
  1252.                     PRInt32 optname, const char* optval, PRInt32 optlen)
  1253. {
  1254.     PRInt32 rv, err;
  1255.  
  1256.     rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
  1257.     if (rv < 0) {
  1258.         err = _MD_ERRNO();
  1259.         _PR_MD_MAP_SETSOCKOPT_ERROR(err);
  1260.     }
  1261.     return rv==0?PR_SUCCESS:PR_FAILURE;
  1262. }
  1263.  
  1264. PR_IMPLEMENT(PRInt32) _MD_pr_poll(PRPollDesc *pds, PRIntn npds,
  1265.                         PRIntervalTime timeout)
  1266. {
  1267.     PRPollDesc *pd, *epd;
  1268.     PRPollQueue pq;
  1269.     PRInt32 n, err, pdcnt;
  1270.     PRIntn is;
  1271.     _PRUnixPollDesc *unixpds, *unixpd;
  1272.     _PRCPU *io_cpu;
  1273.     PRThread *me = _PR_MD_CURRENT_THREAD();
  1274.  
  1275.     if (_PR_IS_NATIVE_THREAD(me)) {
  1276.         fd_set rd, wt, ex;
  1277.         struct timeval tv, *tvp = NULL;
  1278.         int maxfd = -1;
  1279.         /*
  1280.          * For restarting _MD_SELECT() if it is interrupted by a signal.
  1281.          * We use these variables to figure out how much time has elapsed
  1282.          * and how much of the timeout still remains.
  1283.          */
  1284.         PRIntervalTime start, elapsed, remaining;
  1285.  
  1286.         FD_ZERO(&rd);
  1287.         FD_ZERO(&wt);
  1288.         FD_ZERO(&ex);
  1289.  
  1290.         for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1291.             PRInt32 osfd;
  1292.             PRInt16 in_flags = pd->in_flags;
  1293.             PRFileDesc *bottom = pd->fd;
  1294.  
  1295.             if ((NULL == bottom) || (in_flags == 0)) {
  1296.                 continue;
  1297.             }
  1298.             while (bottom->lower != NULL) {
  1299.                 bottom = bottom->lower;
  1300.             }
  1301.             osfd = bottom->secret->md.osfd;
  1302.  
  1303.             if (osfd > maxfd) {
  1304.                 maxfd = osfd;
  1305.             }
  1306.             if (in_flags & PR_POLL_READ)  {
  1307.                 FD_SET(osfd, &rd);
  1308.             }
  1309.             if (in_flags & PR_POLL_WRITE) {
  1310.                 FD_SET(osfd, &wt);
  1311.             }
  1312.             if (in_flags & PR_POLL_EXCEPT) {
  1313.                 FD_SET(osfd, &ex);
  1314.             }
  1315.         }
  1316.         if (timeout != PR_INTERVAL_NO_TIMEOUT) {
  1317.             tv.tv_sec = PR_IntervalToSeconds(timeout);
  1318.             tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
  1319.             tvp = &tv;
  1320.             start = PR_IntervalNow();
  1321.         }
  1322.         
  1323. retry:
  1324.         n = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
  1325.         if (n == -1 && errno == EINTR) {
  1326.             if (timeout == PR_INTERVAL_NO_TIMEOUT) {
  1327.                 goto retry;
  1328.             } else {
  1329.                 elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
  1330.                 if (elapsed > timeout) {
  1331.                     n = 0;  /* timed out */
  1332.                 } else {
  1333.                     remaining = timeout - elapsed;
  1334.                     tv.tv_sec = PR_IntervalToSeconds(remaining);
  1335.                     tv.tv_usec = PR_IntervalToMicroseconds(
  1336.                         remaining - PR_SecondsToInterval(tv.tv_sec));
  1337.                     goto retry;
  1338.                 }
  1339.             }
  1340.         }
  1341.         
  1342.         if (n > 0) {
  1343.             n = 0;
  1344.             for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1345.                 PRInt32 osfd;
  1346.                 PRInt16 in_flags = pd->in_flags;
  1347.                 PRInt16 out_flags = 0;
  1348.                 PRFileDesc *bottom = pd->fd;
  1349.  
  1350.                 if ((NULL == bottom) || (in_flags == 0)) {
  1351.                     pd->out_flags = 0;
  1352.                     continue;
  1353.                 }
  1354.                 while (bottom->lower != NULL) {
  1355.                     bottom = bottom->lower;
  1356.                 }
  1357.                 osfd = bottom->secret->md.osfd;
  1358.  
  1359.                 if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd))  {
  1360.                     out_flags |= PR_POLL_READ;
  1361.                 }
  1362.                 if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
  1363.                     out_flags |= PR_POLL_WRITE;
  1364.                 }
  1365.                 if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
  1366.                     out_flags |= PR_POLL_EXCEPT;
  1367.                 }
  1368.                 pd->out_flags = out_flags;
  1369.                 if (out_flags) {
  1370.                     n++;
  1371.                 }
  1372.             }
  1373.             PR_ASSERT(n > 0);
  1374.         } else if (n < 0) {
  1375.             err = _MD_ERRNO();
  1376.             if (err == EBADF) {
  1377.                 /* Find the bad fds */
  1378.                 n = 0;
  1379.                 for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1380.                     PRFileDesc *bottom = pd->fd;
  1381.                     pd->out_flags = 0;
  1382.                     if ((NULL == bottom) || (pd->in_flags == 0)) {
  1383.                         continue;
  1384.                     }
  1385.                     while (bottom->lower != NULL) {
  1386.                         bottom = bottom->lower;
  1387.                     }
  1388.                     if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) {
  1389.                             pd->out_flags = PR_POLL_NVAL;
  1390.                             n++;
  1391.                     }
  1392.                 }
  1393.                 PR_ASSERT(n > 0);
  1394.             } else {
  1395.                 PR_ASSERT(err != EINTR);  /* should have been handled above */
  1396.                 _PR_MD_MAP_SELECT_ERROR(err);
  1397.             }
  1398.         }
  1399.  
  1400.         return n;
  1401.     }
  1402.  
  1403.     /*
  1404.      * XXX
  1405.      *        PRPollDesc has a PRFileDesc field, fd, while the IOQ
  1406.      *        is a list of PRPollQueue structures, each of which contains
  1407.      *        a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
  1408.      *        the OS file descriptor, osfd, and not a PRFileDesc.
  1409.      *        So, we have allocate memory for _PRUnixPollDesc structures,
  1410.      *        copy the flags information from the pds list and have pq
  1411.      *        point to this list of _PRUnixPollDesc structures.
  1412.      *
  1413.      *        It would be better if the memory allocation can be avoided.
  1414.      */
  1415.  
  1416.     unixpds = (_PRUnixPollDesc*) PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
  1417.     if (!unixpds) {
  1418.         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  1419.            return -1;
  1420.     }
  1421.     unixpd = unixpds;
  1422.  
  1423.     _PR_INTSOFF(is);
  1424.     _PR_MD_IOQ_LOCK();
  1425.        _PR_THREAD_LOCK(me);
  1426.  
  1427.     if (_PR_PENDING_INTERRUPT(me)) {
  1428.         me->flags &= ~_PR_INTERRUPT;
  1429.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  1430.         _PR_THREAD_UNLOCK(me);
  1431.         _PR_MD_IOQ_UNLOCK();
  1432.         _PR_FAST_INTSON(is);
  1433.         PR_DELETE(unixpds);
  1434.            return -1;
  1435.     }
  1436.  
  1437.     pdcnt = 0;
  1438.     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1439.         PRInt32 osfd;
  1440.         PRInt16 in_flags = pd->in_flags;
  1441.         PRFileDesc *bottom = pd->fd;
  1442.  
  1443.         if ((NULL == bottom) || (in_flags == 0)) {
  1444.             continue;
  1445.         }
  1446.         while (bottom->lower != NULL) {
  1447.             bottom = bottom->lower;
  1448.         }
  1449.         osfd = bottom->secret->md.osfd;
  1450.  
  1451.         PR_ASSERT(osfd >= 0 || in_flags == 0);
  1452.  
  1453.         unixpd->osfd = osfd;
  1454.         unixpd->in_flags = pd->in_flags;
  1455.         unixpd++;
  1456.         pdcnt++;
  1457.  
  1458.         if (in_flags & PR_POLL_READ)  {
  1459.             FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
  1460.             _PR_FD_READ_CNT(me->cpu)[osfd]++;
  1461.         }
  1462.         if (in_flags & PR_POLL_WRITE) {
  1463.             FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
  1464.             (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
  1465.         }
  1466.         if (in_flags & PR_POLL_EXCEPT) {
  1467.             FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  1468.             (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
  1469.         }
  1470.         if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
  1471.             _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
  1472.     }
  1473.     if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
  1474.         _PR_IOQ_TIMEOUT(me->cpu) = timeout;
  1475.  
  1476.  
  1477.     pq.pds = unixpds;
  1478.     pq.npds = pdcnt;
  1479.  
  1480.     pq.thr = me;
  1481.     io_cpu = me->cpu;
  1482.     pq.on_ioq = PR_TRUE;
  1483.     pq.timeout = timeout;
  1484.     _PR_ADD_TO_IOQ(pq, me->cpu);
  1485.     _PR_SLEEPQ_LOCK(me->cpu);
  1486.     _PR_ADD_SLEEPQ(me, timeout);
  1487.     me->state = _PR_IO_WAIT;
  1488.     me->io_pending = PR_TRUE;
  1489.     me->io_suspended = PR_FALSE;
  1490.     _PR_SLEEPQ_UNLOCK(me->cpu);
  1491.     _PR_THREAD_UNLOCK(me);
  1492.     _PR_MD_IOQ_UNLOCK();
  1493.  
  1494.     _PR_MD_WAIT(me, timeout);
  1495.  
  1496.     me->io_pending = PR_FALSE;
  1497.     me->io_suspended = PR_FALSE;
  1498.  
  1499.     /*
  1500.      * This thread should run on the same cpu on which it was blocked; when 
  1501.      * the IO request times out the fd sets and fd counts for the
  1502.      * cpu are updated below.
  1503.      */
  1504.     PR_ASSERT(me->cpu == io_cpu);
  1505.     /*
  1506.      * Copy the out_flags from the _PRUnixPollDesc structures to the
  1507.      * user's PRPollDesc structures and free the allocated memory
  1508.      */
  1509.     unixpd = unixpds;
  1510.     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1511.         if ((NULL == pd->fd) || (pd->in_flags == 0)) {
  1512.             pd->out_flags = 0;
  1513.             continue;
  1514.         }
  1515.         pd->out_flags = unixpd->out_flags;
  1516.         unixpd++;
  1517.     }
  1518.     PR_DELETE(unixpds);
  1519.  
  1520.     /*
  1521.     ** If we timed out the pollq might still be on the ioq. Remove it
  1522.     ** before continuing.
  1523.     */
  1524.     if (pq.on_ioq) {
  1525.         _PR_MD_IOQ_LOCK();
  1526.         /*
  1527.          * Need to check pq.on_ioq again
  1528.          */
  1529.         if (pq.on_ioq == PR_TRUE) {
  1530.             PR_REMOVE_LINK(&pq.links);
  1531.             for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1532.                 PRInt32 osfd;
  1533.                 PRInt16 in_flags = pd->in_flags;
  1534.                 PRFileDesc *bottom = pd->fd;
  1535.  
  1536.                 if ((NULL == bottom) || (in_flags == 0)) {
  1537.                     continue;
  1538.                 }
  1539.                 while (bottom->lower != NULL) {
  1540.                     bottom = bottom->lower;
  1541.                 }
  1542.                 osfd = bottom->secret->md.osfd;
  1543.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  1544.                 if (in_flags & PR_POLL_READ)  {
  1545.                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  1546.                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  1547.                 }
  1548.                 if (in_flags & PR_POLL_WRITE) {
  1549.                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  1550.                             FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  1551.                 }
  1552.                 if (in_flags & PR_POLL_EXCEPT) {
  1553.                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  1554.                             FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  1555.                 }
  1556.             }
  1557.         }
  1558.         _PR_MD_IOQ_UNLOCK();
  1559.     }
  1560.     _PR_INTSON(is);
  1561.     if (_PR_PENDING_INTERRUPT(me)) {
  1562.         me->flags &= ~_PR_INTERRUPT;
  1563.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  1564.            return -1;
  1565.     } else {
  1566.         n = 0;
  1567.         if (pq.on_ioq == PR_FALSE) {
  1568.             /* Count the number of ready descriptors */
  1569.             while (--npds >= 0) {
  1570.             if (pds->out_flags) {
  1571.                 n++;
  1572.             }
  1573.                 pds++;
  1574.             }
  1575.         }
  1576.         return n;
  1577.     }
  1578. }
  1579.  
  1580.  
  1581.  
  1582.  
  1583. /************************************************************************/
  1584.  
  1585. /*
  1586. ** Scan through io queue and find any bad fd's that triggered the error
  1587. ** from _MD_SELECT
  1588. */
  1589. static void FindBadFDs(void)
  1590. {
  1591.     PRCList *q;
  1592.     PRThread *me = _MD_CURRENT_THREAD();
  1593.  
  1594.     PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
  1595.     q = (_PR_IOQ(me->cpu)).next;
  1596.     _PR_IOQ_MAX_OSFD(me->cpu) = -1;
  1597.     _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
  1598.     while (q != &_PR_IOQ(me->cpu)) {
  1599.         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  1600.         PRBool notify = PR_FALSE;
  1601.         _PRUnixPollDesc *pds = pq->pds;
  1602.         _PRUnixPollDesc *epds = pds + pq->npds;
  1603.         PRInt32 pq_max_osfd = -1;
  1604.  
  1605.         q = q->next;
  1606.         for (; pds < epds; pds++) {
  1607.             PRInt32 osfd = pds->osfd;
  1608.             pds->out_flags = 0;
  1609.             PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
  1610.             if (pds->in_flags == 0) {
  1611.                 continue;  /* skip this fd */
  1612.             }
  1613.             if (fcntl(osfd, F_GETFL, 0) == -1) {
  1614.                 /* Found a bad descriptor, remove it from the fd_sets. */
  1615.                 PR_LOG(_pr_io_lm, PR_LOG_MAX,
  1616.                     ("file descriptor %d is bad", osfd));
  1617.                 pds->out_flags = PR_POLL_NVAL;
  1618.                 notify = PR_TRUE;
  1619.             }
  1620.             if (osfd > pq_max_osfd) {
  1621.                 pq_max_osfd = osfd;
  1622.             }
  1623.         }
  1624.  
  1625.         if (notify) {
  1626.             PRIntn pri;
  1627.             PR_REMOVE_LINK(&pq->links);
  1628.             pq->on_ioq = PR_FALSE;
  1629.  
  1630.             /*
  1631.          * Decrement the count of descriptors for each desciptor/event
  1632.          * because this I/O request is being removed from the
  1633.          * ioq
  1634.          */
  1635.             pds = pq->pds;
  1636.             for (; pds < epds; pds++) {
  1637.                 PRInt32 osfd = pds->osfd;
  1638.                 PRInt16 in_flags = pds->in_flags;
  1639.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  1640.                 if (in_flags & PR_POLL_READ) {
  1641.                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  1642.                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  1643.                 }
  1644.                 if (in_flags & PR_POLL_WRITE) {
  1645.                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  1646.                         FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  1647.                 }
  1648.                 if (in_flags & PR_POLL_EXCEPT) {
  1649.                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  1650.                         FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  1651.                 }
  1652.             }
  1653.  
  1654.             _PR_THREAD_LOCK(pq->thr);
  1655.             if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
  1656.                 _PRCPU *cpu = pq->thr->cpu;
  1657.                 _PR_SLEEPQ_LOCK(pq->thr->cpu);
  1658.                 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
  1659.                 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
  1660.  
  1661.                 pri = pq->thr->priority;
  1662.                 pq->thr->state = _PR_RUNNABLE;
  1663.  
  1664.                 _PR_RUNQ_LOCK(cpu);
  1665.                 _PR_ADD_RUNQ(pq->thr, cpu, pri);
  1666.                 _PR_RUNQ_UNLOCK(cpu);
  1667.             }
  1668.             _PR_THREAD_UNLOCK(pq->thr);
  1669.         } else {
  1670.             if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
  1671.                 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
  1672.             if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
  1673.                 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
  1674.         }
  1675.     }
  1676.     if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
  1677.         if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
  1678.             _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
  1679.     }
  1680. }
  1681.  
  1682. /************************************************************************/
  1683.  
  1684. /*
  1685. ** Called by the scheduler when there is nothing to do. This means that
  1686. ** all threads are blocked on some monitor somewhere.
  1687. **
  1688. ** Note: this code doesn't release the scheduler lock.
  1689. */
  1690. /*
  1691. ** Pause the current CPU. longjmp to the cpu's pause stack
  1692. **
  1693. ** This must be called with the scheduler locked
  1694. */
  1695. void _MD_PauseCPU(PRIntervalTime ticks)
  1696. {
  1697.     PRThread *me = _MD_CURRENT_THREAD();
  1698. #ifdef _PR_USE_POLL
  1699.     int timeout;
  1700.     struct pollfd *pollfds;    /* an array of pollfd structures */
  1701.     struct pollfd *pollfdPtr;    /* a pointer that steps through the array */
  1702.     unsigned long npollfds;     /* number of pollfd structures in array */
  1703.     int nfd;                    /* to hold the return value of poll() */
  1704. #else
  1705.     struct timeval timeout, *tvp;
  1706.     fd_set r, w, e;
  1707.     fd_set *rp, *wp, *ep;
  1708.     PRInt32 max_osfd, nfd;
  1709. #endif  /* _PR_USE_POLL */
  1710.     PRInt32 rv;
  1711.     PRCList *q;
  1712.     PRUint32 min_timeout;
  1713.     sigset_t oldset;
  1714. #ifdef IRIX
  1715. extern sigset_t ints_off;
  1716. #endif
  1717.  
  1718.     PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
  1719.  
  1720.     _PR_MD_IOQ_LOCK();
  1721.  
  1722. #ifdef _PR_USE_POLL
  1723.     /* Build up the pollfd structure array to wait on */
  1724.  
  1725.     /* Find out how many pollfd structures are needed */
  1726.     npollfds = 0;
  1727.     for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
  1728.         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  1729.  
  1730.         npollfds += pq->npds;
  1731.     }
  1732.     /*
  1733.      * We use a pipe to wake up a native thread.  An fd is needed
  1734.      * for the pipe and we poll it for reading.
  1735.      */
  1736.     if (_PR_IS_NATIVE_THREAD_SUPPORTED())
  1737.         npollfds++;
  1738.  
  1739.     pollfds = (struct pollfd *) PR_MALLOC(npollfds * sizeof(struct pollfd));
  1740.     pollfdPtr = pollfds;
  1741.  
  1742.     /*
  1743.      * If we need to poll the pipe for waking up a native thread,
  1744.      * the pipe's fd is the first element in the pollfds array.
  1745.      */
  1746.     if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
  1747.         pollfdPtr->fd = _pr_md_pipefd[0];
  1748.         pollfdPtr->events = PR_POLL_READ;
  1749.         pollfdPtr++;
  1750.     }
  1751.  
  1752.     min_timeout = PR_INTERVAL_NO_TIMEOUT;
  1753.     for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
  1754.         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  1755.         _PRUnixPollDesc *pds = pq->pds;
  1756.         _PRUnixPollDesc *epds = pds + pq->npds;
  1757.  
  1758.         if (pq->timeout < min_timeout) {
  1759.             min_timeout = pq->timeout;
  1760.         }
  1761.         for (; pds < epds; pds++, pollfdPtr++) {
  1762.             /*
  1763.          * Assert that the pollfdPtr pointer does not go
  1764.          * beyond the end of the pollfds array
  1765.          */
  1766.             PR_ASSERT(pollfdPtr < pollfds + npollfds);
  1767.             pollfdPtr->fd = pds->osfd;
  1768.             /* direct copy of poll flags */
  1769.             pollfdPtr->events = pds->in_flags;
  1770.         }
  1771.     }
  1772. #else
  1773.     /*
  1774.      * assigment of fd_sets
  1775.      */
  1776.     r = _PR_FD_READ_SET(me->cpu);
  1777.     w = _PR_FD_WRITE_SET(me->cpu);
  1778.     e = _PR_FD_EXCEPTION_SET(me->cpu);
  1779.  
  1780.     rp = &r;
  1781.     wp = &w;
  1782.     ep = &e;
  1783.  
  1784.     max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
  1785.     min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
  1786. #endif  /* _PR_USE_POLL */
  1787.     /*
  1788.     ** Compute the minimum timeout value: make it the smaller of the
  1789.     ** timeouts specified by the i/o pollers or the timeout of the first
  1790.     ** sleeping thread.
  1791.     */
  1792.     q = _PR_SLEEPQ(me->cpu).next;
  1793.  
  1794.     if (q != &_PR_SLEEPQ(me->cpu)) {
  1795.         PRThread *t = _PR_THREAD_PTR(q);
  1796.  
  1797.         if (t->sleep < min_timeout) {
  1798.             min_timeout = t->sleep;
  1799.         }
  1800.     }
  1801.     if (min_timeout > ticks) {
  1802.         min_timeout = ticks;
  1803.     }
  1804.  
  1805. #ifdef _PR_USE_POLL
  1806.     if (min_timeout == PR_INTERVAL_NO_TIMEOUT)
  1807.         timeout = -1;
  1808.     else
  1809.         timeout = PR_IntervalToMilliseconds(min_timeout);
  1810. #else
  1811.     if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
  1812.         tvp = NULL;
  1813.     } else {
  1814.         timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
  1815.         timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
  1816.             % PR_USEC_PER_SEC;
  1817.         tvp = &timeout;
  1818.     }
  1819. #endif  /* _PR_USE_POLL */
  1820.  
  1821.     _PR_MD_IOQ_UNLOCK();
  1822.     _MD_CHECK_FOR_EXIT();
  1823.     /*
  1824.      * check for i/o operations
  1825.      */
  1826. #ifndef _PR_NO_CLOCK_TIMER
  1827.     /*
  1828.      * Disable the clock interrupts while we are in select, if clock interrupts
  1829.      * are enabled. Otherwise, when the select/poll calls are interrupted, the
  1830.      * timer value starts ticking from zero again when the system call is restarted.
  1831.      */
  1832. #ifdef IRIX
  1833.     /*
  1834.      * SIGCHLD signal is used on Irix to detect he termination of an
  1835.      * sproc by SIGSEGV, SIGBUS or SIGABRT signals when
  1836.      * _nspr_terminate_on_error is set.
  1837.      */
  1838.     if ((!_nspr_noclock) || (_nspr_terminate_on_error))
  1839. #else
  1840.         if (!_nspr_noclock)
  1841. #endif    /* IRIX */
  1842. #ifdef IRIX
  1843.     sigprocmask(SIG_BLOCK, &ints_off, &oldset);
  1844. #else
  1845.     PR_ASSERT(sigismember(&timer_set, SIGALRM));
  1846.     sigprocmask(SIG_BLOCK, &timer_set, &oldset);
  1847. #endif    /* IRIX */
  1848. #endif  /* !_PR_NO_CLOCK_TIMER */
  1849.  
  1850. #ifndef _PR_USE_POLL
  1851.     PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));
  1852.     nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
  1853. #else
  1854.     nfd = _MD_POLL(pollfds, npollfds, timeout);
  1855. #endif  /* !_PR_USE_POLL */
  1856.  
  1857. #ifndef _PR_NO_CLOCK_TIMER
  1858. #ifdef IRIX
  1859.     if ((!_nspr_noclock) || (_nspr_terminate_on_error))
  1860. #else
  1861.         if (!_nspr_noclock)
  1862. #endif    /* IRIX */
  1863.     sigprocmask(SIG_SETMASK, &oldset, 0);
  1864. #endif  /* !_PR_NO_CLOCK_TIMER */
  1865.  
  1866.     _MD_CHECK_FOR_EXIT();
  1867.     _PR_MD_IOQ_LOCK();
  1868.     /*
  1869.     ** Notify monitors that are associated with the selected descriptors.
  1870.     */
  1871. #ifdef _PR_USE_POLL
  1872.     if (nfd > 0) {
  1873.         pollfdPtr = pollfds;
  1874.         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
  1875.             /*
  1876.          * Assert that the pipe is the first element in the
  1877.          * pollfds array.
  1878.          */
  1879.             PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);
  1880.             if ((pollfds[0].revents & PR_POLL_READ) && (nfd == 1)) {
  1881.                 /*
  1882.          * woken up by another thread; read all the data
  1883.          * in the pipe to empty the pipe
  1884.          */
  1885.                 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,
  1886.                     PIPE_BUF)) == PIPE_BUF){
  1887.                 }
  1888.                 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));
  1889.             }
  1890.             pollfdPtr++;
  1891.         }
  1892.         for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
  1893.             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  1894.             PRBool notify = PR_FALSE;
  1895.             _PRUnixPollDesc *pds = pq->pds;
  1896.             _PRUnixPollDesc *epds = pds + pq->npds;
  1897.  
  1898.             for (; pds < epds; pds++, pollfdPtr++) {
  1899.                 /*
  1900.          * Assert that the pollfdPtr pointer does not go beyond
  1901.          * the end of the pollfds array.
  1902.          */
  1903.                 PR_ASSERT(pollfdPtr < pollfds + npollfds);
  1904.                 /*
  1905.          * Assert that the fd's in the pollfds array (stepped
  1906.          * through by pollfdPtr) are in the same order as
  1907.          * the fd's in _PR_IOQ() (stepped through by q and pds).
  1908.          * This is how the pollfds array was created earlier.
  1909.          */
  1910.                 PR_ASSERT(pollfdPtr->fd == pds->osfd);
  1911.                 pds->out_flags = pollfdPtr->revents;
  1912.                 /* Negative fd's are ignored by poll() */
  1913.                 if (pds->osfd >= 0 && pds->out_flags) {
  1914.                     notify = PR_TRUE;
  1915.                 }
  1916.             }
  1917.             if (notify) {
  1918.                 PRIntn pri;
  1919.                 PRThread *thred;
  1920.  
  1921.                 PR_REMOVE_LINK(&pq->links);
  1922.                 pq->on_ioq = PR_FALSE;
  1923.  
  1924.                 /*
  1925.                  * Because this thread can run on a different cpu right
  1926.                  * after being added to the run queue, do not dereference
  1927.                  * pq
  1928.                  */
  1929.                  thred = pq->thr;
  1930.                 _PR_THREAD_LOCK(thred);
  1931.                 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
  1932.                     _PRCPU *cpu = pq->thr->cpu;
  1933.                     _PR_SLEEPQ_LOCK(pq->thr->cpu);
  1934.                     _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
  1935.                     _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
  1936.  
  1937.                     pri = pq->thr->priority;
  1938.                     pq->thr->state = _PR_RUNNABLE;
  1939.  
  1940.                     _PR_RUNQ_LOCK(cpu);
  1941.                     _PR_ADD_RUNQ(pq->thr, cpu, pri);
  1942.                     _PR_RUNQ_UNLOCK(cpu);
  1943.                     if (_pr_md_idle_cpus > 1)
  1944.                         _PR_MD_WAKEUP_WAITER(thred);
  1945.                 }
  1946.                 _PR_THREAD_UNLOCK(thred);
  1947.             }
  1948.         }
  1949.     } else if (nfd == -1) {
  1950.         PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
  1951.     }
  1952.  
  1953.     /* done with pollfds */
  1954.     PR_DELETE(pollfds);
  1955. #else
  1956.     if (nfd > 0) {
  1957.         q = _PR_IOQ(me->cpu).next;
  1958.         _PR_IOQ_MAX_OSFD(me->cpu) = -1;
  1959.         _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
  1960.         while (q != &_PR_IOQ(me->cpu)) {
  1961.             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  1962.             PRBool notify = PR_FALSE;
  1963.             _PRUnixPollDesc *pds = pq->pds;
  1964.             _PRUnixPollDesc *epds = pds + pq->npds;
  1965.             PRInt32 pq_max_osfd = -1;
  1966.  
  1967.             q = q->next;
  1968.             for (; pds < epds; pds++) {
  1969.                 PRInt32 osfd = pds->osfd;
  1970.                 PRInt16 in_flags = pds->in_flags;
  1971.                 PRInt16 out_flags = 0;
  1972.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  1973.                 if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, rp)) {
  1974.                     out_flags |= PR_POLL_READ;
  1975.                 }
  1976.                 if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, wp)) {
  1977.                     out_flags |= PR_POLL_WRITE;
  1978.                 }
  1979.                 if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
  1980.                     out_flags |= PR_POLL_EXCEPT;
  1981.                 }
  1982.                 pds->out_flags = out_flags;
  1983.                 if (out_flags) {
  1984.                     notify = PR_TRUE;
  1985.                 }
  1986.                 if (osfd > pq_max_osfd) {
  1987.                     pq_max_osfd = osfd;
  1988.                 }
  1989.             }
  1990.             if (notify == PR_TRUE) {
  1991.                 PRIntn pri;
  1992.                 PRThread *thred;
  1993.  
  1994.                 PR_REMOVE_LINK(&pq->links);
  1995.                 pq->on_ioq = PR_FALSE;
  1996.  
  1997.                 /*
  1998.                  * Decrement the count of descriptors for each desciptor/event
  1999.                  * because this I/O request is being removed from the
  2000.                  * ioq
  2001.                  */
  2002.                 pds = pq->pds;
  2003.                 for (; pds < epds; pds++) {
  2004.                     PRInt32 osfd = pds->osfd;
  2005.                     PRInt16 in_flags = pds->in_flags;
  2006.                     PR_ASSERT(osfd >= 0 || in_flags == 0);
  2007.                     if (in_flags & PR_POLL_READ) {
  2008.                         if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  2009.                             FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  2010.                     }
  2011.                     if (in_flags & PR_POLL_WRITE) {
  2012.                         if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  2013.                             FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  2014.                     }
  2015.                     if (in_flags & PR_POLL_EXCEPT) {
  2016.                         if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  2017.                             FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  2018.                     }
  2019.                 }
  2020.  
  2021.                 /*
  2022.                  * Because this thread can run on a different cpu right
  2023.                  * after being added to the run queue, do not dereference
  2024.                  * pq
  2025.                  */
  2026.                  thred = pq->thr;
  2027.                 _PR_THREAD_LOCK(thred);
  2028.                 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
  2029.                     _PRCPU *cpu = thred->cpu;
  2030.                     _PR_SLEEPQ_LOCK(pq->thr->cpu);
  2031.                     _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
  2032.                     _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
  2033.  
  2034.                     pri = pq->thr->priority;
  2035.                     pq->thr->state = _PR_RUNNABLE;
  2036.  
  2037.                     pq->thr->cpu = cpu;
  2038.                     _PR_RUNQ_LOCK(cpu);
  2039.                     _PR_ADD_RUNQ(pq->thr, cpu, pri);
  2040.                     _PR_RUNQ_UNLOCK(cpu);
  2041.                     if (_pr_md_idle_cpus > 1)
  2042.                         _PR_MD_WAKEUP_WAITER(thred);
  2043.                 }
  2044.                 _PR_THREAD_UNLOCK(thred);
  2045.             } else {
  2046.                 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
  2047.                     _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
  2048.                 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
  2049.                     _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
  2050.             }
  2051.         }
  2052.         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
  2053.             if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {
  2054.                 /*
  2055.              * woken up by another thread; read all the data
  2056.              * in the pipe to empty the pipe
  2057.              */
  2058.                 while ((rv =
  2059.                     read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
  2060.                     == PIPE_BUF){
  2061.                 }
  2062.                 PR_ASSERT((rv > 0) ||
  2063.                     ((rv == -1) && (errno == EAGAIN)));
  2064.             }
  2065.             if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
  2066.                 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
  2067.         }
  2068.     } else if (nfd < 0) {
  2069.         if (errno == EBADF) {
  2070.             FindBadFDs();
  2071.         } else {
  2072.             PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
  2073.                 errno));
  2074.         }
  2075.     } else {
  2076.         PR_ASSERT(nfd == 0);
  2077.         /*
  2078.          * compute the new value of _PR_IOQ_TIMEOUT
  2079.          */
  2080.         q = _PR_IOQ(me->cpu).next;
  2081.         _PR_IOQ_MAX_OSFD(me->cpu) = -1;
  2082.         _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
  2083.         while (q != &_PR_IOQ(me->cpu)) {
  2084.             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  2085.             _PRUnixPollDesc *pds = pq->pds;
  2086.             _PRUnixPollDesc *epds = pds + pq->npds;
  2087.             PRInt32 pq_max_osfd = -1;
  2088.  
  2089.             q = q->next;
  2090.             for (; pds < epds; pds++) {
  2091.                 if (pds->osfd > pq_max_osfd) {
  2092.                     pq_max_osfd = pds->osfd;
  2093.                 }
  2094.             }
  2095.             if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
  2096.                 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
  2097.             if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
  2098.                 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
  2099.         }
  2100.         if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
  2101.             if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
  2102.                 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
  2103.         }
  2104.     }
  2105. #endif  /* _PR_USE_POLL */
  2106.     _PR_MD_IOQ_UNLOCK();
  2107. }
  2108.  
  2109. void _MD_Wakeup_CPUs()
  2110. {
  2111.     PRInt32 rv, data;
  2112.  
  2113.     data = 0;
  2114.     rv = write(_pr_md_pipefd[1], &data, 1);
  2115.  
  2116.     while ((rv < 0) && (errno == EAGAIN)) {
  2117.         /*
  2118.          * pipe full, read all data in pipe to empty it
  2119.          */
  2120.         while ((rv =
  2121.             read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
  2122.             == PIPE_BUF) {
  2123.         }
  2124.         PR_ASSERT((rv > 0) ||
  2125.             ((rv == -1) && (errno == EAGAIN)));
  2126.         rv = write(_pr_md_pipefd[1], &data, 1);
  2127.     }
  2128. }
  2129.  
  2130.  
  2131. void _MD_InitCPUS()
  2132. {
  2133.     PRInt32 rv, flags;
  2134.     PRThread *me = _MD_CURRENT_THREAD();
  2135.  
  2136.     rv = pipe(_pr_md_pipefd);
  2137.     PR_ASSERT(rv == 0);
  2138.     _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
  2139.     FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
  2140.  
  2141.     flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
  2142.     fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
  2143.     flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
  2144.     fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
  2145. }
  2146.  
  2147. /*
  2148. ** Unix SIGALRM (clock) signal handler
  2149. */
  2150. static void ClockInterruptHandler()
  2151. {
  2152.     int olderrno;
  2153.     PRUintn pri;
  2154.     _PRCPU *cpu = _PR_MD_CURRENT_CPU();
  2155.     PRThread *me = _MD_CURRENT_THREAD();
  2156.  
  2157. #ifdef SOLARIS
  2158.     if (!me || _PR_IS_NATIVE_THREAD(me)) {
  2159.         _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;
  2160.         return;
  2161.     }
  2162. #endif
  2163.  
  2164.     if (_PR_MD_GET_INTSOFF() != 0) {
  2165.         cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
  2166.         return;
  2167.     }
  2168.     _PR_MD_SET_INTSOFF(1);
  2169.  
  2170.     olderrno = errno;
  2171.     _PR_ClockInterrupt();
  2172.     errno = olderrno;
  2173.  
  2174.     /*
  2175.     ** If the interrupt wants a resched or if some other thread at
  2176.     ** the same priority needs the cpu, reschedule.
  2177.     */
  2178.     pri = me->priority;
  2179.     if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {
  2180. #ifdef _PR_NO_PREEMPT
  2181.         cpu->resched = PR_TRUE;
  2182.         if (pr_interruptSwitchHook) {
  2183.             (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);
  2184.         }
  2185. #else /* _PR_NO_PREEMPT */
  2186.         /*
  2187.     ** Re-enable unix interrupts (so that we can use
  2188.     ** setjmp/longjmp for context switching without having to
  2189.     ** worry about the signal state)
  2190.     */
  2191.         sigprocmask(SIG_SETMASK, &empty_set, 0);
  2192.         PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));
  2193.  
  2194.         if(!(me->flags & _PR_IDLE_THREAD)) {
  2195.             _PR_THREAD_LOCK(me);
  2196.             me->state = _PR_RUNNABLE;
  2197.             me->cpu = cpu;
  2198.             _PR_RUNQ_LOCK(cpu);
  2199.             _PR_ADD_RUNQ(me, cpu, pri);
  2200.             _PR_RUNQ_UNLOCK(cpu);
  2201.             _PR_THREAD_UNLOCK(me);
  2202.         } else
  2203.             me->state = _PR_RUNNABLE;
  2204.         _MD_SWITCH_CONTEXT(me);
  2205.         PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));
  2206. #endif /* _PR_NO_PREEMPT */
  2207.     }
  2208.     /*
  2209.      * Because this thread could be running on a different cpu after
  2210.      * a context switch the current cpu should be accessed and the
  2211.      * value of the 'cpu' variable should not be used.
  2212.      */
  2213.     _PR_MD_SET_INTSOFF(0);
  2214. }
  2215.  
  2216. /* # of milliseconds per clock tick that we will use */
  2217. #define MSEC_PER_TICK    50
  2218.  
  2219.  
  2220. void _MD_StartInterrupts()
  2221. {
  2222.     struct itimerval itval;
  2223.     char *eval;
  2224.     struct sigaction vtact;
  2225.  
  2226.     vtact.sa_handler = (void (*)()) ClockInterruptHandler;
  2227.     vtact.sa_flags = SA_RESTART;
  2228.     vtact.sa_mask = timer_set;
  2229.     sigaction(SIGALRM, &vtact, 0);
  2230.  
  2231.     if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {
  2232.         if (atoi(eval) == 0)
  2233.             _nspr_noclock = 0;
  2234.         else
  2235.             _nspr_noclock = 1;
  2236.     }
  2237.  
  2238. #ifndef _PR_NO_CLOCK_TIMER
  2239.     if (!_nspr_noclock) {
  2240.         itval.it_interval.tv_sec = 0;
  2241.         itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
  2242.         itval.it_value = itval.it_interval;
  2243.         setitimer(ITIMER_REAL, &itval, 0);
  2244.     }
  2245. #endif
  2246. }
  2247.  
  2248. void _MD_StopInterrupts()
  2249. {
  2250.     sigprocmask(SIG_BLOCK, &timer_set, 0);
  2251. }
  2252.  
  2253. void _MD_DisableClockInterrupts()
  2254. {
  2255.     struct itimerval itval;
  2256.     extern PRUintn _pr_numCPU;
  2257.  
  2258.     PR_ASSERT(_pr_numCPU == 1);
  2259.     if (!_nspr_noclock) {
  2260.         itval.it_interval.tv_sec = 0;
  2261.         itval.it_interval.tv_usec = 0;
  2262.         itval.it_value = itval.it_interval;
  2263.         setitimer(ITIMER_REAL, &itval, 0);
  2264.     }
  2265. }
  2266.  
  2267. void _MD_BlockClockInterrupts()
  2268. {
  2269.     sigprocmask(SIG_BLOCK, &timer_set, 0);
  2270. }
  2271.  
  2272. void _MD_UnblockClockInterrupts()
  2273. {
  2274.     sigprocmask(SIG_UNBLOCK, &timer_set, 0);
  2275. }
  2276.  
  2277. void _MD_MakeNonblock(PRFileDesc *fd)
  2278. {
  2279.     PRInt32 osfd = fd->secret->md.osfd;
  2280.     int flags;
  2281.  
  2282.     if (osfd <= 2) {
  2283.         /* Don't mess around with stdin, stdout or stderr */
  2284.         return;
  2285.     }
  2286.     flags = fcntl(osfd, F_GETFL, 0);
  2287.  
  2288.     /*
  2289.      * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible.
  2290.      * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O),
  2291.      * otherwise connect() still blocks and can be interrupted by SIGALRM.
  2292.      */
  2293.  
  2294. #ifdef SUNOS4
  2295.     fcntl(osfd, F_SETFL, flags | FNDELAY);
  2296. #else
  2297.     fcntl(osfd, F_SETFL, flags | O_NONBLOCK);
  2298. #endif
  2299.     }
  2300.  
  2301. PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode)
  2302. {
  2303.     PRInt32 osflags;
  2304.     PRInt32 rv, err;
  2305.  
  2306.     if (flags & PR_RDWR) {
  2307.         osflags = O_RDWR;
  2308.     } else if (flags & PR_WRONLY) {
  2309.         osflags = O_WRONLY;
  2310.     } else {
  2311.         osflags = O_RDONLY;
  2312.     }
  2313.  
  2314.     if (flags & PR_APPEND)
  2315.         osflags |= O_APPEND;
  2316.     if (flags & PR_TRUNCATE)
  2317.         osflags |= O_TRUNC;
  2318.     if (flags & PR_SYNC) {
  2319. #if defined(FREEBSD)
  2320.         osflags |= O_FSYNC;
  2321. #else
  2322.         osflags |= O_SYNC;
  2323. #endif
  2324.     }
  2325.  
  2326.     /*
  2327.     ** On creations we hold the 'create' lock in order to enforce
  2328.     ** the semantics of PR_Rename. (see the latter for more details)
  2329.     */
  2330.     if (flags & PR_CREATE_FILE)
  2331.     {
  2332.         osflags |= O_CREAT ;
  2333.         if (NULL !=_pr_rename_lock)
  2334.             PR_Lock(_pr_rename_lock);
  2335.     }
  2336.  
  2337.     rv = open(name, osflags, mode);
  2338.  
  2339.     if (rv < 0) {
  2340.         err = _MD_ERRNO();
  2341.         _PR_MD_MAP_OPEN_ERROR(err);
  2342.     }
  2343.  
  2344.     if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
  2345.         PR_Unlock(_pr_rename_lock);
  2346.     return rv;
  2347. }
  2348.  
  2349. PRIntervalTime intr_timeout_ticks;
  2350.  
  2351. static void sigsegvhandler() {
  2352.     fprintf(stderr,"Received SIGSEGV\n");
  2353.     fflush(stderr);
  2354.     pause();
  2355. }
  2356.  
  2357. static void sigaborthandler() {
  2358.     fprintf(stderr,"Received SIGABRT\n");
  2359.     fflush(stderr);
  2360.     pause();
  2361. }
  2362.  
  2363. static void sigbushandler() {
  2364.     fprintf(stderr,"Received SIGBUS\n");
  2365.     fflush(stderr);
  2366.     pause();
  2367. }
  2368.  
  2369. #endif  /* !defined(_PR_PTHREADS) */
  2370.  
  2371. void _PR_UnixInit()
  2372. {
  2373.     struct sigaction sigact;
  2374.     int rv;
  2375.  
  2376.     sigemptyset(&timer_set);
  2377.  
  2378. #if !defined(_PR_PTHREADS)
  2379.  
  2380.     sigaddset(&timer_set, SIGALRM);
  2381.     sigemptyset(&empty_set);
  2382.     intr_timeout_ticks =
  2383.             PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);
  2384.  
  2385. #if defined(SOLARIS) || defined(IRIX)
  2386.  
  2387.     if (getenv("NSPR_SIGSEGV_HANDLE")) {
  2388.         sigact.sa_handler = sigsegvhandler;
  2389.         sigact.sa_flags = SA_RESTART;
  2390.         sigact.sa_mask = timer_set;
  2391.         sigaction(SIGSEGV, &sigact, 0);
  2392.     }
  2393.  
  2394.     if (getenv("NSPR_SIGABRT_HANDLE")) {
  2395.         sigact.sa_handler = sigaborthandler;
  2396.         sigact.sa_flags = SA_RESTART;
  2397.         sigact.sa_mask = timer_set;
  2398.         sigaction(SIGABRT, &sigact, 0);
  2399.     }
  2400.  
  2401.     if (getenv("NSPR_SIGBUS_HANDLE")) {
  2402.         sigact.sa_handler = sigbushandler;
  2403.         sigact.sa_flags = SA_RESTART;
  2404.         sigact.sa_mask = timer_set;
  2405.         sigaction(SIGBUS, &sigact, 0);
  2406.     }
  2407.  
  2408. #endif
  2409. #endif  /* !defined(_PR_PTHREADS) */
  2410.  
  2411.     /*
  2412.      * Under HP-UX DCE threads, sigaction() installs a per-thread
  2413.      * handler, so we use sigvector() to install a process-wide
  2414.      * handler.
  2415.      */
  2416. #if defined(HPUX) && defined(_PR_DCETHREADS)
  2417.     {
  2418.         struct sigvec vec;
  2419.  
  2420.         vec.sv_handler = SIG_IGN;
  2421.         vec.sv_mask = 0;
  2422.         vec.sv_flags = 0;
  2423.         rv = sigvector(SIGPIPE, &vec, NULL);
  2424.         PR_ASSERT(0 == rv);
  2425.     }
  2426. #else
  2427.     sigact.sa_handler = SIG_IGN;
  2428.     sigemptyset(&sigact.sa_mask);
  2429.     sigact.sa_flags = 0;
  2430.     rv = sigaction(SIGPIPE, &sigact, 0);
  2431.     PR_ASSERT(0 == rv);
  2432. #endif /* HPUX && _PR_DCETHREADS */
  2433.  
  2434.     _pr_rename_lock = PR_NewLock();
  2435.     PR_ASSERT(NULL != _pr_rename_lock);
  2436.     _pr_Xfe_mon = PR_NewMonitor();
  2437.     PR_ASSERT(NULL != _pr_Xfe_mon);
  2438.  
  2439. }
  2440.  
  2441. /*
  2442.  * _MD_InitSegs --
  2443.  *
  2444.  * This is Unix's version of _PR_MD_INIT_SEGS(), which is
  2445.  * called by _PR_InitSegs(), which in turn is called by
  2446.  * PR_Init().
  2447.  */
  2448. void _MD_InitSegs()
  2449. {
  2450. #ifdef DEBUG
  2451.     /*
  2452.     ** Disable using mmap(2) if NSPR_NO_MMAP is set
  2453.     */
  2454.     if (getenv("NSPR_NO_MMAP")) {
  2455.         _pr_zero_fd = -2;
  2456.         return;
  2457.     }
  2458. #endif
  2459.     _pr_zero_fd = open("/dev/zero",O_RDWR , 0);
  2460.     _pr_md_lock = PR_NewLock();
  2461. }
  2462.  
  2463. PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
  2464. {
  2465.     static char *lastaddr = (char*) _PR_STACK_VMBASE;
  2466.     PRStatus retval = PR_SUCCESS;
  2467.     int prot;
  2468.     void *rv;
  2469.  
  2470.     PR_ASSERT(seg != 0);
  2471.     PR_ASSERT(size != 0);
  2472.  
  2473.     PR_Lock(_pr_md_lock);
  2474.     if (_pr_zero_fd < 0) {
  2475. from_heap:
  2476.         seg->vaddr = PR_MALLOC(size);
  2477.         if (!seg->vaddr) {
  2478.             retval = PR_FAILURE;
  2479.         }
  2480.         else {
  2481.             seg->size = size;
  2482.             seg->access = PR_SEGMENT_RDWR;
  2483.         }
  2484.         goto exit;
  2485.     }
  2486.  
  2487.     prot = PROT_READ|PROT_WRITE;
  2488.     rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,
  2489.         _MD_MMAP_FLAGS,
  2490.         _pr_zero_fd, 0);
  2491.     if (rv == (void*)-1) {
  2492.         goto from_heap;
  2493.     }
  2494.     lastaddr += size;
  2495.     seg->vaddr = rv;
  2496.     seg->size = size;
  2497.     seg->access = PR_SEGMENT_RDWR;
  2498.     seg->flags = _PR_SEG_VM;
  2499.  
  2500. exit:
  2501.     PR_Unlock(_pr_md_lock);
  2502.     return retval;
  2503. }
  2504.  
  2505. void _MD_FreeSegment(PRSegment *seg)
  2506. {
  2507.     if (seg->flags & _PR_SEG_VM)
  2508.         (void) munmap(seg->vaddr, seg->size);
  2509.     else
  2510.         PR_DELETE(seg->vaddr);
  2511. }
  2512.  
  2513. /*
  2514.  *-----------------------------------------------------------------------
  2515.  *
  2516.  * PR_Now --
  2517.  *
  2518.  *     Returns the current time in microseconds since the epoch.
  2519.  *     The epoch is midnight January 1, 1970 GMT.
  2520.  *     The implementation is machine dependent.  This is the Unix
  2521.  *     implementation.
  2522.  *     Cf. time_t time(time_t *tp)
  2523.  *
  2524.  *-----------------------------------------------------------------------
  2525.  */
  2526.  
  2527. PR_IMPLEMENT(PRTime)
  2528. PR_Now(void)
  2529. {
  2530.     struct timeval tv;
  2531.     PRInt64 s, us, s2us;
  2532.  
  2533. #if (defined(SOLARIS) && defined(_SVID_GETTOD)) || defined(SONY)
  2534.     gettimeofday(&tv);
  2535. #else
  2536.     gettimeofday(&tv, 0);
  2537. #endif
  2538.     LL_I2L(s2us, PR_USEC_PER_SEC);
  2539.     LL_I2L(s, tv.tv_sec);
  2540.     LL_I2L(us, tv.tv_usec);
  2541.     LL_MUL(s, s, s2us);
  2542.     LL_ADD(s, s, us);
  2543.     return s;
  2544. }
  2545.  
  2546. PR_IMPLEMENT(PRIntervalTime) _PR_UNIX_GetInterval()
  2547. {
  2548.     struct timeval time;
  2549.     PRIntervalTime ticks;
  2550.  
  2551. #if defined(_SVID_GETTOD) || defined(SONY)
  2552.     (void)gettimeofday(&time);  /* fallicy of course */
  2553. #else
  2554.     (void)gettimeofday(&time, NULL);  /* fallicy of course */
  2555. #endif
  2556.     ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC;  /* that's in milliseconds */
  2557.     ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC;  /* so's that */
  2558.     return ticks;
  2559. }  /* _PR_SUNOS_GetInterval */
  2560.  
  2561. PR_IMPLEMENT(PRIntervalTime) _PR_UNIX_TicksPerSecond()
  2562. {
  2563.     return 1000;  /* this needs some work :) */
  2564. }
  2565.  
  2566. /*
  2567.  * _PR_UnixTransmitFile
  2568.  *
  2569.  *    Send file fd across socket sd. If headers is non-NULL, 'hlen'
  2570.  *    bytes of headers is sent before sending the file.
  2571.  *
  2572.  *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
  2573.  *    
  2574.  *    return number of bytes sent or -1 on error
  2575.  *
  2576.  */
  2577. #define TRANSMITFILE_MMAP_CHUNK    (256 * 1024)
  2578. PR_IMPLEMENT(PRInt32) _PR_UnixTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 
  2579. const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
  2580. PRIntervalTime timeout)
  2581. {
  2582.     PRInt32 rv, count = 0;
  2583.     PRInt32 len, index = 0;
  2584.     struct stat statbuf;
  2585.     struct PRIOVec iov[2];
  2586.     void *addr;
  2587.     PRInt32 err;
  2588.  
  2589.     /* Get file size */
  2590.     if (fstat(fd->secret->md.osfd, &statbuf) == -1) {
  2591.         err = _MD_ERRNO();
  2592.         switch (err) {
  2593.             case EBADF:
  2594.                 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
  2595.                 break;
  2596.             case EFAULT:
  2597.                 PR_SetError(PR_ACCESS_FAULT_ERROR, err);
  2598.                 break;
  2599.             case EINTR:
  2600.                 PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
  2601.                 break;
  2602.             case ETIMEDOUT:
  2603. #ifdef ENOLINK
  2604.             case ENOLINK:
  2605. #endif
  2606.                 PR_SetError(PR_REMOTE_FILE_ERROR, err);
  2607.                 break;
  2608.             default:
  2609.                 PR_SetError(PR_UNKNOWN_ERROR, err);
  2610.                 break;
  2611.         }
  2612.         count = -1;
  2613.         goto done;
  2614.     }
  2615.     /*
  2616.      * If the file is large, mmap and send the file in chunks so as
  2617.      * to not consume too much virtual address space
  2618.      */
  2619.     len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
  2620.         TRANSMITFILE_MMAP_CHUNK;
  2621.     /*
  2622.      * Map in (part of) file. Take care of zero-length files.
  2623.      */
  2624.     if (len) {
  2625.         addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
  2626.             fd->secret->md.osfd, 0);
  2627.  
  2628.         if (addr == (void*)-1) {
  2629.             _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
  2630.             count = -1;
  2631.             goto done;
  2632.         }
  2633.     }
  2634.     /*
  2635.      * send headers, first, followed by the file
  2636.      */
  2637.     if (hlen) {
  2638.         iov[index].iov_base = (char *) headers;
  2639.         iov[index].iov_len = hlen;
  2640.         index++;
  2641.     }
  2642.     iov[index].iov_base = (char*)addr;
  2643.     iov[index].iov_len = len;
  2644.     index++;
  2645.     rv = PR_Writev(sd, iov, index, timeout);
  2646.     if (len)
  2647.         munmap(addr,len);
  2648.     if (rv >= 0) {
  2649.         PR_ASSERT(rv == hlen + len);
  2650.         statbuf.st_size -= len;
  2651.         count += rv;
  2652.     } else {
  2653.         count = -1;
  2654.         goto done;
  2655.     }
  2656.     /*
  2657.      * send remaining bytes of the file, if any
  2658.      */
  2659.     len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
  2660.         TRANSMITFILE_MMAP_CHUNK;
  2661.     while (len > 0) {
  2662.         /*
  2663.          * Map in (part of) file
  2664.          */
  2665.         PR_ASSERT((count - hlen) % TRANSMITFILE_MMAP_CHUNK == 0);
  2666.         addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
  2667.                 fd->secret->md.osfd, count - hlen);
  2668.  
  2669.         if (addr == (void*)-1) {
  2670.             _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
  2671.             count = -1;
  2672.             goto done;
  2673.         }
  2674.         rv =  PR_Send(sd, addr, len, 0, timeout);
  2675.         munmap(addr,len);
  2676.         if (rv >= 0) {
  2677.             PR_ASSERT(rv == len);
  2678.             statbuf.st_size -= rv;
  2679.             count += rv;
  2680.             len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ?
  2681.                 statbuf.st_size : TRANSMITFILE_MMAP_CHUNK;
  2682.         } else {
  2683.             count = -1;
  2684.             goto done;
  2685.         }
  2686.     }
  2687. done:
  2688.     if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
  2689.         PR_Close(sd);
  2690.     return count;
  2691. }
  2692.  
  2693. #if defined(HPUX11) && !defined(_PR_PTHREADS)
  2694.  
  2695. /*
  2696.  * _PR_HPUXTransmitFile
  2697.  *
  2698.  *    Send file fd across socket sd. If headers is non-NULL, 'hlen'
  2699.  *    bytes of headers is sent before sending the file.
  2700.  *
  2701.  *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
  2702.  *    
  2703.  *    return number of bytes sent or -1 on error
  2704.  *
  2705.  *      This implementation takes advantage of the sendfile() system
  2706.  *      call available in HP-UX B.11.00.
  2707.  *
  2708.  * Known problem: sendfile() does not work with NSPR's malloc()
  2709.  * functions.  The reason is unknown.  So if you want to use
  2710.  * _PR_HPUXTransmitFile(), you must not override the native malloc()
  2711.  * functions.
  2712.  */
  2713.  
  2714. PRInt32
  2715. _PR_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 
  2716.     const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
  2717.     PRIntervalTime timeout)
  2718. {
  2719.     struct stat statbuf;
  2720.     PRInt32 nbytes_to_send;
  2721.     off_t offset;
  2722.     struct iovec hdtrl[2];  /* optional header and trailer buffers */
  2723.     int send_flags;
  2724.     PRInt32 count;
  2725.     PRInt32 rv, err;
  2726.     PRThread *me = _PR_MD_CURRENT_THREAD();
  2727.  
  2728.     /* Get file size */
  2729.     if (fstat(fd->secret->md.osfd, &statbuf) == -1) {
  2730.         _PR_MD_MAP_FSTAT_ERROR(errno);
  2731.         return -1;
  2732.     }
  2733.     nbytes_to_send = hlen + statbuf.st_size;
  2734.     offset = 0;
  2735.  
  2736.     hdtrl[0].iov_base = (void *) headers;  /* cast away the 'const' */
  2737.     hdtrl[0].iov_len = hlen;
  2738.     hdtrl[1].iov_base = NULL;
  2739.     hdtrl[1].iov_base = 0;
  2740.     /*
  2741.      * SF_DISCONNECT seems to disconnect the socket even if sendfile()
  2742.      * only does a partial send on a nonblocking socket.  This
  2743.      * would prevent the subsequent sendfile() calls on that socket
  2744.      * from working.  So we don't use the SD_DISCONNECT flag.
  2745.      */
  2746.     send_flags = 0;
  2747.     rv = 0;
  2748.  
  2749.     while (1) {
  2750.         count = sendfile(sd->secret->md.osfd, fd->secret->md.osfd,
  2751.                 offset, 0, hdtrl, send_flags);
  2752.         PR_ASSERT(count <= nbytes_to_send);
  2753.         if (count == -1) {
  2754.             err = errno;
  2755.             if (err == EINTR) {
  2756.                 if (_PR_PENDING_INTERRUPT(me)) {
  2757.                     me->flags &= ~_PR_INTERRUPT;
  2758.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  2759.                     return -1;
  2760.                 }
  2761.                 continue;  /* retry */
  2762.             }
  2763.         if (err != EAGAIN && err != EWOULDBLOCK) {
  2764.                 _MD_hpux_map_sendfile_error(err);
  2765.                 return -1;
  2766.             }
  2767.             count = 0;
  2768.         }
  2769.         rv += count;
  2770.  
  2771.         if (count < nbytes_to_send) {
  2772.             /*
  2773.              * Optimization: if bytes sent is less than requested, call
  2774.              * select before returning. This is because it is likely that
  2775.              * the next sendfile() call will return EWOULDBLOCK.
  2776.              */
  2777.             if (!_PR_IS_NATIVE_THREAD(me)) {
  2778.                 if (_PR_WaitForFD(sd->secret->md.osfd,
  2779.                         PR_POLL_WRITE, timeout) == 0) {
  2780.                     if (_PR_PENDING_INTERRUPT(me)) {
  2781.                         me->flags &= ~_PR_INTERRUPT;
  2782.                         PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  2783.                     } else {
  2784.                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  2785.                     }
  2786.                     return -1;
  2787.                 } else if (_PR_PENDING_INTERRUPT(me)) {
  2788.                     me->flags &= ~_PR_INTERRUPT;
  2789.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  2790.                     return -1;
  2791.                 }
  2792.             } else {
  2793.                 if (socket_io_wait(sd->secret->md.osfd, WRITE_FD, timeout)< 0) {
  2794.                     return -1;
  2795.                 }
  2796.             }
  2797.  
  2798.             if (hdtrl[0].iov_len == 0) {
  2799.                 PR_ASSERT(hdtrl[0].iov_base == NULL);
  2800.                 offset += count;
  2801.             } else if (count < hdtrl[0].iov_len) {
  2802.                 PR_ASSERT(offset == 0);
  2803.                 hdtrl[0].iov_base = (char *) hdtrl[0].iov_base + count;
  2804.                 hdtrl[0].iov_len -= count;
  2805.             } else {
  2806.                 offset = count - hdtrl[0].iov_len;
  2807.                 hdtrl[0].iov_base = NULL;
  2808.                 hdtrl[0].iov_len = 0;
  2809.             }
  2810.             nbytes_to_send -= count;
  2811.         } else {
  2812.             break;  /* done */
  2813.         }
  2814.     }
  2815.  
  2816.     if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
  2817.         PR_Close(sd);
  2818.     }
  2819.     return rv;
  2820. }
  2821.  
  2822. #endif /* HPUX11 && !_PR_PTHREADS */
  2823.  
  2824. #if !defined(_PR_PTHREADS)
  2825. /*
  2826. ** Wait for I/O on a single descriptor.
  2827.  *
  2828.  * return 0, if timed-out or interrupted, else return 1
  2829. */
  2830. PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
  2831. {
  2832.     _PRUnixPollDesc pd;
  2833.     PRPollQueue pq;
  2834.     PRIntn is;
  2835.     PRInt32 rv = 1;
  2836.     _PRCPU *io_cpu;
  2837.     PRThread *me = _PR_MD_CURRENT_THREAD();
  2838.  
  2839.     PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
  2840.     PR_LOG(_pr_io_lm, PR_LOG_MIN,
  2841.        ("waiting to %s on osfd=%d",
  2842.         (how == PR_POLL_READ) ? "read" : "write",
  2843.         osfd));
  2844.  
  2845.     if (timeout == PR_INTERVAL_NO_WAIT) return 0;
  2846.  
  2847.     pd.osfd = osfd;
  2848.     pd.in_flags = how;
  2849.     pd.out_flags = 0;
  2850.  
  2851.     pq.pds = &pd;
  2852.     pq.npds = 1;
  2853.  
  2854.     _PR_INTSOFF(is);
  2855.     _PR_MD_IOQ_LOCK();
  2856.     _PR_THREAD_LOCK(me);
  2857.  
  2858.     if (_PR_PENDING_INTERRUPT(me)) {
  2859.         _PR_THREAD_UNLOCK(me);
  2860.         _PR_MD_IOQ_UNLOCK();
  2861.         _PR_FAST_INTSON(is);
  2862.         return 0;
  2863.     }
  2864.  
  2865.     pq.thr = me;
  2866.     io_cpu = me->cpu;
  2867.     pq.on_ioq = PR_TRUE;
  2868.     pq.timeout = timeout;
  2869.     _PR_ADD_TO_IOQ(pq, me->cpu);
  2870.     if (how == PR_POLL_READ) {
  2871.         FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
  2872.         (_PR_FD_READ_CNT(me->cpu))[osfd]++;
  2873.     } else if (how == PR_POLL_WRITE) {
  2874.         FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
  2875.         (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
  2876.     } else {
  2877.         FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  2878.         (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
  2879.     }
  2880.     if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
  2881.         _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
  2882.     if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
  2883.         _PR_IOQ_TIMEOUT(me->cpu) = timeout;
  2884.         
  2885.  
  2886.     _PR_SLEEPQ_LOCK(me->cpu);
  2887.     _PR_ADD_SLEEPQ(me, timeout);
  2888.     me->state = _PR_IO_WAIT;
  2889.     me->io_pending = PR_TRUE;
  2890.     me->io_suspended = PR_FALSE;
  2891.     _PR_SLEEPQ_UNLOCK(me->cpu);
  2892.     _PR_THREAD_UNLOCK(me);
  2893.     _PR_MD_IOQ_UNLOCK();
  2894.  
  2895.     _PR_MD_WAIT(me, timeout);
  2896.     me->io_pending = PR_FALSE;
  2897.     me->io_suspended = PR_FALSE;
  2898.  
  2899.     /*
  2900.      * This thread should run on the same cpu on which it was blocked; when 
  2901.      * the IO request times out the fd sets and fd counts for the
  2902.      * cpu are updated below.
  2903.      */
  2904.     PR_ASSERT(me->cpu == io_cpu);
  2905.  
  2906.     /*
  2907.     ** If we timed out the pollq might still be on the ioq. Remove it
  2908.     ** before continuing.
  2909.     */
  2910.     if (pq.on_ioq) {
  2911.         _PR_MD_IOQ_LOCK();
  2912.     /*
  2913.      * Need to check pq.on_ioq again
  2914.      */
  2915.         if (pq.on_ioq) {
  2916.                 PR_REMOVE_LINK(&pq.links);
  2917.         if (how == PR_POLL_READ) {
  2918.             if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
  2919.                 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  2920.         
  2921.         } else if (how == PR_POLL_WRITE) {
  2922.             if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
  2923.                 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  2924.         } else {
  2925.             if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
  2926.                 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  2927.         }
  2928.         }
  2929.         _PR_MD_IOQ_UNLOCK();
  2930.         rv = 0;
  2931.     }
  2932.     _PR_FAST_INTSON(is);
  2933.    return(rv);
  2934. }
  2935.  
  2936. /*
  2937.  * Unblock threads waiting for I/O
  2938.  *    used when interrupting threads
  2939.  *
  2940.  * NOTE: The thread lock should held when this function is called.
  2941.  * On return, the thread lock is released.
  2942.  */
  2943. void _PR_Unblock_IO_Wait(PRThread *thr)
  2944. {
  2945.     int pri = thr->priority;
  2946.     _PRCPU *cpu = thr->cpu;
  2947.  
  2948.     /*
  2949.      * GLOBAL threads wakeup periodically to check for interrupt
  2950.      */
  2951.     if (_PR_IS_NATIVE_THREAD(thr)) {
  2952.         _PR_THREAD_UNLOCK(thr); 
  2953.         return;
  2954.     }
  2955.  
  2956.     PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
  2957.     _PR_SLEEPQ_LOCK(cpu);
  2958.     _PR_DEL_SLEEPQ(thr, PR_TRUE);
  2959.     _PR_SLEEPQ_UNLOCK(cpu);
  2960.  
  2961.     PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
  2962.     thr->state = _PR_RUNNABLE;
  2963.     _PR_RUNQ_LOCK(cpu);
  2964.     _PR_ADD_RUNQ(thr, cpu, pri);
  2965.     _PR_RUNQ_UNLOCK(cpu);
  2966.     _PR_THREAD_UNLOCK(thr);
  2967.     _PR_MD_WAKEUP_WAITER(thr);
  2968. }
  2969. #endif  /* !defined(_PR_PTHREADS) */
  2970.  
  2971. /*
  2972.  * When a nonblocking connect has completed, determine whether it
  2973.  * succeeded or failed, and if it failed, what the error code is.
  2974.  *
  2975.  * The function returns the error code.  An error code of 0 means
  2976.  * that the nonblocking connect succeeded.
  2977.  */
  2978.  
  2979. int _MD_unix_get_nonblocking_connect_error(int osfd)
  2980. {
  2981. #if defined(NCR) || defined(UNIXWARE) || defined(SNI) || defined(NEC)
  2982.     /*
  2983.      * getsockopt() fails with EPIPE, so use getmsg() instead.
  2984.      */
  2985.  
  2986.     int rv;
  2987.     int flags = 0;
  2988.     rv = getmsg(osfd, NULL, NULL, &flags);
  2989.     PR_ASSERT(-1 == rv || 0 == rv);
  2990.     if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
  2991.         return errno;
  2992.     }
  2993.     return 0;  /* no error */
  2994. #else
  2995.     int err;
  2996.     _PRSockLen_t optlen = sizeof(err);
  2997.     if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
  2998.         return errno;
  2999.     } else {
  3000.         return err;
  3001.     }
  3002. #endif
  3003. }
  3004.  
  3005. /************************************************************************/
  3006.  
  3007. /*
  3008. ** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
  3009. ** safe.  Unfortunately, neither is mozilla. To make these programs work
  3010. ** in a pre-emptive threaded environment, we need to use a lock.
  3011. */
  3012.  
  3013. void PR_XLock()
  3014. {
  3015.     PR_EnterMonitor(_pr_Xfe_mon);
  3016. }
  3017.  
  3018. void PR_XUnlock()
  3019. {
  3020.     PR_ExitMonitor(_pr_Xfe_mon);
  3021. }
  3022.  
  3023. PRBool PR_XIsLocked()
  3024. {
  3025.     return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
  3026. }
  3027.  
  3028. void PR_XWait(int ms)
  3029. {
  3030.     PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
  3031. }
  3032.  
  3033. void PR_XNotify(void)
  3034. {
  3035.     PR_Notify(_pr_Xfe_mon);
  3036. }
  3037.  
  3038. void PR_XNotifyAll(void)
  3039. {
  3040.     PR_NotifyAll(_pr_Xfe_mon);
  3041. }
  3042.  
  3043. #ifdef HAVE_BSD_FLOCK
  3044.  
  3045. #include <sys/file.h>
  3046.  
  3047. PR_IMPLEMENT(PRStatus)
  3048. _MD_LockFile(PRInt32 f)
  3049. {
  3050.     PRInt32 rv;
  3051.     rv = flock(f, LOCK_EX);
  3052.     if (rv == 0)
  3053.         return PR_SUCCESS;
  3054.     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
  3055.     return PR_FAILURE;
  3056. }
  3057.  
  3058. PR_IMPLEMENT(PRStatus)
  3059. _MD_TLockFile(PRInt32 f)
  3060. {
  3061.     PRInt32 rv;
  3062.     rv = flock(f, LOCK_EX|LOCK_NB);
  3063.     if (rv == 0)
  3064.         return PR_SUCCESS;
  3065.     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
  3066.     return PR_FAILURE;
  3067. }
  3068.  
  3069. PR_IMPLEMENT(PRStatus)
  3070. _MD_UnlockFile(PRInt32 f)
  3071. {
  3072.     PRInt32 rv;
  3073.     rv = flock(f, LOCK_UN);
  3074.     if (rv == 0)
  3075.         return PR_SUCCESS;
  3076.     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
  3077.     return PR_FAILURE;
  3078. }
  3079. #else
  3080.  
  3081. PR_IMPLEMENT(PRStatus)
  3082. _MD_LockFile(PRInt32 f)
  3083. {
  3084.     PRInt32 rv;
  3085.     rv = lockf(f, F_LOCK, 0);
  3086.     if (rv == 0)
  3087.         return PR_SUCCESS;
  3088.     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
  3089.     return PR_FAILURE;
  3090. }
  3091.  
  3092. PR_IMPLEMENT(PRStatus)
  3093. _MD_TLockFile(PRInt32 f)
  3094. {
  3095.     PRInt32 rv;
  3096.     rv = lockf(f, F_TLOCK, 0);
  3097.     if (rv == 0)
  3098.         return PR_SUCCESS;
  3099.     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
  3100.     return PR_FAILURE;
  3101. }
  3102.  
  3103. PR_IMPLEMENT(PRStatus)
  3104. _MD_UnlockFile(PRInt32 f)
  3105. {
  3106.     PRInt32 rv;
  3107.     rv = lockf(f, F_ULOCK, 0);
  3108.     if (rv == 0)
  3109.         return PR_SUCCESS;
  3110.     _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
  3111.     return PR_FAILURE;
  3112. }
  3113. #endif
  3114.  
  3115. PR_IMPLEMENT(PRStatus) _MD_gethostname(char *name, PRUint32 namelen)
  3116. {
  3117.     PRIntn rv;
  3118.  
  3119.     rv = gethostname(name, namelen);
  3120.     if (0 == rv) {
  3121.         return PR_SUCCESS;
  3122.     }
  3123.     _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
  3124.     return PR_FAILURE;
  3125. }
  3126.  
  3127. /*
  3128.  *******************************************************************
  3129.  *
  3130.  * Memory-mapped files
  3131.  *
  3132.  *******************************************************************
  3133.  */
  3134.  
  3135. PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
  3136. {
  3137.     PRFileInfo info;
  3138.     PRUint32 sz;
  3139.  
  3140.     LL_L2UI(sz, size);
  3141.     if (sz) {
  3142.         if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) {
  3143.         return PR_FAILURE;
  3144.         }
  3145.         if (sz > info.size) {
  3146.             /*
  3147.              * Need to extend the file
  3148.              */
  3149.             if (fmap->prot != PR_PROT_READWRITE) {
  3150.             PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
  3151.             return PR_FAILURE;
  3152.             }
  3153.             if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) {
  3154.             return PR_FAILURE;
  3155.             }
  3156.             if (PR_Write(fmap->fd, "", 1) != 1) {
  3157.             return PR_FAILURE;
  3158.             }
  3159.     }
  3160.     }
  3161.     if (fmap->prot == PR_PROT_READONLY) {
  3162.     fmap->md.prot = PROT_READ;
  3163.     fmap->md.flags = 0;
  3164.     } else if (fmap->prot == PR_PROT_READWRITE) {
  3165.     fmap->md.prot = PROT_READ | PROT_WRITE;
  3166.     fmap->md.flags = MAP_SHARED;
  3167.     } else {
  3168.     PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
  3169.     fmap->md.prot = PROT_READ | PROT_WRITE;
  3170.     fmap->md.flags = MAP_PRIVATE;
  3171.     }
  3172.     return PR_SUCCESS;
  3173. }
  3174.  
  3175. void * _MD_MemMap(
  3176.     PRFileMap *fmap,
  3177.     PRInt64 offset,
  3178.     PRUint32 len)
  3179. {
  3180.     PRInt32 off;
  3181.     void *addr;
  3182.  
  3183.     LL_L2I(off, offset);
  3184.     if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags,
  3185.         fmap->fd->secret->md.osfd, off)) == (void *) -1) {
  3186.             _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
  3187.         addr = NULL;
  3188.     }
  3189.     return addr;
  3190. }
  3191.  
  3192. PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
  3193. {
  3194.     if (munmap(addr, len) == 0) {
  3195.         return PR_SUCCESS;
  3196.     } else {
  3197.     if (errno == EINVAL) {
  3198.             PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
  3199.     } else {
  3200.         PR_SetError(PR_UNKNOWN_ERROR, errno);
  3201.     }
  3202.         return PR_FAILURE;
  3203.     }
  3204. }
  3205.  
  3206. PRStatus _MD_CloseFileMap(PRFileMap *fmap)
  3207. {
  3208.     PR_DELETE(fmap);
  3209.     return PR_SUCCESS;
  3210. }
  3211.