Sun Dec 18 22:30:25 2011 UTC ()
Fix monotonic interval timers.


(christos)
diff -r1.170 -r1.171 src/sys/kern/kern_time.c
diff -r1.8 -r1.9 src/sys/kern/subr_time.c
diff -r1.29 -r1.30 src/sys/sys/timevar.h

cvs diff -r1.170 -r1.171 src/sys/kern/kern_time.c (expand / switch to unified diff)

--- src/sys/kern/kern_time.c 2011/10/27 16:12:52 1.170
+++ src/sys/kern/kern_time.c 2011/12/18 22:30:25 1.171
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: kern_time.c,v 1.170 2011/10/27 16:12:52 christos Exp $ */ 1/* $NetBSD: kern_time.c,v 1.171 2011/12/18 22:30:25 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christopher G. Demetriou, and by Andrew Doran. 8 * by Christopher G. Demetriou, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 60 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.170 2011/10/27 16:12:52 christos Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.171 2011/12/18 22:30:25 christos Exp $");
65 65
66#include <sys/param.h> 66#include <sys/param.h>
67#include <sys/resourcevar.h> 67#include <sys/resourcevar.h>
68#include <sys/kernel.h> 68#include <sys/kernel.h>
69#include <sys/systm.h> 69#include <sys/systm.h>
70#include <sys/proc.h> 70#include <sys/proc.h>
71#include <sys/vnode.h> 71#include <sys/vnode.h>
72#include <sys/signalvar.h> 72#include <sys/signalvar.h>
73#include <sys/syslog.h> 73#include <sys/syslog.h>
74#include <sys/timetc.h> 74#include <sys/timetc.h>
75#include <sys/timex.h> 75#include <sys/timex.h>
76#include <sys/kauth.h> 76#include <sys/kauth.h>
77#include <sys/mount.h> 77#include <sys/mount.h>
@@ -664,27 +664,30 @@ timer_settime(struct ptimer *pt) @@ -664,27 +664,30 @@ timer_settime(struct ptimer *pt)
664{ 664{
665 struct ptimer *ptn, *pptn; 665 struct ptimer *ptn, *pptn;
666 struct ptlist *ptl; 666 struct ptlist *ptl;
667 667
668 KASSERT(mutex_owned(&timer_lock)); 668 KASSERT(mutex_owned(&timer_lock));
669 669
670 if (!CLOCK_VIRTUAL_P(pt->pt_type)) { 670 if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
671 callout_halt(&pt->pt_ch, &timer_lock); 671 callout_halt(&pt->pt_ch, &timer_lock);
672 if (timespecisset(&pt->pt_time.it_value)) { 672 if (timespecisset(&pt->pt_time.it_value)) {
673 /* 673 /*
674 * Don't need to check tshzto() return value, here. 674 * Don't need to check tshzto() return value, here.
675 * callout_reset() does it for us. 675 * callout_reset() does it for us.
676 */ 676 */
677 callout_reset(&pt->pt_ch, tshzto(&pt->pt_time.it_value), 677 callout_reset(&pt->pt_ch,
 678 pt->pt_type == CLOCK_MONOTONIC ?
 679 tshztoup(&pt->pt_time.it_value) :
 680 tshzto(&pt->pt_time.it_value),
678 realtimerexpire, pt); 681 realtimerexpire, pt);
679 } 682 }
680 } else { 683 } else {
681 if (pt->pt_active) { 684 if (pt->pt_active) {
682 ptn = LIST_NEXT(pt, pt_list); 685 ptn = LIST_NEXT(pt, pt_list);
683 LIST_REMOVE(pt, pt_list); 686 LIST_REMOVE(pt, pt_list);
684 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) 687 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
685 timespecadd(&pt->pt_time.it_value, 688 timespecadd(&pt->pt_time.it_value,
686 &ptn->pt_time.it_value, 689 &ptn->pt_time.it_value,
687 &ptn->pt_time.it_value); 690 &ptn->pt_time.it_value);
688 } 691 }
689 if (timespecisset(&pt->pt_time.it_value)) { 692 if (timespecisset(&pt->pt_time.it_value)) {
690 if (pt->pt_type == CLOCK_VIRTUAL) 693 if (pt->pt_type == CLOCK_VIRTUAL)
@@ -994,54 +997,59 @@ realtimerexpire(void *arg) @@ -994,54 +997,59 @@ realtimerexpire(void *arg)
994 int backwards; 997 int backwards;
995 998
996 pt = arg; 999 pt = arg;
997 1000
998 mutex_spin_enter(&timer_lock); 1001 mutex_spin_enter(&timer_lock);
999 itimerfire(pt); 1002 itimerfire(pt);
1000 1003
1001 if (!timespecisset(&pt->pt_time.it_interval)) { 1004 if (!timespecisset(&pt->pt_time.it_interval)) {
1002 timespecclear(&pt->pt_time.it_value); 1005 timespecclear(&pt->pt_time.it_value);
1003 mutex_spin_exit(&timer_lock); 1006 mutex_spin_exit(&timer_lock);
1004 return; 1007 return;
1005 } 1008 }
1006 1009
1007 getnanotime(&now); 1010 if (pt->pt_type == CLOCK_MONOTONIC) {
 1011 getnanouptime(&now);
 1012 } else {
 1013 getnanotime(&now);
 1014 }
1008 backwards = (timespeccmp(&pt->pt_time.it_value, &now, >)); 1015 backwards = (timespeccmp(&pt->pt_time.it_value, &now, >));
1009 timespecadd(&pt->pt_time.it_value, &pt->pt_time.it_interval, &next); 1016 timespecadd(&pt->pt_time.it_value, &pt->pt_time.it_interval, &next);
1010 /* Handle the easy case of non-overflown timers first. */ 1017 /* Handle the easy case of non-overflown timers first. */
1011 if (!backwards && timespeccmp(&next, &now, >)) { 1018 if (!backwards && timespeccmp(&next, &now, >)) {
1012 pt->pt_time.it_value = next; 1019 pt->pt_time.it_value = next;
1013 } else { 1020 } else {
1014 now_ns = timespec2ns(&now); 1021 now_ns = timespec2ns(&now);
1015 last_val = timespec2ns(&pt->pt_time.it_value); 1022 last_val = timespec2ns(&pt->pt_time.it_value);
1016 interval = timespec2ns(&pt->pt_time.it_interval); 1023 interval = timespec2ns(&pt->pt_time.it_interval);
1017 1024
1018 next_val = now_ns + 1025 next_val = now_ns +
1019 (now_ns - last_val + interval - 1) % interval; 1026 (now_ns - last_val + interval - 1) % interval;
1020 1027
1021 if (backwards) 1028 if (backwards)
1022 next_val += interval; 1029 next_val += interval;
1023 else 1030 else
1024 pt->pt_overruns += (now_ns - last_val) / interval; 1031 pt->pt_overruns += (now_ns - last_val) / interval;
1025 1032
1026 pt->pt_time.it_value.tv_sec = next_val / 1000000000; 1033 pt->pt_time.it_value.tv_sec = next_val / 1000000000;
1027 pt->pt_time.it_value.tv_nsec = next_val % 1000000000; 1034 pt->pt_time.it_value.tv_nsec = next_val % 1000000000;
1028 } 1035 }
1029 1036
1030 /* 1037 /*
1031 * Don't need to check tshzto() return value, here. 1038 * Don't need to check tshzto() return value, here.
1032 * callout_reset() does it for us. 1039 * callout_reset() does it for us.
1033 */ 1040 */
1034 callout_reset(&pt->pt_ch, tshzto(&pt->pt_time.it_value), 1041 callout_reset(&pt->pt_ch, pt->pt_type == CLOCK_MONOTONIC ?
 1042 tshztoup(&pt->pt_time.it_value) : tshzto(&pt->pt_time.it_value),
1035 realtimerexpire, pt); 1043 realtimerexpire, pt);
1036 mutex_spin_exit(&timer_lock); 1044 mutex_spin_exit(&timer_lock);
1037} 1045}
1038 1046
1039/* BSD routine to get the value of an interval timer. */ 1047/* BSD routine to get the value of an interval timer. */
1040/* ARGSUSED */ 1048/* ARGSUSED */
1041int 1049int
1042sys___getitimer50(struct lwp *l, const struct sys___getitimer50_args *uap, 1050sys___getitimer50(struct lwp *l, const struct sys___getitimer50_args *uap,
1043 register_t *retval) 1051 register_t *retval)
1044{ 1052{
1045 /* { 1053 /* {
1046 syscallarg(int) which; 1054 syscallarg(int) which;
1047 syscallarg(struct itimerval *) itv; 1055 syscallarg(struct itimerval *) itv;

cvs diff -r1.8 -r1.9 src/sys/kern/subr_time.c (expand / switch to unified diff)

--- src/sys/kern/subr_time.c 2011/01/26 19:15:13 1.8
+++ src/sys/kern/subr_time.c 2011/12/18 22:30:25 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr_time.c,v 1.8 2011/01/26 19:15:13 drochner Exp $ */ 1/* $NetBSD: subr_time.c,v 1.9 2011/12/18 22:30:25 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1993 4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -23,27 +23,27 @@ @@ -23,27 +23,27 @@
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 * 30 *
31 * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 31 * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
32 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 32 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.8 2011/01/26 19:15:13 drochner Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.9 2011/12/18 22:30:25 christos Exp $");
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/timex.h> 40#include <sys/timex.h>
41#include <sys/time.h> 41#include <sys/time.h>
42#include <sys/timetc.h> 42#include <sys/timetc.h>
43#include <sys/intr.h> 43#include <sys/intr.h>
44 44
45/* 45/*
46 * Compute number of hz until specified time. Used to compute second 46 * Compute number of hz until specified time. Used to compute second
47 * argument to callout_reset() from an absolute time. 47 * argument to callout_reset() from an absolute time.
48 */ 48 */
49int 49int
@@ -119,26 +119,38 @@ tvtohz(const struct timeval *tv) @@ -119,26 +119,38 @@ tvtohz(const struct timeval *tv)
119 return ((int)ticks); 119 return ((int)ticks);
120} 120}
121 121
122int 122int
123tshzto(const struct timespec *tsp) 123tshzto(const struct timespec *tsp)
124{ 124{
125 struct timespec now, ts; 125 struct timespec now, ts;
126 126
127 ts = *tsp; /* Don't modify original tsp. */ 127 ts = *tsp; /* Don't modify original tsp. */
128 getnanotime(&now); 128 getnanotime(&now);
129 timespecsub(&ts, &now, &ts); 129 timespecsub(&ts, &now, &ts);
130 return tstohz(&ts); 130 return tstohz(&ts);
131} 131}
 132
 133int
 134tshztoup(const struct timespec *tsp)
 135{
 136 struct timespec now, ts;
 137
 138 ts = *tsp; /* Don't modify original tsp. */
 139 getnanouptime(&now);
 140 timespecsub(&ts, &now, &ts);
 141 return tstohz(&ts);
 142}
 143
