Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  uxpoll.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#if defined(_PR_PTHREADS)

#  error "This file should not be compiled"

#else /* defined(_PR_PTHREADS) */

#  include "primpl.h"

#  include <sys/time.h>

#  include <fcntl.h>
#  ifdef _PR_USE_POLL
#    include <poll.h>
#  endif

#  if defined(_PR_USE_POLL)
static PRInt32 NativeThreadPoll(PRPollDesc* pds, PRIntn npds,
                                PRIntervalTime timeout) {
  /*
   * This function is mostly duplicated from ptio.s's PR_Poll().
   */

  PRInt32 ready = 0;
  /*
   * For restarting poll() if it is interrupted by a signal.
   * We use these variables to figure out how much time has
   * elapsed and how much of the timeout still remains.
   */

  PRIntn index, msecs;
  struct pollfd* syspoll = NULL;
  PRIntervalTime start, elapsed, remaining;

  syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
  if (NULL == syspoll) {
    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    return -1;
  }
  for (index = 0; index < npds; ++index) {
    PRFileDesc* bottom;
    PRInt16 in_flags_read = 0, in_flags_write = 0;
    PRInt16 out_flags_read = 0, out_flags_write = 0;

    if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) {
      if (pds[index].in_flags & PR_POLL_READ) {
        in_flags_read = (pds[index].fd->methods->poll)(
            pds[index].fd, pds[index].in_flags & ~PR_POLL_WRITE,
            &out_flags_read);
      }
      if (pds[index].in_flags & PR_POLL_WRITE) {
        in_flags_write = (pds[index].fd->methods->poll)(
            pds[index].fd, pds[index].in_flags & ~PR_POLL_READ,
            &out_flags_write);
      }
      if ((0 != (in_flags_read & out_flags_read)) ||
          (0 != (in_flags_write & out_flags_write))) {
        /* this one is ready right now */
        if (0 == ready) {
          /*
           * We will return without calling the system
           * poll function.  So zero the out_flags
           * fields of all the poll descriptors before
           * this one.
           */

          int i;
          for (i = 0; i < index; i++) {
            pds[i].out_flags = 0;
          }
        }
        ready += 1;
        pds[index].out_flags = out_flags_read | out_flags_write;
      } else {
        pds[index].out_flags = 0; /* pre-condition */
        /* now locate the NSPR layer at the bottom of the stack */
        bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER);
        PR_ASSERT(NULL != bottom); /* what to do about that? */
        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
          if (0 == ready) {
            syspoll[index].fd = bottom->secret->md.osfd;
            syspoll[index].events = 0; /* pre-condition */
            if (in_flags_read & PR_POLL_READ) {
              pds[index].out_flags |= _PR_POLL_READ_SYS_READ;
              syspoll[index].events |= POLLIN;
            }
            if (in_flags_read & PR_POLL_WRITE) {
              pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE;
              syspoll[index].events |= POLLOUT;
            }
            if (in_flags_write & PR_POLL_READ) {
              pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ;
              syspoll[index].events |= POLLIN;
            }
            if (in_flags_write & PR_POLL_WRITE) {
              pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE;
              syspoll[index].events |= POLLOUT;
            }
            if (pds[index].in_flags & PR_POLL_EXCEPT) {
              syspoll[index].events |= POLLPRI;
            }
          }
        } else {
          if (0 == ready) {
            int i;
            for (i = 0; i < index; i++) {
              pds[i].out_flags = 0;
            }
          }
          ready += 1; /* this will cause an abrupt return */
          pds[index].out_flags = PR_POLL_NVAL; /* bogii */
        }
      }
    } else {
      /* make poll() ignore this entry */
      syspoll[index].fd = -1;
      syspoll[index].events = 0;
      pds[index].out_flags = 0;
    }
  }

  if (0 == ready) {
    switch (timeout) {
      case PR_INTERVAL_NO_WAIT:
        msecs = 0;
        break;
      case PR_INTERVAL_NO_TIMEOUT:
        msecs = -1;
        break;
      default:
        msecs = PR_IntervalToMilliseconds(timeout);
        start = PR_IntervalNow();
    }

  retry:
    ready = _MD_POLL(syspoll, npds, msecs);
    if (-1 == ready) {
      PRIntn oserror = errno;

      if (EINTR == oserror) {
        if (timeout == PR_INTERVAL_NO_TIMEOUT) {
          goto retry;
        } else if (timeout == PR_INTERVAL_NO_WAIT) {
          ready = 0;
        } else {
          elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
          if (elapsed > timeout) {
            ready = 0; /* timed out */
          } else {
            remaining = timeout - elapsed;
            msecs = PR_IntervalToMilliseconds(remaining);
            goto retry;
          }
        }
      } else {
        _PR_MD_MAP_POLL_ERROR(oserror);
      }
    } else if (ready > 0) {
      for (index = 0; index < npds; ++index) {
        PRInt16 out_flags = 0;
        if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) {
          if (0 != syspoll[index].revents) {
            /*
            ** Set up the out_flags so that it contains the
            ** bits that the highest layer thinks are nice
            ** to have. Then the client of that layer will
            ** call the appropriate I/O function and maybe
            ** the protocol will make progress.
            */

            if (syspoll[index].revents & POLLIN) {
              if (pds[index].out_flags & _PR_POLL_READ_SYS_READ) {
                out_flags |= PR_POLL_READ;
              }
              if (pds[index].out_flags & _PR_POLL_WRITE_SYS_READ) {
                out_flags |= PR_POLL_WRITE;
              }
            }
            if (syspoll[index].revents & POLLOUT) {
              if (pds[index].out_flags & _PR_POLL_READ_SYS_WRITE) {
                out_flags |= PR_POLL_READ;
              }
              if (pds[index].out_flags & _PR_POLL_WRITE_SYS_WRITE) {
                out_flags |= PR_POLL_WRITE;
              }
            }
            if (syspoll[index].revents & POLLPRI) {
              out_flags |= PR_POLL_EXCEPT;
            }
            if (syspoll[index].revents & POLLERR) {
              out_flags |= PR_POLL_ERR;
            }
            if (syspoll[index].revents & POLLNVAL) {
              out_flags |= PR_POLL_NVAL;
            }
            if (syspoll[index].revents & POLLHUP) {
              out_flags |= PR_POLL_HUP;
            }
          }
        }
        pds[index].out_flags = out_flags;
      }
    }
  }

  PR_DELETE(syspoll);
  return ready;

