Blame sysdeps/mach/hurd/getitimer.c

Packit 6c4009
/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
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 <stddef.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <sys/time.h>
Packit 6c4009
#include <hurd.h>
Packit 6c4009
Packit 6c4009
/* XXX Temporary cheezoid implementation; see __setitmr.c.  */
Packit 6c4009
Packit 6c4009
/* These are defined in __setitmr.c.  */
Packit 6c4009
extern spin_lock_t _hurd_itimer_lock;
Packit 6c4009
extern struct itimerval _hurd_itimerval;
Packit 6c4009
extern struct timeval _hurd_itimer_started;
Packit 6c4009
Packit 6c4009
static inline void
Packit 6c4009
subtract_timeval (struct timeval *from, const struct timeval *subtract)
Packit 6c4009
{
Packit 6c4009
  from->tv_usec -= subtract->tv_usec;
Packit 6c4009
  from->tv_sec -= subtract->tv_sec;
Packit 6c4009
  while (from->tv_usec < 0)
Packit 6c4009
    {
Packit 6c4009
      --from->tv_sec;
Packit 6c4009
      from->tv_usec += 1000000;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Set *VALUE to the current setting of timer WHICH.
Packit 6c4009
   Return 0 on success, -1 on errors.  */
Packit 6c4009
int
Packit 6c4009
__getitimer (enum __itimer_which which, struct itimerval *value)
Packit 6c4009
{
Packit 6c4009
  struct itimerval val;
Packit 6c4009
  struct timeval elapsed;
Packit 6c4009
Packit 6c4009
  switch (which)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      return __hurd_fail (EINVAL);
Packit 6c4009
Packit 6c4009
    case ITIMER_VIRTUAL:
Packit 6c4009
    case ITIMER_PROF:
Packit 6c4009
      return __hurd_fail (ENOSYS);
Packit 6c4009
Packit 6c4009
    case ITIMER_REAL:
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Get the time now.  */
Packit 6c4009
  if (__gettimeofday (&elapsed, NULL) < 0)
Packit 6c4009
    return -1;
Packit 6c4009
Packit 6c4009
  /* Extract the current timer setting; and the time it was set, so we can
Packit 6c4009
     calculate the time elapsed so far.  */
Packit 6c4009
  HURD_CRITICAL_BEGIN;
Packit 6c4009
  __spin_lock (&_hurd_itimer_lock);
Packit 6c4009
  val = _hurd_itimerval;
Packit 6c4009
  subtract_timeval (&elapsed, &_hurd_itimer_started);
Packit 6c4009
  __spin_unlock (&_hurd_itimer_lock);
Packit 6c4009
  HURD_CRITICAL_END;
Packit 6c4009
Packit 6c4009
  if ((val.it_value.tv_sec | val.it_value.tv_usec) != 0)
Packit 6c4009
    {
Packit 6c4009
      /* There is a pending alarm set.  VAL indicates the interval it was
Packit 6c4009
	 set for, relative to the time recorded in _hurd_itimer_started.
Packit 6c4009
	 Now compensate for the time elapsed since to get the user's
Packit 6c4009
	 conception of the current value of the timer (as if the value
Packit 6c4009
	 stored decreased every microsecond).  */
Packit 6c4009
      if (timercmp (&val.it_value, &elapsed, <))
Packit 6c4009
	{
Packit 6c4009
	  /* Hmm.  The timer should have just gone off, but has not been
Packit 6c4009
	     reset.  This is a possible timing glitch.  The alarm will signal
Packit 6c4009
	     soon, so fabricate a value for how soon.  */
Packit 6c4009
	  val.it_value.tv_sec = 0;
Packit 6c4009
	  val.it_value.tv_usec = 10; /* Random.  */
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	/* Subtract the time elapsed since the timer was set
Packit 6c4009
	   from the current timer value the user sees.  */
Packit 6c4009
	subtract_timeval (&val.it_value, &elapsed);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  *value = val;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
weak_alias (__getitimer, getitimer)