summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2014-02-28 10:31:12 +0100
committerAndy Wingo <wingo@pobox.com>2014-02-28 10:31:12 +0100
commit966d4bdd70a574b86f5feb21cc2925c756e39c3b (patch)
tree3fe045a930eaa455c115eab0691d86e84b94f072
parentfc2b8f6c6d347f0f1508b9ed63cb820de3d17276 (diff)
downloadguile-966d4bdd70a574b86f5feb21cc2925c756e39c3b.tar.gz
Fix setitimer documentation. Allow microseconds >= 1e6.
* doc/ref/posix.texi (Signals): Fix the documentation for setitimer; it was wrong. * libguile/scmsigs.c (pack_tv): New helper. Allow usecs >= 1e6. (unpack_tv): New helper. (scm_setitimer): Use the new helpers. * test-suite/tests/signals.test: Add setitimer tests.
-rw-r--r--doc/ref/posix.texi32
-rw-r--r--libguile/scmsigs.c31
-rw-r--r--test-suite/tests/signals.test43
3 files changed, 81 insertions, 25 deletions
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index 6cd90bc6a..570102c27 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -2130,14 +2130,17 @@ the C level (@pxref{Blocking}).
@end deffn
@deffn {Scheme Procedure} getitimer which_timer
-@deffnx {Scheme Procedure} setitimer which_timer interval_seconds interval_microseconds periodic_seconds periodic_microseconds
+@deffnx {Scheme Procedure} setitimer which_timer interval_seconds interval_microseconds value_seconds value_microseconds
@deffnx {C Function} scm_getitimer (which_timer)
-@deffnx {C Function} scm_setitimer (which_timer, interval_seconds, interval_microseconds, periodic_seconds, periodic_microseconds)
-Get or set the periods programmed in certain system timers. These
-timers have a current interval value which counts down and on reaching
-zero raises a signal. An optional periodic value can be set to
-restart from there each time, for periodic operation.
-@var{which_timer} is one of the following values
+@deffnx {C Function} scm_setitimer (which_timer, interval_seconds, interval_microseconds, value_seconds, value_microseconds)
+Get or set the periods programmed in certain system timers.
+
+These timers have two settings. The first setting, the interval, is the
+value at which the timer will be reset when the current timer expires.
+The second is the current value of the timer, indicating when the next
+expiry will be signalled.
+
+@var{which_timer} is one of the following values:
@defvar ITIMER_REAL
A real-time timer, counting down elapsed real time. At zero it raises
@@ -2159,21 +2162,20 @@ This timer is intended for profiling where a program is spending its
time (by looking where it is when the timer goes off).
@end defvar
-@code{getitimer} returns the current timer value and its programmed
-restart value, as a list containing two pairs. Each pair is a time in
-seconds and microseconds: @code{((@var{interval_secs}
-. @var{interval_usecs}) (@var{periodic_secs}
-. @var{periodic_usecs}))}.
+@code{getitimer} returns the restart timer value and its current value,
+as a list containing two pairs. Each pair is a time in seconds and
+microseconds: @code{((@var{interval_secs} . @var{interval_usecs})
+(@var{value_secs} . @var{value_usecs}))}.
@code{setitimer} sets the timer values similarly, in seconds and
-microseconds (which must be integers). The periodic value can be zero
+microseconds (which must be integers). The interval value can be zero
to have the timer run down just once. The return value is the timer's
previous setting, in the same form as @code{getitimer} returns.
@example
(setitimer ITIMER_REAL
- 5 500000 ;; first SIGALRM in 5.5 seconds time
- 2 0) ;; then repeat every 2 seconds
+ 5 500000 ;; Raise SIGALRM every 5.5 seconds
+ 2 0) ;; with the first SIGALRM in 2 seconds
@end example
Although the timers are programmed in microseconds, the actual
diff --git a/libguile/scmsigs.c b/libguile/scmsigs.c
index d0a0c194d..d65dcea84 100644
--- a/libguile/scmsigs.c
+++ b/libguile/scmsigs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2007, 2008, 2009, 2011, 2013 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2007, 2008, 2009, 2011, 2013, 2014 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -514,6 +514,23 @@ SCM_DEFINE (scm_alarm, "alarm", 1, 0, 0,
#undef FUNC_NAME
#endif /* HAVE_ALARM */
+static void
+pack_tv (struct timeval *tv, SCM seconds, SCM microseconds)
+{
+ tv->tv_sec = scm_to_long (seconds);
+ tv->tv_usec = scm_to_long (microseconds);
+
+ /* Allow usec to be outside the range [0, 999999). */
+ tv->tv_sec += tv->tv_usec / (1000 * 1000);
+ tv->tv_usec %= 1000 * 1000;
+}
+
+static SCM
+unpack_tv (const struct timeval *tv)
+{
+ return scm_cons (scm_from_long (tv->tv_sec), scm_from_long (tv->tv_usec));
+}
+
#ifdef HAVE_SETITIMER
SCM_DEFINE (scm_setitimer, "setitimer", 5, 0, 0,
(SCM which_timer,
@@ -543,20 +560,16 @@ SCM_DEFINE (scm_setitimer, "setitimer", 5, 0, 0,
struct itimerval old_timer;
c_which_timer = SCM_NUM2INT(1, which_timer);
- new_timer.it_interval.tv_sec = SCM_NUM2LONG(2, interval_seconds);
- new_timer.it_interval.tv_usec = SCM_NUM2LONG(3, interval_microseconds);
- new_timer.it_value.tv_sec = SCM_NUM2LONG(4, value_seconds);
- new_timer.it_value.tv_usec = SCM_NUM2LONG(5, value_microseconds);
+ pack_tv (&new_timer.it_interval, interval_seconds, interval_microseconds);
+ pack_tv (&new_timer.it_value, value_seconds, value_microseconds);
SCM_SYSCALL(rv = setitimer(c_which_timer, &new_timer, &old_timer));
if(rv != 0)
SCM_SYSERROR;
- return scm_list_2 (scm_cons (scm_from_long (old_timer.it_interval.tv_sec),
- scm_from_long (old_timer.it_interval.tv_usec)),
- scm_cons (scm_from_long (old_timer.it_value.tv_sec),
- scm_from_long (old_timer.it_value.tv_usec)));
+ return scm_list_2 (unpack_tv (&old_timer.it_interval),
+ unpack_tv (&old_timer.it_value));
}
#undef FUNC_NAME
#endif /* HAVE_SETITIMER */
diff --git a/test-suite/tests/signals.test b/test-suite/tests/signals.test
index c05ecd94c..ec1c4152d 100644
--- a/test-suite/tests/signals.test
+++ b/test-suite/tests/signals.test
@@ -1,6 +1,6 @@
;;;; signals.test --- test suite for Guile's signal functions -*- scheme -*-
;;;;
-;;;; Copyright (C) 2009 Free Software Foundation, Inc.
+;;;; Copyright (C) 2009, 2014 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
@@ -18,6 +18,7 @@
;;;; Boston, MA 02110-1301 USA
(define-module (test-suite test-signals)
+ #:use-module (ice-9 match)
#:use-module (test-suite lib))
(with-test-prefix "sigaction"
@@ -27,3 +28,43 @@
(sigaction SIGINT 51))
)
+
+(when (defined? 'setitimer)
+ (with-test-prefix "setitimer"
+ (with-test-prefix "current itimers are 0"
+ (pass-if "ITIMER_REAL"
+ (equal? (setitimer ITIMER_REAL 0 0 0 0)
+ '((0 . 0) (0 . 0))))
+ (pass-if "ITIMER_VIRTUAL"
+ (equal? (setitimer ITIMER_VIRTUAL 0 0 0 0)
+ '((0 . 0) (0 . 0))))
+ (pass-if "ITIMER_PROF"
+ (equal? (setitimer ITIMER_PROF 0 0 0 0)
+ '((0 . 0) (0 . 0)))))
+
+ (with-test-prefix "setting values correctly"
+ (pass-if "initial setting"
+ (equal? (setitimer ITIMER_PROF 1 0 3 0)
+ '((0 . 0) (0 . 0))))
+ (pass-if "reset to zero"
+ (match (setitimer ITIMER_PROF 0 0 0 0)
+ (((1 . 0) (val-secs . val-usecs))
+ ;; We don't presume that the timer is strictly lower than the
+ ;; value at which we set it, given its limited internal
+ ;; precision. Assert instead that the timer is between 2 and
+ ;; 3.5 seconds.
+ (<= #e2e6 (+ (* val-secs #e1e6) val-usecs) #e3.5e6)))))
+
+ (with-test-prefix "usecs > 1e6"
+ (pass-if "initial setting"
+ (equal? (setitimer ITIMER_PROF 1 0 0 #e3e6)
+ '((0 . 0) (0 . 0))))
+ (pass-if "reset to zero"
+ (match (setitimer ITIMER_PROF 0 0 0 0)
+ (((1 . 0) (val-secs . val-usecs))
+ ;; We don't presume that the timer is strictly lower than the
+ ;; value at which we set it, given its limited internal
+ ;; precision. Assert instead that the timer is between 2 and
+ ;; 3.5 seconds.
+ (and (<= #e2e6 (+ (* val-secs #e1e6) val-usecs) #e3.5e6)
+ (<= 0 val-usecs 999999))))))))