Blame misc/pselect.c

Packit 6c4009
/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <signal.h>
Packit 6c4009
#include <stddef.h>	/* For NULL.  */
Packit 6c4009
#include <sys/time.h>
Packit 6c4009
#include <sys/select.h>
Packit 6c4009
#include <sysdep-cancel.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
Packit 6c4009
   readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
Packit 6c4009
   (if not NULL) for exceptional conditions.  If TIMEOUT is not NULL, time out
Packit 6c4009
   after waiting the interval specified therein.  Additionally set the sigmask
Packit 6c4009
   SIGMASK for this call.  Returns the number of ready descriptors, or -1 for
Packit 6c4009
   errors.  */
Packit 6c4009
int
Packit 6c4009
__pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
Packit 6c4009
	   const struct timespec *timeout, const sigset_t *sigmask)
Packit 6c4009
{
Packit 6c4009
  struct timeval tval;
Packit 6c4009
  int retval;
Packit 6c4009
  sigset_t savemask;
Packit 6c4009
Packit 6c4009
  /* Change nanosecond number to microseconds.  This might mean losing
Packit 6c4009
     precision and therefore the `pselect` should be available.  But
Packit 6c4009
     for now it is hardly found.  */
Packit 6c4009
  if (timeout != NULL)
Packit 6c4009
    {
Packit 6c4009
      /* Catch bugs which would be hidden by the TIMESPEC_TO_TIMEVAL
Packit 6c4009
	 computations.  The division by 1000 truncates values.  */
Packit 6c4009
      if (__glibc_unlikely (timeout->tv_nsec < 0))
Packit 6c4009
	{
Packit 6c4009
	  __set_errno (EINVAL);
Packit 6c4009
	  return -1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      TIMESPEC_TO_TIMEVAL (&tval, timeout);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* The setting and restoring of the signal mask and the select call
Packit 6c4009
     should be an atomic operation.  This can't be done without kernel
Packit 6c4009
     help.  */
Packit 6c4009
  if (sigmask != NULL)
Packit 6c4009
    __sigprocmask (SIG_SETMASK, sigmask, &savemask);
Packit 6c4009
Packit 6c4009
  /* Note the pselect() is a cancellation point.  But since we call
Packit 6c4009
     select() which itself is a cancellation point we do not have
Packit 6c4009
     to do anything here.  */
Packit 6c4009
  retval = __select (nfds, readfds, writefds, exceptfds,
Packit 6c4009
		     timeout != NULL ? &tval : NULL);
Packit 6c4009
Packit 6c4009
  if (sigmask != NULL)
Packit 6c4009
    __sigprocmask (SIG_SETMASK, &savemask, NULL);
Packit 6c4009
Packit 6c4009
  return retval;
Packit 6c4009
}
Packit 6c4009
#ifndef __pselect
Packit 6c4009
weak_alias (__pselect, pselect)
Packit 6c4009
/* __select handles cancellation.  */
Packit 6c4009
LIBC_CANCEL_HANDLED ();
Packit 6c4009
#endif