/* NativeThreadPoll */
#  endif /* defined(_PR_USE_POLL) */

#  if !defined(_PR_USE_POLL)
static PRInt32 NativeThreadSelect(PRPollDesc* pds, PRIntn npds,
                                  PRIntervalTime timeout) {
  /*
   * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
   */

  fd_set rd, wt, ex;
  PRFileDesc* bottom;
  PRPollDesc *pd, *epd;
  PRInt32 maxfd = -1, ready, err;
  PRIntervalTime remaining, elapsed, start;

  struct timeval tv, *tvp = NULL;

  FD_ZERO(&rd);
  FD_ZERO(&wt);
  FD_ZERO(&ex);

  ready = 0;
  for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    PRInt16 in_flags_read = 0, in_flags_write = 0;
    PRInt16 out_flags_read = 0, out_flags_write = 0;

    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
      if (pd->in_flags & PR_POLL_READ) {
        in_flags_read = (pd->fd->methods->poll)(
            pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
      }
      if (pd->in_flags & PR_POLL_WRITE) {
        in_flags_write = (pd->fd->methods->poll)(
            pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
      }
      if ((0 != (in_flags_read & out_flags_read)) ||
          (0 != (in_flags_write & out_flags_write))) {
        /* this one's ready right now */
        if (0 == ready) {
          /*
           * We will have to return without calling the
           * system poll/select function.  So zero the
           * out_flags fields of all the poll descriptors
           * before this one.
           */

          PRPollDesc* prev;
          for (prev = pds; prev < pd; prev++) {
            prev->out_flags = 0;
          }
        }
        ready += 1;
        pd->out_flags = out_flags_read | out_flags_write;
      } else {
        pd->out_flags = 0; /* pre-condition */

        /* make sure this is an NSPR supported stack */
        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
        PR_ASSERT(NULL != bottom); /* what to do about that? */
        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
          if (0 == ready) {
            PRInt32 osfd = bottom->secret->md.osfd;
            if (osfd > maxfd) {
              maxfd = osfd;
            }
            if (in_flags_read & PR_POLL_READ) {
              pd->out_flags |= _PR_POLL_READ_SYS_READ;
              FD_SET(osfd, &rd);
            }
            if (in_flags_read & PR_POLL_WRITE) {
              pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
              FD_SET(osfd, &wt);
            }
            if (in_flags_write & PR_POLL_READ) {
              pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
              FD_SET(osfd, &rd);
            }
            if (in_flags_write & PR_POLL_WRITE) {
              pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
              FD_SET(osfd, &wt);
            }
            if (pd->in_flags & PR_POLL_EXCEPT) {
              FD_SET(osfd, &ex);
            }
          }
        } else {
          if (0 == ready) {
            PRPollDesc* prev;
            for (prev = pds; prev < pd; prev++) {
              prev->out_flags = 0;
            }
          }
          ready += 1;                   /* this will cause an abrupt return */
          pd->out_flags = PR_POLL_NVAL; /* bogii */
        }
      }
    } else {
      pd->out_flags = 0;
    }
  }

  if (0 != ready) {
    return ready; /* no need to block */
  }

  remaining = timeout;
  start = PR_IntervalNow();

