(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
getitimer.c
       1  /* Copyright (C) 1994-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <stddef.h>
      19  #include <errno.h>
      20  #include <sys/time.h>
      21  #include <hurd.h>
      22  #include <mach.h>
      23  
      24  /* XXX Temporary cheezoid implementation; see setitimer.c.  */
      25  
      26  /* These are defined in __setitmr.c.  */
      27  extern spin_lock_t _hurd_itimer_lock;
      28  extern struct itimerval _hurd_itimerval;
      29  extern struct timeval _hurd_itimer_started;
      30  
      31  static inline void
      32  subtract_timeval (struct timeval *from, const struct timeval *subtract)
      33  {
      34    from->tv_usec -= subtract->tv_usec;
      35    from->tv_sec -= subtract->tv_sec;
      36    while (from->tv_usec < 0)
      37      {
      38        --from->tv_sec;
      39        from->tv_usec += 1000000;
      40      }
      41  }
      42  
      43  /* Set *VALUE to the current setting of timer WHICH.
      44     Return 0 on success, -1 on errors.  */
      45  int
      46  __getitimer (enum __itimer_which which, struct itimerval *value)
      47  {
      48    struct itimerval val;
      49    struct timeval elapsed;
      50  
      51    switch (which)
      52      {
      53      default:
      54        return __hurd_fail (EINVAL);
      55  
      56      case ITIMER_VIRTUAL:
      57      case ITIMER_PROF:
      58        return __hurd_fail (ENOSYS);
      59  
      60      case ITIMER_REAL:
      61        break;
      62      }
      63  
      64    /* Get the time now.  */
      65    {
      66       time_value_t tv;
      67       __host_get_time (__mach_host_self (), &tv);
      68       elapsed.tv_sec = tv.seconds;
      69       elapsed.tv_usec = tv.microseconds;
      70    }
      71  
      72    /* Extract the current timer setting; and the time it was set, so we can
      73       calculate the time elapsed so far.  */
      74    HURD_CRITICAL_BEGIN;
      75    __spin_lock (&_hurd_itimer_lock);
      76    val = _hurd_itimerval;
      77    subtract_timeval (&elapsed, &_hurd_itimer_started);
      78    __spin_unlock (&_hurd_itimer_lock);
      79    HURD_CRITICAL_END;
      80  
      81    if ((val.it_value.tv_sec | val.it_value.tv_usec) != 0)
      82      {
      83        /* There is a pending alarm set.  VAL indicates the interval it was
      84  	 set for, relative to the time recorded in _hurd_itimer_started.
      85  	 Now compensate for the time elapsed since to get the user's
      86  	 conception of the current value of the timer (as if the value
      87  	 stored decreased every microsecond).  */
      88        if (timercmp (&val.it_value, &elapsed, <))
      89  	{
      90  	  /* Hmm.  The timer should have just gone off, but has not been
      91  	     reset.  This is a possible timing glitch.  The alarm will signal
      92  	     soon, so fabricate a value for how soon.  */
      93  	  val.it_value.tv_sec = 0;
      94  	  val.it_value.tv_usec = 10; /* Random.  */
      95  	}
      96        else
      97  	/* Subtract the time elapsed since the timer was set
      98  	   from the current timer value the user sees.  */
      99  	subtract_timeval (&val.it_value, &elapsed);
     100      }
     101  
     102    *value = val;
     103    return 0;
     104  }
     105  
     106  weak_alias (__getitimer, getitimer)