tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

uxpoll.c (18936B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #if defined(_PR_PTHREADS)
      7 
      8 #  error "This file should not be compiled"
      9 
     10 #else /* defined(_PR_PTHREADS) */
     11 
     12 #  include "primpl.h"
     13 
     14 #  include <sys/time.h>
     15 
     16 #  include <fcntl.h>
     17 #  ifdef _PR_USE_POLL
     18 #    include <poll.h>
     19 #  endif
     20 
     21 #  if defined(_PR_USE_POLL)
     22 static PRInt32 NativeThreadPoll(PRPollDesc* pds, PRIntn npds,
     23                                PRIntervalTime timeout) {
     24  /*
     25   * This function is mostly duplicated from ptio.s's PR_Poll().
     26   */
     27  PRInt32 ready = 0;
     28  /*
     29   * For restarting poll() if it is interrupted by a signal.
     30   * We use these variables to figure out how much time has
     31   * elapsed and how much of the timeout still remains.
     32   */
     33  PRIntn index, msecs;
     34  struct pollfd* syspoll = NULL;
     35  PRIntervalTime start, elapsed, remaining;
     36 
     37  syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
     38  if (NULL == syspoll) {
     39    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     40    return -1;
     41  }
     42  for (index = 0; index < npds; ++index) {
     43    PRFileDesc* bottom;
     44    PRInt16 in_flags_read = 0, in_flags_write = 0;
     45    PRInt16 out_flags_read = 0, out_flags_write = 0;
     46 
     47    if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) {
     48      if (pds[index].in_flags & PR_POLL_READ) {
     49        in_flags_read = (pds[index].fd->methods->poll)(
     50            pds[index].fd, pds[index].in_flags & ~PR_POLL_WRITE,
     51            &out_flags_read);
     52      }
     53      if (pds[index].in_flags & PR_POLL_WRITE) {
     54        in_flags_write = (pds[index].fd->methods->poll)(
     55            pds[index].fd, pds[index].in_flags & ~PR_POLL_READ,
     56            &out_flags_write);
     57      }
     58      if ((0 != (in_flags_read & out_flags_read)) ||
     59          (0 != (in_flags_write & out_flags_write))) {
     60        /* this one is ready right now */
     61        if (0 == ready) {
     62          /*
     63           * We will return without calling the system
     64           * poll function.  So zero the out_flags
     65           * fields of all the poll descriptors before
     66           * this one.
     67           */
     68          int i;
     69          for (i = 0; i < index; i++) {
     70            pds[i].out_flags = 0;
     71          }
     72        }
     73        ready += 1;
     74        pds[index].out_flags = out_flags_read | out_flags_write;
     75      } else {
     76        pds[index].out_flags = 0; /* pre-condition */
     77        /* now locate the NSPR layer at the bottom of the stack */
     78        bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER);
     79        PR_ASSERT(NULL != bottom); /* what to do about that? */
     80        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
     81          if (0 == ready) {
     82            syspoll[index].fd = bottom->secret->md.osfd;
     83            syspoll[index].events = 0; /* pre-condition */
     84            if (in_flags_read & PR_POLL_READ) {
     85              pds[index].out_flags |= _PR_POLL_READ_SYS_READ;
     86              syspoll[index].events |= POLLIN;
     87            }
     88            if (in_flags_read & PR_POLL_WRITE) {
     89              pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE;
     90              syspoll[index].events |= POLLOUT;
     91            }
     92            if (in_flags_write & PR_POLL_READ) {
     93              pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ;
     94              syspoll[index].events |= POLLIN;
     95            }
     96            if (in_flags_write & PR_POLL_WRITE) {
     97              pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE;
     98              syspoll[index].events |= POLLOUT;
     99            }
    100            if (pds[index].in_flags & PR_POLL_EXCEPT) {
    101              syspoll[index].events |= POLLPRI;
    102            }
    103          }
    104        } else {
    105          if (0 == ready) {
    106            int i;
    107            for (i = 0; i < index; i++) {
    108              pds[i].out_flags = 0;
    109            }
    110          }
    111          ready += 1; /* this will cause an abrupt return */
    112          pds[index].out_flags = PR_POLL_NVAL; /* bogii */
    113        }
    114      }
    115    } else {
    116      /* make poll() ignore this entry */
    117      syspoll[index].fd = -1;
    118      syspoll[index].events = 0;
    119      pds[index].out_flags = 0;
    120    }
    121  }
    122 
    123  if (0 == ready) {
    124    switch (timeout) {
    125      case PR_INTERVAL_NO_WAIT:
    126        msecs = 0;
    127        break;
    128      case PR_INTERVAL_NO_TIMEOUT:
    129        msecs = -1;
    130        break;
    131      default:
    132        msecs = PR_IntervalToMilliseconds(timeout);
    133        start = PR_IntervalNow();
    134    }
    135 
    136  retry:
    137    ready = _MD_POLL(syspoll, npds, msecs);
    138    if (-1 == ready) {
    139      PRIntn oserror = errno;
    140 
    141      if (EINTR == oserror) {
    142        if (timeout == PR_INTERVAL_NO_TIMEOUT) {
    143          goto retry;
    144        } else if (timeout == PR_INTERVAL_NO_WAIT) {
    145          ready = 0;
    146        } else {
    147          elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
    148          if (elapsed > timeout) {
    149            ready = 0; /* timed out */
    150          } else {
    151            remaining = timeout - elapsed;
    152            msecs = PR_IntervalToMilliseconds(remaining);
    153            goto retry;
    154          }
    155        }
    156      } else {
    157        _PR_MD_MAP_POLL_ERROR(oserror);
    158      }
    159    } else if (ready > 0) {
    160      for (index = 0; index < npds; ++index) {
    161        PRInt16 out_flags = 0;
    162        if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) {
    163          if (0 != syspoll[index].revents) {
    164            /*
    165            ** Set up the out_flags so that it contains the
    166            ** bits that the highest layer thinks are nice
    167            ** to have. Then the client of that layer will
    168            ** call the appropriate I/O function and maybe
    169            ** the protocol will make progress.
    170            */
    171            if (syspoll[index].revents & POLLIN) {
    172              if (pds[index].out_flags & _PR_POLL_READ_SYS_READ) {
    173                out_flags |= PR_POLL_READ;
    174              }
    175              if (pds[index].out_flags & _PR_POLL_WRITE_SYS_READ) {
    176                out_flags |= PR_POLL_WRITE;
    177              }
    178            }
    179            if (syspoll[index].revents & POLLOUT) {
    180              if (pds[index].out_flags & _PR_POLL_READ_SYS_WRITE) {
    181                out_flags |= PR_POLL_READ;
    182              }
    183              if (pds[index].out_flags & _PR_POLL_WRITE_SYS_WRITE) {
    184                out_flags |= PR_POLL_WRITE;
    185              }
    186            }
    187            if (syspoll[index].revents & POLLPRI) {
    188              out_flags |= PR_POLL_EXCEPT;
    189            }
    190            if (syspoll[index].revents & POLLERR) {
    191              out_flags |= PR_POLL_ERR;
    192            }
    193            if (syspoll[index].revents & POLLNVAL) {
    194              out_flags |= PR_POLL_NVAL;
    195            }
    196            if (syspoll[index].revents & POLLHUP) {
    197              out_flags |= PR_POLL_HUP;
    198            }
    199          }
    200        }
    201        pds[index].out_flags = out_flags;
    202      }
    203    }
    204  }
    205 
    206  PR_DELETE(syspoll);
    207  return ready;
    208 
    209 } /* NativeThreadPoll */
    210 #  endif /* defined(_PR_USE_POLL) */
    211 
    212 #  if !defined(_PR_USE_POLL)
    213 static PRInt32 NativeThreadSelect(PRPollDesc* pds, PRIntn npds,
    214                                  PRIntervalTime timeout) {
    215  /*
    216   * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
    217   */
    218  fd_set rd, wt, ex;
    219  PRFileDesc* bottom;
    220  PRPollDesc *pd, *epd;
    221  PRInt32 maxfd = -1, ready, err;
    222  PRIntervalTime remaining, elapsed, start;
    223 
    224  struct timeval tv, *tvp = NULL;
    225 
    226  FD_ZERO(&rd);
    227  FD_ZERO(&wt);
    228  FD_ZERO(&ex);
    229 
    230  ready = 0;
    231  for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    232    PRInt16 in_flags_read = 0, in_flags_write = 0;
    233    PRInt16 out_flags_read = 0, out_flags_write = 0;
    234 
    235    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
    236      if (pd->in_flags & PR_POLL_READ) {
    237        in_flags_read = (pd->fd->methods->poll)(
    238            pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
    239      }
    240      if (pd->in_flags & PR_POLL_WRITE) {
    241        in_flags_write = (pd->fd->methods->poll)(
    242            pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
    243      }
    244      if ((0 != (in_flags_read & out_flags_read)) ||
    245          (0 != (in_flags_write & out_flags_write))) {
    246        /* this one's ready right now */
    247        if (0 == ready) {
    248          /*
    249           * We will have to return without calling the
    250           * system poll/select function.  So zero the
    251           * out_flags fields of all the poll descriptors
    252           * before this one.
    253           */
    254          PRPollDesc* prev;
    255          for (prev = pds; prev < pd; prev++) {
    256            prev->out_flags = 0;
    257          }
    258        }
    259        ready += 1;
    260        pd->out_flags = out_flags_read | out_flags_write;
    261      } else {
    262        pd->out_flags = 0; /* pre-condition */
    263 
    264        /* make sure this is an NSPR supported stack */
    265        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
    266        PR_ASSERT(NULL != bottom); /* what to do about that? */
    267        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
    268          if (0 == ready) {
    269            PRInt32 osfd = bottom->secret->md.osfd;
    270            if (osfd > maxfd) {
    271              maxfd = osfd;
    272            }
    273            if (in_flags_read & PR_POLL_READ) {
    274              pd->out_flags |= _PR_POLL_READ_SYS_READ;
    275              FD_SET(osfd, &rd);
    276            }
    277            if (in_flags_read & PR_POLL_WRITE) {
    278              pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
    279              FD_SET(osfd, &wt);
    280            }
    281            if (in_flags_write & PR_POLL_READ) {
    282              pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
    283              FD_SET(osfd, &rd);
    284            }
    285            if (in_flags_write & PR_POLL_WRITE) {
    286              pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
    287              FD_SET(osfd, &wt);
    288            }
    289            if (pd->in_flags & PR_POLL_EXCEPT) {
    290              FD_SET(osfd, &ex);
    291            }
    292          }
    293        } else {
    294          if (0 == ready) {
    295            PRPollDesc* prev;
    296            for (prev = pds; prev < pd; prev++) {
    297              prev->out_flags = 0;
    298            }
    299          }
    300          ready += 1;                   /* this will cause an abrupt return */
    301          pd->out_flags = PR_POLL_NVAL; /* bogii */
    302        }
    303      }
    304    } else {
    305      pd->out_flags = 0;
    306    }
    307  }
    308 
    309  if (0 != ready) {
    310    return ready; /* no need to block */
    311  }
    312 
    313  remaining = timeout;
    314  start = PR_IntervalNow();
    315 
    316 retry:
    317  if (timeout != PR_INTERVAL_NO_TIMEOUT) {
    318    PRInt32 ticksPerSecond = PR_TicksPerSecond();
    319    tv.tv_sec = remaining / ticksPerSecond;
    320    tv.tv_usec = PR_IntervalToMicroseconds(remaining % ticksPerSecond);
    321    tvp = &tv;
    322  }
    323 
    324  ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
    325 
    326  if (ready == -1 && errno == EINTR) {
    327    if (timeout == PR_INTERVAL_NO_TIMEOUT) {
    328      goto retry;
    329    } else {
    330      elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
    331      if (elapsed > timeout) {
    332        ready = 0; /* timed out */
    333      } else {
    334        remaining = timeout - elapsed;
    335        goto retry;
    336      }
    337    }
    338  }
    339 
    340  /*
    341  ** Now to unravel the select sets back into the client's poll
    342  ** descriptor list. Is this possibly an area for pissing away
    343  ** a few cycles or what?
    344  */
    345  if (ready > 0) {
    346    ready = 0;
    347    for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    348      PRInt16 out_flags = 0;
    349      if ((NULL != pd->fd) && (0 != pd->in_flags)) {
    350        PRInt32 osfd;
    351        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
    352        PR_ASSERT(NULL != bottom);
    353 
    354        osfd = bottom->secret->md.osfd;
    355 
    356        if (FD_ISSET(osfd, &rd)) {
    357          if (pd->out_flags & _PR_POLL_READ_SYS_READ) {
    358            out_flags |= PR_POLL_READ;
    359          }
    360          if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) {
    361            out_flags |= PR_POLL_WRITE;
    362          }
    363        }
    364        if (FD_ISSET(osfd, &wt)) {
    365          if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) {
    366            out_flags |= PR_POLL_READ;
    367          }
    368          if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) {
    369            out_flags |= PR_POLL_WRITE;
    370          }
    371        }
    372        if (FD_ISSET(osfd, &ex)) {
    373          out_flags |= PR_POLL_EXCEPT;
    374        }
    375      }
    376      pd->out_flags = out_flags;
    377      if (out_flags) {
    378        ready++;
    379      }
    380    }
    381    PR_ASSERT(ready > 0);
    382  } else if (ready < 0) {
    383    err = _MD_ERRNO();
    384    if (err == EBADF) {
    385      /* Find the bad fds */
    386      ready = 0;
    387      for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    388        pd->out_flags = 0;
    389        if ((NULL != pd->fd) && (0 != pd->in_flags)) {
    390          bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
    391          if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) {
    392            pd->out_flags = PR_POLL_NVAL;
    393            ready++;
    394          }
    395        }
    396      }
    397      PR_ASSERT(ready > 0);
    398    } else {
    399      _PR_MD_MAP_SELECT_ERROR(err);
    400    }
    401  }
    402 
    403  return ready;
    404 } /* NativeThreadSelect */
    405 #  endif /* !defined(_PR_USE_POLL) */
    406 
    407 static PRInt32 LocalThreads(PRPollDesc* pds, PRIntn npds,
    408                            PRIntervalTime timeout) {
    409  PRPollDesc *pd, *epd;
    410  PRInt32 ready, pdcnt;
    411  _PRUnixPollDesc *unixpds, *unixpd;
    412 
    413  /*
    414   * XXX
    415   *        PRPollDesc has a PRFileDesc field, fd, while the IOQ
    416   *        is a list of PRPollQueue structures, each of which contains
    417   *        a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
    418   *        the OS file descriptor, osfd, and not a PRFileDesc.
    419   *        So, we have allocate memory for _PRUnixPollDesc structures,
    420   *        copy the flags information from the pds list and have pq
    421   *        point to this list of _PRUnixPollDesc structures.
    422   *
    423   *        It would be better if the memory allocation can be avoided.
    424   */
    425 
    426  unixpd = unixpds =
    427      (_PRUnixPollDesc*)PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
    428  if (NULL == unixpds) {
    429    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    430    return -1;
    431  }
    432 
    433  ready = 0;
    434  for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++) {
    435    PRFileDesc* bottom;
    436    PRInt16 in_flags_read = 0, in_flags_write = 0;
    437    PRInt16 out_flags_read = 0, out_flags_write = 0;
    438 
    439    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
    440      if (pd->in_flags & PR_POLL_READ) {
    441        in_flags_read = (pd->fd->methods->poll)(
    442            pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
    443      }
    444      if (pd->in_flags & PR_POLL_WRITE) {
    445        in_flags_write = (pd->fd->methods->poll)(
    446            pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
    447      }
    448      if ((0 != (in_flags_read & out_flags_read)) ||
    449          (0 != (in_flags_write & out_flags_write))) {
    450        /* this one's ready right now */
    451        if (0 == ready) {
    452          /*
    453           * We will have to return without calling the
    454           * system poll/select function.  So zero the
    455           * out_flags fields of all the poll descriptors
    456           * before this one.
    457           */
    458          PRPollDesc* prev;
    459          for (prev = pds; prev < pd; prev++) {
    460            prev->out_flags = 0;
    461          }
    462        }
    463        ready += 1;
    464        pd->out_flags = out_flags_read | out_flags_write;
    465      } else {
    466        pd->out_flags = 0; /* pre-condition */
    467        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
    468        PR_ASSERT(NULL != bottom); /* what to do about that? */
    469        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
    470          if (0 == ready) {
    471            unixpd->osfd = bottom->secret->md.osfd;
    472            unixpd->in_flags = 0;
    473            if (in_flags_read & PR_POLL_READ) {
    474              unixpd->in_flags |= _PR_UNIX_POLL_READ;
    475              pd->out_flags |= _PR_POLL_READ_SYS_READ;
    476            }
    477            if (in_flags_read & PR_POLL_WRITE) {
    478              unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
    479              pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
    480            }
    481            if (in_flags_write & PR_POLL_READ) {
    482              unixpd->in_flags |= _PR_UNIX_POLL_READ;
    483              pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
    484            }
    485            if (in_flags_write & PR_POLL_WRITE) {
    486              unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
    487              pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
    488            }
    489            if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT) {
    490              unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
    491            }
    492            unixpd++;
    493            pdcnt++;
    494          }
    495        } else {
    496          if (0 == ready) {
    497            PRPollDesc* prev;
    498            for (prev = pds; prev < pd; prev++) {
    499              prev->out_flags = 0;
    500            }
    501          }
    502          ready += 1;                   /* this will cause an abrupt return */
    503          pd->out_flags = PR_POLL_NVAL; /* bogii */
    504        }
    505      }
    506    }
    507  }
    508 
    509  if (0 != ready) {
    510    /* no need to block */
    511    PR_DELETE(unixpds);
    512    return ready;
    513  }
    514 
    515  ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
    516 
    517  /*
    518   * Copy the out_flags from the _PRUnixPollDesc structures to the
    519   * user's PRPollDesc structures and free the allocated memory
    520   */
    521  unixpd = unixpds;
    522  for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    523    PRInt16 out_flags = 0;
    524    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
    525      /*
    526       * take errors from the poll operation,
    527       * the R/W bits from the request
    528       */
    529      if (0 != unixpd->out_flags) {
    530        if (unixpd->out_flags & _PR_UNIX_POLL_READ) {
    531          if (pd->out_flags & _PR_POLL_READ_SYS_READ) {
    532            out_flags |= PR_POLL_READ;
    533          }
    534          if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) {
    535            out_flags |= PR_POLL_WRITE;
    536          }
    537        }
    538        if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) {
    539          if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) {
    540            out_flags |= PR_POLL_READ;
    541          }
    542          if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) {
    543            out_flags |= PR_POLL_WRITE;
    544          }
    545        }
    546        if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) {
    547          out_flags |= PR_POLL_EXCEPT;
    548        }
    549        if (unixpd->out_flags & _PR_UNIX_POLL_ERR) {
    550          out_flags |= PR_POLL_ERR;
    551        }
    552        if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
    553          out_flags |= PR_POLL_NVAL;
    554        }
    555        if (unixpd->out_flags & _PR_UNIX_POLL_HUP) {
    556          out_flags |= PR_POLL_HUP;
    557        }
    558      }
    559      unixpd++;
    560    }
    561    pd->out_flags = out_flags;
    562  }
    563 
    564  PR_DELETE(unixpds);
    565 
    566  return ready;
    567 } /* LocalThreads */
    568 
    569 #  if defined(_PR_USE_POLL)
    570 #    define NativeThreads NativeThreadPoll
    571 #  else
    572 #    define NativeThreads NativeThreadSelect
    573 #  endif
    574 
    575 PRInt32 _MD_pr_poll(PRPollDesc* pds, PRIntn npds, PRIntervalTime timeout) {
    576  PRInt32 rv = 0;
    577  PRThread* me = _PR_MD_CURRENT_THREAD();
    578 
    579  if (_PR_PENDING_INTERRUPT(me)) {
    580    me->flags &= ~_PR_INTERRUPT;
    581    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
    582    return -1;
    583  }
    584  if (0 == npds) {
    585    PR_Sleep(timeout);
    586  } else if (_PR_IS_NATIVE_THREAD(me)) {
    587    rv = NativeThreads(pds, npds, timeout);
    588  } else {
    589    rv = LocalThreads(pds, npds, timeout);
    590  }
    591 
    592  return rv;
    593 } /* _MD_pr_poll */
    594 
    595 #endif /* defined(_PR_PTHREADS) */
    596 
    597 /* uxpoll.c */