diff options
Diffstat (limited to 'sysdeps/mach/hurd/getitimer.c')
-rw-r--r-- | sysdeps/mach/hurd/getitimer.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/getitimer.c b/sysdeps/mach/hurd/getitimer.c new file mode 100644 index 0000000000..15c46cae68 --- /dev/null +++ b/sysdeps/mach/hurd/getitimer.c @@ -0,0 +1,104 @@ +/* Copyright (C) 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <errno.h> +#include <sys/time.h> +#include <hurd.h> + +/* XXX Temporary cheezoid implementation; see __setitmr.c. */ + +/* These are defined in __setitmr.c. */ +extern spin_lock_t _hurd_itimer_lock; +extern struct itimerval _hurd_itimerval; +extern struct timeval _hurd_itimer_started; + +static inline void +subtract_timeval (struct timeval *from, const struct timeval *subtract) +{ + from->tv_usec -= subtract->tv_usec; + from->tv_sec -= subtract->tv_sec; + while (from->tv_usec < 0) + { + --from->tv_sec; + from->tv_usec += 1000000; + } +} + +/* Set *VALUE to the current setting of timer WHICH. + Return 0 on success, -1 on errors. */ +int +DEFUN(__getitimer, (which, value), + enum __itimer_which which AND struct itimerval *value) +{ + struct itimerval val; + struct timeval elapsed; + + switch (which) + { + default: + return __hurd_fail (EINVAL); + + case ITIMER_VIRTUAL: + case ITIMER_PROF: + return __hurd_fail (ENOSYS); + + case ITIMER_REAL: + break; + } + + /* Get the time now. */ + if (__gettimeofday (&elapsed, NULL) < 0) + return -1; + + /* Extract the current timer setting; and the time it was set, so we can + calculate the time elapsed so far. */ + HURD_CRITICAL_BEGIN; + __spin_lock (&_hurd_itimer_lock); + val = _hurd_itimerval; + subtract_timeval (&elapsed, &_hurd_itimer_started); + __spin_unlock (&_hurd_itimer_lock); + HURD_CRITICAL_END; + + if ((val.it_value.tv_sec | val.it_value.tv_usec) != 0) + { + /* There is a pending alarm set. VAL indicates the interval it was + set for, relative to the time recorded in _hurd_itimer_started. + Now compensate for the time elapsed since to get the user's + conception of the current value of the timer (as if the value + stored decreased every microsecond). */ + if (timercmp (&val.it_value, &elapsed, <)) + { + /* Hmm. The timer should have just gone off, but has not been + reset. This is a possible timing glitch. The alarm will signal + soon, so fabricate a value for how soon. */ + val.it_value.tv_sec = 0; + val.it_value.tv_usec = 10; /* Random. */ + } + else + /* Subtract the time elapsed since the timer was set + from the current timer value the user sees. */ + subtract_timeval (&val.it_value, &elapsed); + } + + *value = val; + return 0; +} + +weak_alias (__getitimer, getitimer) |