Blame hurd/hurdselect.c

Packit Service 82fcde
/* Guts of both `select' and `poll' for Hurd.
Packit Service 82fcde
   Copyright (C) 1991-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/poll.h>
Packit Service 82fcde
#include <hurd.h>
Packit Service 82fcde
#include <hurd/fd.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
Packit Service 82fcde
/* All user select types.  */
Packit Service 82fcde
#define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
Packit Service 82fcde
Packit Service 82fcde
/* Used to record that a particular select rpc returned.  Must be distinct
Packit Service 82fcde
   from SELECT_ALL (which better not have the high bit set).  */
Packit Service 82fcde
#define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
Packit Service 82fcde
Packit Service 82fcde
/* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
Packit Service 82fcde
   each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull.  If TIMEOUT is not
Packit Service 82fcde
   NULL, time out after waiting the interval specified therein.  Returns
Packit Service 82fcde
   the number of ready descriptors, or -1 for errors.  */
Packit Service 82fcde
int
Packit Service 82fcde
_hurd_select (int nfds,
Packit Service 82fcde
	      struct pollfd *pollfds,
Packit Service 82fcde
	      fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
Packit Service 82fcde
	      const struct timespec *timeout, const sigset_t *sigmask)
Packit Service 82fcde
{
Packit Service 82fcde
  int i;
Packit Service 82fcde
  mach_port_t portset;
Packit Service 82fcde
  int got;
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
  fd_set rfds, wfds, xfds;
Packit Service 82fcde
  int firstfd, lastfd;
Packit Service 82fcde
  mach_msg_timeout_t to = 0;
Packit Service 82fcde
  struct
Packit Service 82fcde
    {
Packit Service 82fcde
      struct hurd_userlink ulink;
Packit Service 82fcde
      struct hurd_fd *cell;
Packit Service 82fcde
      mach_port_t io_port;
Packit Service 82fcde
      int type;
Packit Service 82fcde
      mach_port_t reply_port;
Packit Service 82fcde
    } d[nfds];
Packit Service 82fcde
  sigset_t oset;
Packit Service 82fcde
Packit Service 82fcde
  union typeword		/* Use this to avoid unkosher casts.  */
Packit Service 82fcde
    {
Packit Service 82fcde
      mach_msg_type_t type;
Packit Service 82fcde
      uint32_t word;
Packit Service 82fcde
    };
Packit Service 82fcde
  assert (sizeof (union typeword) == sizeof (mach_msg_type_t));
Packit Service 82fcde
  assert (sizeof (uint32_t) == sizeof (mach_msg_type_t));
Packit Service 82fcde
Packit Service 82fcde
  if (nfds < 0 || (pollfds == NULL && nfds > FD_SETSIZE))
Packit Service 82fcde
    {
Packit Service 82fcde
      errno = EINVAL;
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (timeout != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (timeout->tv_sec < 0 || timeout->tv_nsec < 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  errno = EINVAL;
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      to = (timeout->tv_sec * 1000 +
Packit Service 82fcde
            (timeout->tv_nsec + 999999) / 1000000);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  if (pollfds)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Collect interesting descriptors from the user's `pollfd' array.
Packit Service 82fcde
	 We do a first pass that reads the user's array before taking
Packit Service 82fcde
	 any locks.  The second pass then only touches our own stack,
Packit Service 82fcde
	 and gets the port references.  */
Packit Service 82fcde
Packit Service 82fcde
      for (i = 0; i < nfds; ++i)
Packit Service 82fcde
	if (pollfds[i].fd >= 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    int type = 0;
Packit Service 82fcde
	    if (pollfds[i].events & POLLIN)
Packit Service 82fcde
	      type |= SELECT_READ;
Packit Service 82fcde
	    if (pollfds[i].events & POLLOUT)
Packit Service 82fcde
	      type |= SELECT_WRITE;
Packit Service 82fcde
	    if (pollfds[i].events & POLLPRI)
Packit Service 82fcde
	      type |= SELECT_URG;
Packit Service 82fcde
Packit Service 82fcde
	    d[i].io_port = pollfds[i].fd;
Packit Service 82fcde
	    d[i].type = type;
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
	  d[i].type = 0;
Packit Service 82fcde
Packit Service 82fcde
      HURD_CRITICAL_BEGIN;
Packit Service 82fcde
      __mutex_lock (&_hurd_dtable_lock);
Packit Service 82fcde
Packit Service 82fcde
      for (i = 0; i < nfds; ++i)
Packit Service 82fcde
	if (d[i].type != 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    const int fd = (int) d[i].io_port;
Packit Service 82fcde
Packit Service 82fcde
	    if (fd < _hurd_dtablesize)
Packit Service 82fcde
	      {
Packit Service 82fcde
		d[i].cell = _hurd_dtable[fd];
Packit Service 82fcde
		d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
Packit Service 82fcde
		if (d[i].io_port != MACH_PORT_NULL)
Packit Service 82fcde
		  continue;
Packit Service 82fcde
	      }
Packit Service 82fcde
Packit Service 82fcde
	    /* If one descriptor is bogus, we fail completely.  */
Packit Service 82fcde
	    while (i-- > 0)
Packit Service 82fcde
	      if (d[i].type != 0)
Packit Service 82fcde
		_hurd_port_free (&d[i].cell->port,
Packit Service 82fcde
				 &d[i].ulink, d[i].io_port);
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
      __mutex_unlock (&_hurd_dtable_lock);
Packit Service 82fcde
      HURD_CRITICAL_END;
Packit Service 82fcde
Packit Service 82fcde
      if (i < nfds)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (sigmask)
Packit Service 82fcde
	    __sigprocmask (SIG_SETMASK, &oset, NULL);
Packit Service 82fcde
	  errno = EBADF;
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      lastfd = i - 1;
Packit Service 82fcde
      firstfd = i == 0 ? lastfd : 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Collect interested descriptors from the user's fd_set arguments.
Packit Service 82fcde
	 Use local copies so we can't crash from user bogosity.  */
Packit Service 82fcde
Packit Service 82fcde
      if (readfds == NULL)
Packit Service 82fcde
	FD_ZERO (&rfds);
Packit Service 82fcde
      else
Packit Service 82fcde
	rfds = *readfds;
Packit Service 82fcde
      if (writefds == NULL)
Packit Service 82fcde
	FD_ZERO (&wfds);
Packit Service 82fcde
      else
Packit Service 82fcde
	wfds = *writefds;
Packit Service 82fcde
      if (exceptfds == NULL)
Packit Service 82fcde
	FD_ZERO (&xfds);
Packit Service 82fcde
      else
Packit Service 82fcde
	xfds = *exceptfds;
Packit Service 82fcde
Packit Service 82fcde
      HURD_CRITICAL_BEGIN;
Packit Service 82fcde
      __mutex_lock (&_hurd_dtable_lock);
Packit Service 82fcde
Packit Service 82fcde
      if (nfds > _hurd_dtablesize)
Packit Service 82fcde
	nfds = _hurd_dtablesize;
Packit Service 82fcde
Packit Service 82fcde
      /* Collect the ports for interesting FDs.  */
Packit Service 82fcde
      firstfd = lastfd = -1;
Packit Service 82fcde
      for (i = 0; i < nfds; ++i)
Packit Service 82fcde
	{
Packit Service 82fcde
	  int type = 0;
Packit Service 82fcde
	  if (readfds != NULL && FD_ISSET (i, &rfds))
Packit Service 82fcde
	    type |= SELECT_READ;
Packit Service 82fcde
	  if (writefds != NULL && FD_ISSET (i, &wfds))
Packit Service 82fcde
	    type |= SELECT_WRITE;
Packit Service 82fcde
	  if (exceptfds != NULL && FD_ISSET (i, &xfds))
Packit Service 82fcde
	    type |= SELECT_URG;
Packit Service 82fcde
	  d[i].type = type;
Packit Service 82fcde
	  if (type)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      d[i].cell = _hurd_dtable[i];
Packit Service 82fcde
	      d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
Packit Service 82fcde
	      if (d[i].io_port == MACH_PORT_NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* If one descriptor is bogus, we fail completely.  */
Packit Service 82fcde
		  while (i-- > 0)
Packit Service 82fcde
		    if (d[i].type != 0)
Packit Service 82fcde
		      _hurd_port_free (&d[i].cell->port, &d[i].ulink,
Packit Service 82fcde
				       d[i].io_port);
Packit Service 82fcde
		  break;
Packit Service 82fcde
		}
Packit Service 82fcde
	      lastfd = i;
Packit Service 82fcde
	      if (firstfd == -1)
Packit Service 82fcde
		firstfd = i;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      __mutex_unlock (&_hurd_dtable_lock);
Packit Service 82fcde
      HURD_CRITICAL_END;
Packit Service 82fcde
Packit Service 82fcde
      if (i < nfds)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (sigmask)
Packit Service 82fcde
	    __sigprocmask (SIG_SETMASK, &oset, NULL);
Packit Service 82fcde
	  errno = EBADF;
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
  err = 0;
Packit Service 82fcde
  got = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Send them all io_select request messages.  */
Packit Service 82fcde
Packit Service 82fcde
  if (firstfd == -1)
Packit Service 82fcde
    /* But not if there were no ports to deal with at all.
Packit Service 82fcde
       We are just a pure timeout.  */
Packit Service 82fcde
    portset = __mach_reply_port ();
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      portset = MACH_PORT_NULL;
Packit Service 82fcde
Packit Service 82fcde
      for (i = firstfd; i <= lastfd; ++i)
Packit Service 82fcde
	if (d[i].type)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    int type = d[i].type;
Packit Service 82fcde
	    d[i].reply_port = __mach_reply_port ();
Packit Service 82fcde
	    err = __io_select (d[i].io_port, d[i].reply_port,
Packit Service 82fcde
			       /* Poll only if there's a single descriptor.  */
Packit Service 82fcde
			       (firstfd == lastfd) ? to : 0,
Packit Service 82fcde
			       &type);
Packit Service 82fcde
	    switch (err)
Packit Service 82fcde
	      {
Packit Service 82fcde
	      case MACH_RCV_TIMED_OUT:
Packit Service 82fcde
		/* No immediate response.  This is normal.  */
Packit Service 82fcde
		err = 0;
Packit Service 82fcde
		if (firstfd == lastfd)
Packit Service 82fcde
		  /* When there's a single descriptor, we don't need a
Packit Service 82fcde
		     portset, so just pretend we have one, but really
Packit Service 82fcde
		     use the single reply port.  */
Packit Service 82fcde
		  portset = d[i].reply_port;
Packit Service 82fcde
		else if (got == 0)
Packit Service 82fcde
		  /* We've got multiple reply ports, so we need a port set to
Packit Service 82fcde
		     multiplex them.  */
Packit Service 82fcde
		  {
Packit Service 82fcde
		    /* We will wait again for a reply later.  */
Packit Service 82fcde
		    if (portset == MACH_PORT_NULL)
Packit Service 82fcde
		      /* Create the portset to receive all the replies on.  */
Packit Service 82fcde
		      err = __mach_port_allocate (__mach_task_self (),
Packit Service 82fcde
						  MACH_PORT_RIGHT_PORT_SET,
Packit Service 82fcde
						  &portset);
Packit Service 82fcde
		    if (! err)
Packit Service 82fcde
		      /* Put this reply port in the port set.  */
Packit Service 82fcde
		      __mach_port_move_member (__mach_task_self (),
Packit Service 82fcde
					       d[i].reply_port, portset);
Packit Service 82fcde
		  }
Packit Service 82fcde
		break;
Packit Service 82fcde
Packit Service 82fcde
	      default:
Packit Service 82fcde
		/* No other error should happen.  Callers of select
Packit Service 82fcde
		   don't expect to see errors, so we simulate
Packit Service 82fcde
		   readiness of the erring object and the next call
Packit Service 82fcde
		   hopefully will get the error again.  */
Packit Service 82fcde
		type = SELECT_ALL;
Packit Service 82fcde
		/* FALLTHROUGH */
Packit Service 82fcde
Packit Service 82fcde
	      case 0:
Packit Service 82fcde
		/* We got an answer.  */
Packit Service 82fcde
		if ((type & SELECT_ALL) == 0)
Packit Service 82fcde
		  /* Bogus answer; treat like an error, as a fake positive.  */
Packit Service 82fcde
		  type = SELECT_ALL;
Packit Service 82fcde
Packit Service 82fcde
		/* This port is already ready already.  */
Packit Service 82fcde
		d[i].type &= type;
Packit Service 82fcde
		d[i].type |= SELECT_RETURNED;
Packit Service 82fcde
		++got;
Packit Service 82fcde
		break;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
Packit Service 82fcde
	  }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Now wait for reply messages.  */
Packit Service 82fcde
  if (!err && got == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Now wait for io_select_reply messages on PORT,
Packit Service 82fcde
	 timing out as appropriate.  */
Packit Service 82fcde
Packit Service 82fcde
      union
Packit Service 82fcde
	{
Packit Service 82fcde
	  mach_msg_header_t head;
Packit Service 82fcde
#ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
Packit Service 82fcde
	  struct
Packit Service 82fcde
	    {
Packit Service 82fcde
	      mach_msg_header_t head;
Packit Service 82fcde
	      NDR_record_t ndr;
Packit Service 82fcde
	      error_t err;
Packit Service 82fcde
	    } error;
Packit Service 82fcde
	  struct
Packit Service 82fcde
	    {
Packit Service 82fcde
	      mach_msg_header_t head;
Packit Service 82fcde
	      NDR_record_t ndr;
Packit Service 82fcde
	      error_t err;
Packit Service 82fcde
	      int result;
Packit Service 82fcde
	      mach_msg_trailer_t trailer;
Packit Service 82fcde
	    } success;
Packit Service 82fcde
#else
Packit Service 82fcde
	  struct
Packit Service 82fcde
	    {
Packit Service 82fcde
	      mach_msg_header_t head;
Packit Service 82fcde
	      union typeword err_type;
Packit Service 82fcde
	      error_t err;
Packit Service 82fcde
	    } error;
Packit Service 82fcde
	  struct
Packit Service 82fcde
	    {
Packit Service 82fcde
	      mach_msg_header_t head;
Packit Service 82fcde
	      union typeword err_type;
Packit Service 82fcde
	      error_t err;
Packit Service 82fcde
	      union typeword result_type;
Packit Service 82fcde
	      int result;
Packit Service 82fcde
	    } success;
Packit Service 82fcde
#endif
Packit Service 82fcde
	} msg;
Packit Service 82fcde
      mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
Packit Service 82fcde
      error_t msgerr;
Packit Service 82fcde
      while ((msgerr = __mach_msg (&msg.head,
Packit Service 82fcde
				   MACH_RCV_MSG | MACH_RCV_INTERRUPT | options,
Packit Service 82fcde
				   0, sizeof msg, portset, to,
Packit Service 82fcde
				   MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We got a message.  Decode it.  */
Packit Service 82fcde
#define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
Packit Service 82fcde
#ifdef MACH_MSG_TYPE_BIT
Packit Service 82fcde
	  const union typeword inttype =
Packit Service 82fcde
	  { type:
Packit Service 82fcde
	    { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8, 1, 1, 0, 0 }
Packit Service 82fcde
	  };
Packit Service 82fcde
#endif
Packit Service 82fcde
	  if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
Packit Service 82fcde
	      msg.head.msgh_size >= sizeof msg.error &&
Packit Service 82fcde
	      !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
Packit Service 82fcde
#ifdef MACH_MSG_TYPE_BIT
Packit Service 82fcde
	      msg.error.err_type.word == inttype.word
Packit Service 82fcde
#endif
Packit Service 82fcde
	      )
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* This is a properly formatted message so far.
Packit Service 82fcde
		 See if it is a success or a failure.  */
Packit Service 82fcde
	      if (msg.error.err == EINTR &&
Packit Service 82fcde
		  msg.head.msgh_size == sizeof msg.error)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* EINTR response; poll for further responses
Packit Service 82fcde
		     and then return quickly.  */
Packit Service 82fcde
		  err = EINTR;
Packit Service 82fcde
		  goto poll;
Packit Service 82fcde
		}
Packit Service 82fcde
	      if (msg.error.err ||
Packit Service 82fcde
		  msg.head.msgh_size != sizeof msg.success ||
Packit Service 82fcde
#ifdef MACH_MSG_TYPE_BIT
Packit Service 82fcde
		  msg.success.result_type.word != inttype.word ||
Packit Service 82fcde
#endif
Packit Service 82fcde
		  (msg.success.result & SELECT_ALL) == 0)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* Error or bogus reply.  Simulate readiness.  */
Packit Service 82fcde
		  __mach_msg_destroy (&msg.head);
Packit Service 82fcde
		  msg.success.result = SELECT_ALL;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      /* Look up the respondent's reply port and record its
Packit Service 82fcde
		 readiness.  */
Packit Service 82fcde
	      {
Packit Service 82fcde
		int had = got;
Packit Service 82fcde
		if (firstfd != -1)
Packit Service 82fcde
		  for (i = firstfd; i <= lastfd; ++i)
Packit Service 82fcde
		    if (d[i].type
Packit Service 82fcde
			&& d[i].reply_port == msg.head.msgh_local_port)
Packit Service 82fcde
		      {
Packit Service 82fcde
			d[i].type &= msg.success.result;
Packit Service 82fcde
			d[i].type |= SELECT_RETURNED;
Packit Service 82fcde
			++got;
Packit Service 82fcde
		      }
Packit Service 82fcde
		assert (got > had);
Packit Service 82fcde
	      }
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  if (msg.head.msgh_remote_port != MACH_PORT_NULL)
Packit Service 82fcde
	    __mach_port_deallocate (__mach_task_self (),
Packit Service 82fcde
				    msg.head.msgh_remote_port);
Packit Service 82fcde
Packit Service 82fcde
	  if (got)
Packit Service 82fcde
	  poll:
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* Poll for another message.  */
Packit Service 82fcde
	      to = 0;
Packit Service 82fcde
	      options |= MACH_RCV_TIMEOUT;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (msgerr == MACH_RCV_INTERRUPTED)
Packit Service 82fcde
	/* Interruption on our side (e.g. signal reception).  */
Packit Service 82fcde
	err = EINTR;
Packit Service 82fcde
Packit Service 82fcde
      if (got)
Packit Service 82fcde
	/* At least one descriptor is known to be ready now, so we will
Packit Service 82fcde
	   return success.  */
Packit Service 82fcde
	err = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (firstfd != -1)
Packit Service 82fcde
    for (i = firstfd; i <= lastfd; ++i)
Packit Service 82fcde
      if (d[i].type)
Packit Service 82fcde
	__mach_port_destroy (__mach_task_self (), d[i].reply_port);
Packit Service 82fcde
  if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
Packit Service 82fcde
    /* Destroy PORTSET, but only if it's not actually the reply port for a
Packit Service 82fcde
       single descriptor (in which case it's destroyed in the previous loop;
Packit Service 82fcde
       not doing it here is just a bit more efficient).  */
Packit Service 82fcde
    __mach_port_destroy (__mach_task_self (), portset);
Packit Service 82fcde
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (sigmask)
Packit Service 82fcde
	__sigprocmask (SIG_SETMASK, &oset, NULL);
Packit Service 82fcde
      return __hurd_fail (err);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pollfds)
Packit Service 82fcde
    /* Fill in the `revents' members of the user's array.  */
Packit Service 82fcde
    for (i = 0; i < nfds; ++i)
Packit Service 82fcde
      {
Packit Service 82fcde
	int type = d[i].type;
Packit Service 82fcde
	int_fast16_t revents = 0;
Packit Service 82fcde
Packit Service 82fcde
	if (type & SELECT_RETURNED)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if (type & SELECT_READ)
Packit Service 82fcde
	      revents |= POLLIN;
Packit Service 82fcde
	    if (type & SELECT_WRITE)
Packit Service 82fcde
	      revents |= POLLOUT;
Packit Service 82fcde
	    if (type & SELECT_URG)
Packit Service 82fcde
	      revents |= POLLPRI;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	pollfds[i].revents = revents;
Packit Service 82fcde
      }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Below we recalculate GOT to include an increment for each operation
Packit Service 82fcde
	 allowed on each fd.  */
Packit Service 82fcde
      got = 0;
Packit Service 82fcde
Packit Service 82fcde
      /* Set the user bitarrays.  We only ever have to clear bits, as all
Packit Service 82fcde
	 desired ones are initially set.  */
Packit Service 82fcde
      if (firstfd != -1)
Packit Service 82fcde
	for (i = firstfd; i <= lastfd; ++i)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    int type = d[i].type;
Packit Service 82fcde
Packit Service 82fcde
	    if ((type & SELECT_RETURNED) == 0)
Packit Service 82fcde
	      type = 0;
Packit Service 82fcde
Packit Service 82fcde
	    if (type & SELECT_READ)
Packit Service 82fcde
	      got++;
Packit Service 82fcde
	    else if (readfds)
Packit Service 82fcde
	      FD_CLR (i, readfds);
Packit Service 82fcde
	    if (type & SELECT_WRITE)
Packit Service 82fcde
	      got++;
Packit Service 82fcde
	    else if (writefds)
Packit Service 82fcde
	      FD_CLR (i, writefds);
Packit Service 82fcde
	    if (type & SELECT_URG)
Packit Service 82fcde
	      got++;
Packit Service 82fcde
	    else if (exceptfds)
Packit Service 82fcde
	      FD_CLR (i, exceptfds);
Packit Service 82fcde
	  }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  return got;
Packit Service 82fcde
}