retry:
  if (timeout != PR_INTERVAL_NO_TIMEOUT) {
    PRInt32 ticksPerSecond = PR_TicksPerSecond();
    tv.tv_sec = remaining / ticksPerSecond;
    tv.tv_usec = PR_IntervalToMicroseconds(remaining % ticksPerSecond);
    tvp = &tv;
  }

  ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);

  if (ready == -1 && errno == EINTR) {
    if (timeout == PR_INTERVAL_NO_TIMEOUT) {
      goto retry;
    } else {
      elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
      if (elapsed > timeout) {
        ready = 0; /* timed out */
      } else {
        remaining = timeout - elapsed;
        goto retry;
      }
    }
  }

  /*
  ** Now to unravel the select sets back into the client's poll
  ** descriptor list. Is this possibly an area for pissing away
  ** a few cycles or what?
  */

  if (ready > 0) {
    ready = 0;
    for (pd = pds, epd = pd + npds; pd < epd; pd++) {
      PRInt16 out_flags = 0;
      if ((NULL != pd->fd) && (0 != pd->in_flags)) {
        PRInt32 osfd;
        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
        PR_ASSERT(NULL != bottom);

        osfd = bottom->secret->md.osfd;

        if (FD_ISSET(osfd, &rd)) {
          if (pd->out_flags & _PR_POLL_READ_SYS_READ) {
            out_flags |= PR_POLL_READ;
          }
          if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) {
            out_flags |= PR_POLL_WRITE;
          }
        }
        if (FD_ISSET(osfd, &wt)) {
          if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) {
            out_flags |= PR_POLL_READ;
          }
          if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) {
            out_flags |= PR_POLL_WRITE;
          }
        }
        if (FD_ISSET(osfd, &ex)) {
          out_flags |= PR_POLL_EXCEPT;
        }
      }
      pd->out_flags = out_flags;
      if (out_flags) {
        ready++;
      }
    }
    PR_ASSERT(ready > 0);
  } else if (ready < 0) {
    err = _MD_ERRNO();
    if (err == EBADF) {
      /* Find the bad fds */
      ready = 0;
      for (pd = pds, epd = pd + npds; pd < epd; pd++) {
        pd->out_flags = 0;
        if ((NULL != pd->fd) && (0 != pd->in_flags)) {
          bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
          if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) {
            pd->out_flags = PR_POLL_NVAL;
            ready++;
          }
        }
      }
      PR_ASSERT(ready > 0);
    } else {
      _PR_MD_MAP_SELECT_ERROR(err);
    }
  }

  return ready;
/* NativeThreadSelect */
#  endif /* !defined(_PR_USE_POLL) */