132/* 144/*
133 * Compute number of ticks in the specified amount of time. 145 * Compute number of ticks in the specified amount of time.
134 */ 146 */
135int 147int
136tstohz(const struct timespec *ts) 148tstohz(const struct timespec *ts)
137{ 149{
138 struct timeval tv; 150 struct timeval tv;
139 151
140 /* 152 /*
141 * usec has great enough resolution for hz, so convert to a 153 * usec has great enough resolution for hz, so convert to a
142 * timeval and use tvtohz() above. 154 * timeval and use tvtohz() above.
143 */ 155 */
144 TIMESPEC_TO_TIMEVAL(&tv, ts); 156 TIMESPEC_TO_TIMEVAL(&tv, ts);

cvs diff -r1.29 -r1.30 src/sys/sys/timevar.h (expand / switch to unified diff)

--- src/sys/sys/timevar.h 2010/04/08 11:51:13 1.29
+++ src/sys/sys/timevar.h 2011/12/18 22:30:25 1.30
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: timevar.h,v 1.29 2010/04/08 11:51:13 njoly Exp $ */ 1/* $NetBSD: timevar.h,v 1.30 2011/12/18 22:30:25 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005, 2008 The NetBSD Foundation. 4 * Copyright (c) 2005, 2008 The NetBSD Foundation.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -146,26 +146,27 @@ void getmicrotime(struct timeval *); @@ -146,26 +146,27 @@ void getmicrotime(struct timeval *);
146 146
147/* Other functions */ 147/* Other functions */
148int abstimeout2timo(struct timespec *, int *); 148int abstimeout2timo(struct timespec *, int *);
149void adjtime1(const struct timeval *, struct timeval *, struct proc *); 149void adjtime1(const struct timeval *, struct timeval *, struct proc *);
150int clock_getres1(clockid_t, struct timespec *); 150int clock_getres1(clockid_t, struct timespec *);
151int clock_gettime1(clockid_t, struct timespec *); 151int clock_gettime1(clockid_t, struct timespec *);
152int clock_settime1(struct proc *, clockid_t, const struct timespec *, bool); 152int clock_settime1(struct proc *, clockid_t, const struct timespec *, bool);
153int dogetitimer(struct proc *, int, struct itimerval *); 153int dogetitimer(struct proc *, int, struct itimerval *);
154int dosetitimer(struct proc *, int, struct itimerval *); 154int dosetitimer(struct proc *, int, struct itimerval *);
155int dotimer_gettime(int, struct proc *, struct itimerspec *); 155int dotimer_gettime(int, struct proc *, struct itimerspec *);
156int dotimer_settime(int, struct itimerspec *, struct itimerspec *, int, 156int dotimer_settime(int, struct itimerspec *, struct itimerspec *, int,
157 struct proc *); 157 struct proc *);
158int tshzto(const struct timespec *); 158int tshzto(const struct timespec *);
 159int tshztoup(const struct timespec *);
159int tvhzto(const struct timeval *); 160int tvhzto(const struct timeval *);
160void inittimecounter(void); 161void inittimecounter(void);
161int itimerfix(struct timeval *); 162int itimerfix(struct timeval *);
162int itimespecfix(struct timespec *); 163int itimespecfix(struct timespec *);
163int ppsratecheck(struct timeval *, int *, int); 164int ppsratecheck(struct timeval *, int *, int);
164int ratecheck(struct timeval *, const struct timeval *); 165int ratecheck(struct timeval *, const struct timeval *);
165void realtimerexpire(void *); 166void realtimerexpire(void *);
166int settime(struct proc *p, struct timespec *); 167int settime(struct proc *p, struct timespec *);
167int nanosleep1(struct lwp *l, struct timespec *, struct timespec *); 168int nanosleep1(struct lwp *l, struct timespec *, struct timespec *);
168int settimeofday1(const struct timeval *, bool, 169int settimeofday1(const struct timeval *, bool,
169 const void *, struct lwp *, bool); 170 const void *, struct lwp *, bool);
170int timer_create1(timer_t *, clockid_t, struct sigevent *, copyin_t, 171int timer_create1(timer_t *, clockid_t, struct sigevent *, copyin_t,
171 struct lwp *); 172 struct lwp *);