static PRInt32 LocalThreads(PRPollDesc* pds, PRIntn npds,
                            PRIntervalTime timeout) {
  PRPollDesc *pd, *epd;
  PRInt32 ready, pdcnt;
  _PRUnixPollDesc *unixpds, *unixpd;

  /*
   * XXX
   *        PRPollDesc has a PRFileDesc field, fd, while the IOQ
   *        is a list of PRPollQueue structures, each of which contains
   *        a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
   *        the OS file descriptor, osfd, and not a PRFileDesc.
   *        So, we have allocate memory for _PRUnixPollDesc structures,
   *        copy the flags information from the pds list and have pq
   *        point to this list of _PRUnixPollDesc structures.
   *
   *        It would be better if the memory allocation can be avoided.
   */


  unixpd = unixpds =
      (_PRUnixPollDesc*)PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
  if (NULL == unixpds) {
    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    return -1;
  }

  ready = 0;
  for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++) {
    PRFileDesc* bottom;
    PRInt16 in_flags_read = 0, in_flags_write = 0;
    PRInt16 out_flags_read = 0, out_flags_write = 0;

    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
      if (pd->in_flags & PR_POLL_READ) {
        in_flags_read = (pd->fd->methods->poll)(
            pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
      }
      if (pd->in_flags & PR_POLL_WRITE) {
        in_flags_write = (pd->fd->methods->poll)(
            pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
      }
      if ((0 != (in_flags_read & out_flags_read)) ||
          (0 != (in_flags_write & out_flags_write))) {
        /* this one's ready right now */
        if (0 == ready) {
          /*
           * We will have to return without calling the
           * system poll/select function.  So zero the
           * out_flags fields of all the poll descriptors
           * before this one.
           */

          PRPollDesc* prev;
          for (prev = pds; prev < pd; prev++) {
            prev->out_flags = 0;
          }
        }
        ready += 1;
        pd->out_flags = out_flags_read | out_flags_write;
      } else {
        pd->out_flags = 0; /* pre-condition */
        bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
        PR_ASSERT(NULL != bottom); /* what to do about that? */
        if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) {
          if (0 == ready) {
            unixpd->osfd = bottom->secret->md.osfd;
            unixpd->in_flags = 0;
            if (in_flags_read & PR_POLL_READ) {
              unixpd->in_flags |= _PR_UNIX_POLL_READ;
              pd->out_flags |= _PR_POLL_READ_SYS_READ;
            }
            if (in_flags_read & PR_POLL_WRITE) {
              unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
              pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
            }
            if (in_flags_write & PR_POLL_READ) {
              unixpd->in_flags |= _PR_UNIX_POLL_READ;
              pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
            }
            if (in_flags_write & PR_POLL_WRITE) {
              unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
              pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
            }
            if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT) {
              unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
            }
            unixpd++;
            pdcnt++;
          }
        } else {
          if (0 == ready) {
            PRPollDesc* prev;
            for (prev = pds; prev < pd; prev++) {
              prev->out_flags = 0;
            }
          }
          ready += 1;                   /* this will cause an abrupt return */
          pd->out_flags = PR_POLL_NVAL; /* bogii */
        }
      }
    }
  }

  if (0 != ready) {
    /* no need to block */
    PR_DELETE(unixpds);
    return ready;
  }

  ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);

  /*
   * Copy the out_flags from the _PRUnixPollDesc structures to the
   * user's PRPollDesc structures and free the allocated memory
   */

  unixpd = unixpds;
  for (pd = pds, epd = pd + npds; pd < epd; pd++) {
    PRInt16 out_flags = 0;
    if ((NULL != pd->fd) && (0 != pd->in_flags)) {
      /*
       * take errors from the poll operation,
       * the R/W bits from the request
       */

      if (0 != unixpd->out_flags) {
        if (unixpd->out_flags & _PR_UNIX_POLL_READ) {
          if (pd->out_flags & _PR_POLL_READ_SYS_READ) {
            out_flags |= PR_POLL_READ;
          }
          if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) {
            out_flags |= PR_POLL_WRITE;
          }
        }
        if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) {
          if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) {
            out_flags |= PR_POLL_READ;
          }
          if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) {
            out_flags |= PR_POLL_WRITE;
          }
        }
        if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) {
          out_flags |= PR_POLL_EXCEPT;
        }
        if (unixpd->out_flags & _PR_UNIX_POLL_ERR) {
          out_flags |= PR_POLL_ERR;
        }
        if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
          out_flags |= PR_POLL_NVAL;
        }
        if (unixpd->out_flags & _PR_UNIX_POLL_HUP) {
          out_flags |= PR_POLL_HUP;
        }
      }
      unixpd++;
    }
    pd->out_flags = out_flags;
  }

  PR_DELETE(unixpds);

  return ready;
/* LocalThreads */

#  if defined(_PR_USE_POLL)
#    define NativeThreads NativeThreadPoll
#  else
#    define NativeThreads NativeThreadSelect
#  endif

PRInt32 _MD_pr_poll(PRPollDesc* pds, PRIntn npds, PRIntervalTime timeout) {
  PRInt32 rv = 0;
  PRThread* me = _PR_MD_CURRENT_THREAD();

  if (_PR_PENDING_INTERRUPT(me)) {
    me->flags &= ~_PR_INTERRUPT;
    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
    return -1;
  }
  if (0 == npds) {
    PR_Sleep(timeout);
  } else if (_PR_IS_NATIVE_THREAD(me)) {
    rv = NativeThreads(pds, npds, timeout);
  } else {
    rv = LocalThreads(pds, npds, timeout);
  }

  return rv;
/* _MD_pr_poll */

#endif /* defined(_PR_PTHREADS) */

/* uxpoll.c */

Messung V0.5
C=93 H=84 G=88

¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge