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 (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,1539 +1,1547 @@ @@ -1,1539 +1,1547 @@
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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1982, 1986, 1989, 1993 33 * Copyright (c) 1982, 1986, 1989, 1993
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors 44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software 45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission. 46 * without specific prior written permission.
47 * 47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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>
78#include <sys/sa.h> 78#include <sys/sa.h>
79#include <sys/savar.h> 79#include <sys/savar.h>
80#include <sys/syscallargs.h> 80#include <sys/syscallargs.h>
81#include <sys/cpu.h> 81#include <sys/cpu.h>
82 82
83#include "opt_sa.h" 83#include "opt_sa.h"
84 84
85static void timer_intr(void *); 85static void timer_intr(void *);
86static void itimerfire(struct ptimer *); 86static void itimerfire(struct ptimer *);
87static void itimerfree(struct ptimers *, int); 87static void itimerfree(struct ptimers *, int);
88 88
89kmutex_t timer_lock; 89kmutex_t timer_lock;
90 90
91static void *timer_sih; 91static void *timer_sih;
92static TAILQ_HEAD(, ptimer) timer_queue; 92static TAILQ_HEAD(, ptimer) timer_queue;
93 93
94struct pool ptimer_pool, ptimers_pool; 94struct pool ptimer_pool, ptimers_pool;
95 95
96#define CLOCK_VIRTUAL_P(clockid) \ 96#define CLOCK_VIRTUAL_P(clockid) \
97 ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF) 97 ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF)
98 98
99CTASSERT(ITIMER_REAL == CLOCK_REALTIME); 99CTASSERT(ITIMER_REAL == CLOCK_REALTIME);
100CTASSERT(ITIMER_VIRTUAL == CLOCK_VIRTUAL); 100CTASSERT(ITIMER_VIRTUAL == CLOCK_VIRTUAL);
101CTASSERT(ITIMER_PROF == CLOCK_PROF); 101CTASSERT(ITIMER_PROF == CLOCK_PROF);
102CTASSERT(ITIMER_MONOTONIC == CLOCK_MONOTONIC); 102CTASSERT(ITIMER_MONOTONIC == CLOCK_MONOTONIC);
103 103
104/* 104/*
105 * Initialize timekeeping. 105 * Initialize timekeeping.
106 */ 106 */
107void 107void
108time_init(void) 108time_init(void)
109{ 109{
110 110
111 pool_init(&ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl", 111 pool_init(&ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
112 &pool_allocator_nointr, IPL_NONE); 112 &pool_allocator_nointr, IPL_NONE);
113 pool_init(&ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl", 113 pool_init(&ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl",
114 &pool_allocator_nointr, IPL_NONE); 114 &pool_allocator_nointr, IPL_NONE);
115} 115}
116 116
117void 117void
118time_init2(void) 118time_init2(void)
119{ 119{
120 120
121 TAILQ_INIT(&timer_queue); 121 TAILQ_INIT(&timer_queue);
122 mutex_init(&timer_lock, MUTEX_DEFAULT, IPL_SCHED); 122 mutex_init(&timer_lock, MUTEX_DEFAULT, IPL_SCHED);
123 timer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, 123 timer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
124 timer_intr, NULL); 124 timer_intr, NULL);
125} 125}
126 126
127/* Time of day and interval timer support. 127/* Time of day and interval timer support.
128 * 128 *
129 * These routines provide the kernel entry points to get and set 129 * These routines provide the kernel entry points to get and set
130 * the time-of-day and per-process interval timers. Subroutines 130 * the time-of-day and per-process interval timers. Subroutines
131 * here provide support for adding and subtracting timeval structures 131 * here provide support for adding and subtracting timeval structures
132 * and decrementing interval timers, optionally reloading the interval 132 * and decrementing interval timers, optionally reloading the interval
133 * timers when they expire. 133 * timers when they expire.
134 */ 134 */
135 135
136/* This function is used by clock_settime and settimeofday */ 136/* This function is used by clock_settime and settimeofday */
137static int 137static int
138settime1(struct proc *p, const struct timespec *ts, bool check_kauth) 138settime1(struct proc *p, const struct timespec *ts, bool check_kauth)
139{ 139{
140 struct timespec delta, now; 140 struct timespec delta, now;
141 int s; 141 int s;
142 142
143 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 143 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
144 s = splclock(); 144 s = splclock();
145 nanotime(&now); 145 nanotime(&now);
146 timespecsub(ts, &now, &delta); 146 timespecsub(ts, &now, &delta);
147 147
148 if (check_kauth && kauth_authorize_system(kauth_cred_get(), 148 if (check_kauth && kauth_authorize_system(kauth_cred_get(),
149 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts), 149 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts),
150 &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) { 150 &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) {
151 splx(s); 151 splx(s);
152 return (EPERM); 152 return (EPERM);
153 } 153 }
154 154
155#ifdef notyet 155#ifdef notyet
156 if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */ 156 if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */
157 splx(s); 157 splx(s);
158 return (EPERM); 158 return (EPERM);
159 } 159 }
160#endif 160#endif
161 161
162 tc_setclock(ts); 162 tc_setclock(ts);
163 163
164 timespecadd(&boottime, &delta, &boottime); 164 timespecadd(&boottime, &delta, &boottime);
165 165
166 resettodr(); 166 resettodr();
167 splx(s); 167 splx(s);
168 168
169 return (0); 169 return (0);
170} 170}
171 171
172int 172int
173settime(struct proc *p, struct timespec *ts) 173settime(struct proc *p, struct timespec *ts)
174{ 174{
175 return (settime1(p, ts, true)); 175 return (settime1(p, ts, true));
176} 176}
177 177
178/* ARGSUSED */ 178/* ARGSUSED */
179int 179int
180sys___clock_gettime50(struct lwp *l, 180sys___clock_gettime50(struct lwp *l,
181 const struct sys___clock_gettime50_args *uap, register_t *retval) 181 const struct sys___clock_gettime50_args *uap, register_t *retval)
182{ 182{
183 /* { 183 /* {
184 syscallarg(clockid_t) clock_id; 184 syscallarg(clockid_t) clock_id;
185 syscallarg(struct timespec *) tp; 185 syscallarg(struct timespec *) tp;
186 } */ 186 } */
187 int error; 187 int error;
188 struct timespec ats; 188 struct timespec ats;
189 189
190 error = clock_gettime1(SCARG(uap, clock_id), &ats); 190 error = clock_gettime1(SCARG(uap, clock_id), &ats);
191 if (error != 0) 191 if (error != 0)
192 return error; 192 return error;
193 193
194 return copyout(&ats, SCARG(uap, tp), sizeof(ats)); 194 return copyout(&ats, SCARG(uap, tp), sizeof(ats));
195} 195}
196 196
197int 197int
198clock_gettime1(clockid_t clock_id, struct timespec *ts) 198clock_gettime1(clockid_t clock_id, struct timespec *ts)
199{ 199{
200 200
201 switch (clock_id) { 201 switch (clock_id) {
202 case CLOCK_REALTIME: 202 case CLOCK_REALTIME:
203 nanotime(ts); 203 nanotime(ts);
204 break; 204 break;
205 case CLOCK_MONOTONIC: 205 case CLOCK_MONOTONIC:
206 nanouptime(ts); 206 nanouptime(ts);
207 break; 207 break;
208 default: 208 default:
209 return EINVAL; 209 return EINVAL;
210 } 210 }
211 211
212 return 0; 212 return 0;
213} 213}
214 214
215/* ARGSUSED */ 215/* ARGSUSED */
216int 216int
217sys___clock_settime50(struct lwp *l, 217sys___clock_settime50(struct lwp *l,
218 const struct sys___clock_settime50_args *uap, register_t *retval) 218 const struct sys___clock_settime50_args *uap, register_t *retval)
219{ 219{
220 /* { 220 /* {
221 syscallarg(clockid_t) clock_id; 221 syscallarg(clockid_t) clock_id;
222 syscallarg(const struct timespec *) tp; 222 syscallarg(const struct timespec *) tp;
223 } */ 223 } */
224 int error; 224 int error;
225 struct timespec ats; 225 struct timespec ats;
226 226
227 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) 227 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
228 return error; 228 return error;
229 229
230 return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, true); 230 return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, true);
231} 231}
232 232
233 233
234int 234int
235clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp, 235clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp,
236 bool check_kauth) 236 bool check_kauth)
237{ 237{
238 int error; 238 int error;
239 239
240 switch (clock_id) { 240 switch (clock_id) {
241 case CLOCK_REALTIME: 241 case CLOCK_REALTIME:
242 if ((error = settime1(p, tp, check_kauth)) != 0) 242 if ((error = settime1(p, tp, check_kauth)) != 0)
243 return (error); 243 return (error);
244 break; 244 break;
245 case CLOCK_MONOTONIC: 245 case CLOCK_MONOTONIC:
246 return (EINVAL); /* read-only clock */ 246 return (EINVAL); /* read-only clock */
247 default: 247 default:
248 return (EINVAL); 248 return (EINVAL);
249 } 249 }
250 250
251 return 0; 251 return 0;
252} 252}
253 253
254int 254int
255sys___clock_getres50(struct lwp *l, const struct sys___clock_getres50_args *uap, 255sys___clock_getres50(struct lwp *l, const struct sys___clock_getres50_args *uap,
256 register_t *retval) 256 register_t *retval)
257{ 257{
258 /* { 258 /* {
259 syscallarg(clockid_t) clock_id; 259 syscallarg(clockid_t) clock_id;
260 syscallarg(struct timespec *) tp; 260 syscallarg(struct timespec *) tp;
261 } */ 261 } */
262 struct timespec ts; 262 struct timespec ts;
263 int error = 0; 263 int error = 0;
264 264
265 if ((error = clock_getres1(SCARG(uap, clock_id), &ts)) != 0) 265 if ((error = clock_getres1(SCARG(uap, clock_id), &ts)) != 0)
266 return error; 266 return error;
267 267
268 if (SCARG(uap, tp)) 268 if (SCARG(uap, tp))
269 error = copyout(&ts, SCARG(uap, tp), sizeof(ts)); 269 error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
270 270
271 return error; 271 return error;
272} 272}
273 273
274int 274int
275clock_getres1(clockid_t clock_id, struct timespec *ts) 275clock_getres1(clockid_t clock_id, struct timespec *ts)
276{ 276{
277 277
278 switch (clock_id) { 278 switch (clock_id) {
279 case CLOCK_REALTIME: 279 case CLOCK_REALTIME:
280 case CLOCK_MONOTONIC: 280 case CLOCK_MONOTONIC:
281 ts->tv_sec = 0; 281 ts->tv_sec = 0;
282 if (tc_getfrequency() > 1000000000) 282 if (tc_getfrequency() > 1000000000)
283 ts->tv_nsec = 1; 283 ts->tv_nsec = 1;
284 else 284 else
285 ts->tv_nsec = 1000000000 / tc_getfrequency(); 285 ts->tv_nsec = 1000000000 / tc_getfrequency();
286 break; 286 break;
287 default: 287 default:
288 return EINVAL; 288 return EINVAL;
289 } 289 }
290 290
291 return 0; 291 return 0;
292} 292}
293 293
294/* ARGSUSED */ 294/* ARGSUSED */
295int 295int
296sys___nanosleep50(struct lwp *l, const struct sys___nanosleep50_args *uap, 296sys___nanosleep50(struct lwp *l, const struct sys___nanosleep50_args *uap,
297 register_t *retval) 297 register_t *retval)
298{ 298{
299 /* { 299 /* {
300 syscallarg(struct timespec *) rqtp; 300 syscallarg(struct timespec *) rqtp;
301 syscallarg(struct timespec *) rmtp; 301 syscallarg(struct timespec *) rmtp;
302 } */ 302 } */
303 struct timespec rmt, rqt; 303 struct timespec rmt, rqt;
304 int error, error1; 304 int error, error1;
305 305
306 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec)); 306 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
307 if (error) 307 if (error)
308 return (error); 308 return (error);
309 309
310 error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL); 310 error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL);
311 if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 311 if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR))
312 return error; 312 return error;
313 313
314 error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt)); 314 error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
315 return error1 ? error1 : error; 315 return error1 ? error1 : error;
316} 316}
317 317
318int 318int
319nanosleep1(struct lwp *l, struct timespec *rqt, struct timespec *rmt) 319nanosleep1(struct lwp *l, struct timespec *rqt, struct timespec *rmt)
320{ 320{
321 struct timespec rmtstart; 321 struct timespec rmtstart;
322 int error, timo; 322 int error, timo;
323 323
324 if ((error = itimespecfix(rqt)) != 0) 324 if ((error = itimespecfix(rqt)) != 0)
325 return error; 325 return error;
326 326
327 timo = tstohz(rqt); 327 timo = tstohz(rqt);
328 /* 328 /*
329 * Avoid inadvertantly sleeping forever 329 * Avoid inadvertantly sleeping forever
330 */ 330 */
331 if (timo == 0) 331 if (timo == 0)
332 timo = 1; 332 timo = 1;
333 getnanouptime(&rmtstart); 333 getnanouptime(&rmtstart);
334again: 334again:
335 error = kpause("nanoslp", true, timo, NULL); 335 error = kpause("nanoslp", true, timo, NULL);
336 if (rmt != NULL || error == 0) { 336 if (rmt != NULL || error == 0) {
337 struct timespec rmtend; 337 struct timespec rmtend;
338 struct timespec t0; 338 struct timespec t0;
339 struct timespec *t; 339 struct timespec *t;
340 340
341 getnanouptime(&rmtend); 341 getnanouptime(&rmtend);
342 t = (rmt != NULL) ? rmt : &t0; 342 t = (rmt != NULL) ? rmt : &t0;
343 timespecsub(&rmtend, &rmtstart, t); 343 timespecsub(&rmtend, &rmtstart, t);
344 timespecsub(rqt, t, t); 344 timespecsub(rqt, t, t);
345 if (t->tv_sec < 0) 345 if (t->tv_sec < 0)
346 timespecclear(t); 346 timespecclear(t);
347 if (error == 0) { 347 if (error == 0) {
348 timo = tstohz(t); 348 timo = tstohz(t);
349 if (timo > 0) 349 if (timo > 0)
350 goto again; 350 goto again;
351 } 351 }
352 } 352 }
353 353
354 if (error == ERESTART) 354 if (error == ERESTART)
355 error = EINTR; 355 error = EINTR;
356 if (error == EWOULDBLOCK) 356 if (error == EWOULDBLOCK)
357 error = 0; 357 error = 0;
358 358
359 return error; 359 return error;
360} 360}
361 361
362/* ARGSUSED */ 362/* ARGSUSED */
363int 363int
364sys___gettimeofday50(struct lwp *l, const struct sys___gettimeofday50_args *uap, 364sys___gettimeofday50(struct lwp *l, const struct sys___gettimeofday50_args *uap,
365 register_t *retval) 365 register_t *retval)
366{ 366{
367 /* { 367 /* {
368 syscallarg(struct timeval *) tp; 368 syscallarg(struct timeval *) tp;
369 syscallarg(void *) tzp; really "struct timezone *"; 369 syscallarg(void *) tzp; really "struct timezone *";
370 } */ 370 } */
371 struct timeval atv; 371 struct timeval atv;
372 int error = 0; 372 int error = 0;
373 struct timezone tzfake; 373 struct timezone tzfake;
374 374
375 if (SCARG(uap, tp)) { 375 if (SCARG(uap, tp)) {
376 microtime(&atv); 376 microtime(&atv);
377 error = copyout(&atv, SCARG(uap, tp), sizeof(atv)); 377 error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
378 if (error) 378 if (error)
379 return (error); 379 return (error);
380 } 380 }
381 if (SCARG(uap, tzp)) { 381 if (SCARG(uap, tzp)) {
382 /* 382 /*
383 * NetBSD has no kernel notion of time zone, so we just 383 * NetBSD has no kernel notion of time zone, so we just
384 * fake up a timezone struct and return it if demanded. 384 * fake up a timezone struct and return it if demanded.
385 */ 385 */
386 tzfake.tz_minuteswest = 0; 386 tzfake.tz_minuteswest = 0;
387 tzfake.tz_dsttime = 0; 387 tzfake.tz_dsttime = 0;
388 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake)); 388 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
389 } 389 }
390 return (error); 390 return (error);
391} 391}
392 392
393/* ARGSUSED */ 393/* ARGSUSED */
394int 394int
395sys___settimeofday50(struct lwp *l, const struct sys___settimeofday50_args *uap, 395sys___settimeofday50(struct lwp *l, const struct sys___settimeofday50_args *uap,
396 register_t *retval) 396 register_t *retval)
397{ 397{
398 /* { 398 /* {
399 syscallarg(const struct timeval *) tv; 399 syscallarg(const struct timeval *) tv;
400 syscallarg(const void *) tzp; really "const struct timezone *"; 400 syscallarg(const void *) tzp; really "const struct timezone *";
401 } */ 401 } */
402 402
403 return settimeofday1(SCARG(uap, tv), true, SCARG(uap, tzp), l, true); 403 return settimeofday1(SCARG(uap, tv), true, SCARG(uap, tzp), l, true);
404} 404}
405 405
406int 406int
407settimeofday1(const struct timeval *utv, bool userspace, 407settimeofday1(const struct timeval *utv, bool userspace,
408 const void *utzp, struct lwp *l, bool check_kauth) 408 const void *utzp, struct lwp *l, bool check_kauth)
409{ 409{
410 struct timeval atv; 410 struct timeval atv;
411 struct timespec ts; 411 struct timespec ts;
412 int error; 412 int error;
413 413
414 /* Verify all parameters before changing time. */ 414 /* Verify all parameters before changing time. */
415 415
416 /* 416 /*
417 * NetBSD has no kernel notion of time zone, and only an 417 * NetBSD has no kernel notion of time zone, and only an
418 * obsolete program would try to set it, so we log a warning. 418 * obsolete program would try to set it, so we log a warning.
419 */ 419 */
420 if (utzp) 420 if (utzp)
421 log(LOG_WARNING, "pid %d attempted to set the " 421 log(LOG_WARNING, "pid %d attempted to set the "
422 "(obsolete) kernel time zone\n", l->l_proc->p_pid); 422 "(obsolete) kernel time zone\n", l->l_proc->p_pid);
423 423
424 if (utv == NULL)  424 if (utv == NULL)
425 return 0; 425 return 0;
426 426
427 if (userspace) { 427 if (userspace) {
428 if ((error = copyin(utv, &atv, sizeof(atv))) != 0) 428 if ((error = copyin(utv, &atv, sizeof(atv))) != 0)
429 return error; 429 return error;
430 utv = &atv; 430 utv = &atv;
431 } 431 }
432 432
433 TIMEVAL_TO_TIMESPEC(utv, &ts); 433 TIMEVAL_TO_TIMESPEC(utv, &ts);
434 return settime1(l->l_proc, &ts, check_kauth); 434 return settime1(l->l_proc, &ts, check_kauth);
435} 435}
436 436
437int time_adjusted; /* set if an adjustment is made */ 437int time_adjusted; /* set if an adjustment is made */
438 438
439/* ARGSUSED */ 439/* ARGSUSED */
440int 440int
441sys___adjtime50(struct lwp *l, const struct sys___adjtime50_args *uap, 441sys___adjtime50(struct lwp *l, const struct sys___adjtime50_args *uap,
442 register_t *retval) 442 register_t *retval)
443{ 443{
444 /* { 444 /* {
445 syscallarg(const struct timeval *) delta; 445 syscallarg(const struct timeval *) delta;
446 syscallarg(struct timeval *) olddelta; 446 syscallarg(struct timeval *) olddelta;
447 } */ 447 } */
448 int error = 0; 448 int error = 0;
449 struct timeval atv, oldatv; 449 struct timeval atv, oldatv;
450 450
451 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 451 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME,
452 KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) 452 KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0)
453 return error; 453 return error;
454 454
455 if (SCARG(uap, delta)) { 455 if (SCARG(uap, delta)) {
456 error = copyin(SCARG(uap, delta), &atv, 456 error = copyin(SCARG(uap, delta), &atv,
457 sizeof(*SCARG(uap, delta))); 457 sizeof(*SCARG(uap, delta)));
458 if (error) 458 if (error)
459 return (error); 459 return (error);
460 } 460 }
461 adjtime1(SCARG(uap, delta) ? &atv : NULL, 461 adjtime1(SCARG(uap, delta) ? &atv : NULL,
462 SCARG(uap, olddelta) ? &oldatv : NULL, l->l_proc); 462 SCARG(uap, olddelta) ? &oldatv : NULL, l->l_proc);
463 if (SCARG(uap, olddelta)) 463 if (SCARG(uap, olddelta))
464 error = copyout(&oldatv, SCARG(uap, olddelta), 464 error = copyout(&oldatv, SCARG(uap, olddelta),
465 sizeof(*SCARG(uap, olddelta))); 465 sizeof(*SCARG(uap, olddelta)));
466 return error; 466 return error;
467} 467}
468 468
469void 469void
470adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p) 470adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p)
471{ 471{
472 extern int64_t time_adjtime; /* in kern_ntptime.c */ 472 extern int64_t time_adjtime; /* in kern_ntptime.c */
473 473
474 if (olddelta) { 474 if (olddelta) {
475 mutex_spin_enter(&timecounter_lock); 475 mutex_spin_enter(&timecounter_lock);
476 olddelta->tv_sec = time_adjtime / 1000000; 476 olddelta->tv_sec = time_adjtime / 1000000;
477 olddelta->tv_usec = time_adjtime % 1000000; 477 olddelta->tv_usec = time_adjtime % 1000000;
478 if (olddelta->tv_usec < 0) { 478 if (olddelta->tv_usec < 0) {
479 olddelta->tv_usec += 1000000; 479 olddelta->tv_usec += 1000000;
480 olddelta->tv_sec--; 480 olddelta->tv_sec--;
481 } 481 }
482 mutex_spin_exit(&timecounter_lock); 482 mutex_spin_exit(&timecounter_lock);
483 } 483 }
484  484
485 if (delta) { 485 if (delta) {
486 mutex_spin_enter(&timecounter_lock); 486 mutex_spin_enter(&timecounter_lock);
487 time_adjtime = delta->tv_sec * 1000000 + delta->tv_usec; 487 time_adjtime = delta->tv_sec * 1000000 + delta->tv_usec;
488 488
489 if (time_adjtime) { 489 if (time_adjtime) {
490 /* We need to save the system time during shutdown */ 490 /* We need to save the system time during shutdown */
491 time_adjusted |= 1; 491 time_adjusted |= 1;
492 } 492 }
493 mutex_spin_exit(&timecounter_lock); 493 mutex_spin_exit(&timecounter_lock);
494 } 494 }
495} 495}
496 496
497/* 497/*
498 * Interval timer support. Both the BSD getitimer() family and the POSIX 498 * Interval timer support. Both the BSD getitimer() family and the POSIX
499 * timer_*() family of routines are supported. 499 * timer_*() family of routines are supported.
500 * 500 *
501 * All timers are kept in an array pointed to by p_timers, which is 501 * All timers are kept in an array pointed to by p_timers, which is
502 * allocated on demand - many processes don't use timers at all. The 502 * allocated on demand - many processes don't use timers at all. The
503 * first three elements in this array are reserved for the BSD timers: 503 * first three elements in this array are reserved for the BSD timers:
504 * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, element 504 * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, element
505 * 2 is ITIMER_PROF, and element 3 is ITIMER_MONOTONIC. The rest may be 505 * 2 is ITIMER_PROF, and element 3 is ITIMER_MONOTONIC. The rest may be
506 * allocated by the timer_create() syscall. 506 * allocated by the timer_create() syscall.
507 * 507 *
508 * Realtime timers are kept in the ptimer structure as an absolute 508 * Realtime timers are kept in the ptimer structure as an absolute
509 * time; virtual time timers are kept as a linked list of deltas. 509 * time; virtual time timers are kept as a linked list of deltas.
510 * Virtual time timers are processed in the hardclock() routine of 510 * Virtual time timers are processed in the hardclock() routine of
511 * kern_clock.c. The real time timer is processed by a callout 511 * kern_clock.c. The real time timer is processed by a callout
512 * routine, called from the softclock() routine. Since a callout may 512 * routine, called from the softclock() routine. Since a callout may
513 * be delayed in real time due to interrupt processing in the system, 513 * be delayed in real time due to interrupt processing in the system,
514 * it is possible for the real time timeout routine (realtimeexpire, 514 * it is possible for the real time timeout routine (realtimeexpire,
515 * given below), to be delayed in real time past when it is supposed 515 * given below), to be delayed in real time past when it is supposed
516 * to occur. It does not suffice, therefore, to reload the real timer 516 * to occur. It does not suffice, therefore, to reload the real timer
517 * .it_value from the real time timers .it_interval. Rather, we 517 * .it_value from the real time timers .it_interval. Rather, we
518 * compute the next time in absolute time the timer should go off. */ 518 * compute the next time in absolute time the timer should go off. */
519 519
520/* Allocate a POSIX realtime timer. */ 520/* Allocate a POSIX realtime timer. */
521int 521int
522sys_timer_create(struct lwp *l, const struct sys_timer_create_args *uap, 522sys_timer_create(struct lwp *l, const struct sys_timer_create_args *uap,
523 register_t *retval) 523 register_t *retval)
524{ 524{
525 /* { 525 /* {
526 syscallarg(clockid_t) clock_id; 526 syscallarg(clockid_t) clock_id;
527 syscallarg(struct sigevent *) evp; 527 syscallarg(struct sigevent *) evp;
528 syscallarg(timer_t *) timerid; 528 syscallarg(timer_t *) timerid;
529 } */ 529 } */
530 530
531 return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id), 531 return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id),
532 SCARG(uap, evp), copyin, l); 532 SCARG(uap, evp), copyin, l);
533} 533}
534 534
535int 535int
536timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp, 536timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp,
537 copyin_t fetch_event, struct lwp *l) 537 copyin_t fetch_event, struct lwp *l)
538{ 538{
539 int error; 539 int error;
540 timer_t timerid; 540 timer_t timerid;
541 struct ptimers *pts; 541 struct ptimers *pts;
542 struct ptimer *pt; 542 struct ptimer *pt;
543 struct proc *p; 543 struct proc *p;
544 544
545 p = l->l_proc; 545 p = l->l_proc;
546 546
547 if ((u_int)id > CLOCK_MONOTONIC) 547 if ((u_int)id > CLOCK_MONOTONIC)
548 return (EINVAL); 548 return (EINVAL);
549 549
550 if ((pts = p->p_timers) == NULL) 550 if ((pts = p->p_timers) == NULL)
551 pts = timers_alloc(p); 551 pts = timers_alloc(p);
552 552
553 pt = pool_get(&ptimer_pool, PR_WAITOK); 553 pt = pool_get(&ptimer_pool, PR_WAITOK);
554 if (evp != NULL) { 554 if (evp != NULL) {
555 if (((error = 555 if (((error =
556 (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) || 556 (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) ||
557 ((pt->pt_ev.sigev_notify < SIGEV_NONE) || 557 ((pt->pt_ev.sigev_notify < SIGEV_NONE) ||
558 (pt->pt_ev.sigev_notify > SIGEV_SA)) || 558 (pt->pt_ev.sigev_notify > SIGEV_SA)) ||
559 (pt->pt_ev.sigev_notify == SIGEV_SIGNAL && 559 (pt->pt_ev.sigev_notify == SIGEV_SIGNAL &&
560 (pt->pt_ev.sigev_signo <= 0 || 560 (pt->pt_ev.sigev_signo <= 0 ||
561 pt->pt_ev.sigev_signo >= NSIG))) { 561 pt->pt_ev.sigev_signo >= NSIG))) {
562 pool_put(&ptimer_pool, pt); 562 pool_put(&ptimer_pool, pt);
563 return (error ? error : EINVAL); 563 return (error ? error : EINVAL);
564 } 564 }
565 } 565 }
566 566
567 /* Find a free timer slot, skipping those reserved for setitimer(). */ 567 /* Find a free timer slot, skipping those reserved for setitimer(). */
568 mutex_spin_enter(&timer_lock); 568 mutex_spin_enter(&timer_lock);
569 for (timerid = 3; timerid < TIMER_MAX; timerid++) 569 for (timerid = 3; timerid < TIMER_MAX; timerid++)
570 if (pts->pts_timers[timerid] == NULL) 570 if (pts->pts_timers[timerid] == NULL)
571 break; 571 break;
572 if (timerid == TIMER_MAX) { 572 if (timerid == TIMER_MAX) {
573 mutex_spin_exit(&timer_lock); 573 mutex_spin_exit(&timer_lock);
574 pool_put(&ptimer_pool, pt); 574 pool_put(&ptimer_pool, pt);
575 return EAGAIN; 575 return EAGAIN;
576 } 576 }
577 if (evp == NULL) { 577 if (evp == NULL) {
578 pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 578 pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
579 switch (id) { 579 switch (id) {
580 case CLOCK_REALTIME: 580 case CLOCK_REALTIME:
581 case CLOCK_MONOTONIC: 581 case CLOCK_MONOTONIC:
582 pt->pt_ev.sigev_signo = SIGALRM; 582 pt->pt_ev.sigev_signo = SIGALRM;
583 break; 583 break;
584 case CLOCK_VIRTUAL: 584 case CLOCK_VIRTUAL:
585 pt->pt_ev.sigev_signo = SIGVTALRM; 585 pt->pt_ev.sigev_signo = SIGVTALRM;
586 break; 586 break;
587 case CLOCK_PROF: 587 case CLOCK_PROF:
588 pt->pt_ev.sigev_signo = SIGPROF; 588 pt->pt_ev.sigev_signo = SIGPROF;
589 break; 589 break;
590 } 590 }
591 pt->pt_ev.sigev_value.sival_int = timerid; 591 pt->pt_ev.sigev_value.sival_int = timerid;
592 } 592 }
593 pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo; 593 pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo;
594 pt->pt_info.ksi_errno = 0; 594 pt->pt_info.ksi_errno = 0;
595 pt->pt_info.ksi_code = 0; 595 pt->pt_info.ksi_code = 0;
596 pt->pt_info.ksi_pid = p->p_pid; 596 pt->pt_info.ksi_pid = p->p_pid;
597 pt->pt_info.ksi_uid = kauth_cred_getuid(l->l_cred); 597 pt->pt_info.ksi_uid = kauth_cred_getuid(l->l_cred);
598 pt->pt_info.ksi_value = pt->pt_ev.sigev_value; 598 pt->pt_info.ksi_value = pt->pt_ev.sigev_value;
599 pt->pt_type = id; 599 pt->pt_type = id;
600 pt->pt_proc = p; 600 pt->pt_proc = p;
601 pt->pt_overruns = 0; 601 pt->pt_overruns = 0;
602 pt->pt_poverruns = 0; 602 pt->pt_poverruns = 0;
603 pt->pt_entry = timerid; 603 pt->pt_entry = timerid;
604 pt->pt_queued = false; 604 pt->pt_queued = false;
605 timespecclear(&pt->pt_time.it_value); 605 timespecclear(&pt->pt_time.it_value);
606 if (!CLOCK_VIRTUAL_P(id)) 606 if (!CLOCK_VIRTUAL_P(id))
607 callout_init(&pt->pt_ch, CALLOUT_MPSAFE); 607 callout_init(&pt->pt_ch, CALLOUT_MPSAFE);
608 else 608 else
609 pt->pt_active = 0; 609 pt->pt_active = 0;
610 610
611 pts->pts_timers[timerid] = pt; 611 pts->pts_timers[timerid] = pt;
612 mutex_spin_exit(&timer_lock); 612 mutex_spin_exit(&timer_lock);
613 613
614 return copyout(&timerid, tid, sizeof(timerid)); 614 return copyout(&timerid, tid, sizeof(timerid));
615} 615}
616 616
617/* Delete a POSIX realtime timer */ 617/* Delete a POSIX realtime timer */
618int 618int
619sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap, 619sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap,
620 register_t *retval) 620 register_t *retval)
621{ 621{
622 /* { 622 /* {
623 syscallarg(timer_t) timerid; 623 syscallarg(timer_t) timerid;
624 } */ 624 } */
625 struct proc *p = l->l_proc; 625 struct proc *p = l->l_proc;
626 timer_t timerid; 626 timer_t timerid;
627 struct ptimers *pts; 627 struct ptimers *pts;
628 struct ptimer *pt, *ptn; 628 struct ptimer *pt, *ptn;
629 629
630 timerid = SCARG(uap, timerid); 630 timerid = SCARG(uap, timerid);
631 pts = p->p_timers; 631 pts = p->p_timers;
632  632
633 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 633 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
634 return (EINVAL); 634 return (EINVAL);
635 635
636 mutex_spin_enter(&timer_lock); 636 mutex_spin_enter(&timer_lock);
637 if ((pt = pts->pts_timers[timerid]) == NULL) { 637 if ((pt = pts->pts_timers[timerid]) == NULL) {
638 mutex_spin_exit(&timer_lock); 638 mutex_spin_exit(&timer_lock);
639 return (EINVAL); 639 return (EINVAL);
640 } 640 }
641 if (CLOCK_VIRTUAL_P(pt->pt_type)) { 641 if (CLOCK_VIRTUAL_P(pt->pt_type)) {
642 if (pt->pt_active) { 642 if (pt->pt_active) {
643 ptn = LIST_NEXT(pt, pt_list); 643 ptn = LIST_NEXT(pt, pt_list);
644 LIST_REMOVE(pt, pt_list); 644 LIST_REMOVE(pt, pt_list);
645 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) 645 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
646 timespecadd(&pt->pt_time.it_value, 646 timespecadd(&pt->pt_time.it_value,
647 &ptn->pt_time.it_value, 647 &ptn->pt_time.it_value,
648 &ptn->pt_time.it_value); 648 &ptn->pt_time.it_value);
649 pt->pt_active = 0; 649 pt->pt_active = 0;
650 } 650 }
651 } 651 }
652 itimerfree(pts, timerid); 652 itimerfree(pts, timerid);
653 653
654 return (0); 654 return (0);
655} 655}
656 656
657/* 657/*
658 * Set up the given timer. The value in pt->pt_time.it_value is taken 658 * Set up the given timer. The value in pt->pt_time.it_value is taken
659 * to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC timers and 659 * to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC timers and
660 * a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers. 660 * a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers.
661 */ 661 */
662void 662void
663timer_settime(struct ptimer *pt) 663timer_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)
691 ptl = &pt->pt_proc->p_timers->pts_virtual; 694 ptl = &pt->pt_proc->p_timers->pts_virtual;
692 else 695 else
693 ptl = &pt->pt_proc->p_timers->pts_prof; 696 ptl = &pt->pt_proc->p_timers->pts_prof;
694 697
695 for (ptn = LIST_FIRST(ptl), pptn = NULL; 698 for (ptn = LIST_FIRST(ptl), pptn = NULL;
696 ptn && timespeccmp(&pt->pt_time.it_value, 699 ptn && timespeccmp(&pt->pt_time.it_value,
697 &ptn->pt_time.it_value, >); 700 &ptn->pt_time.it_value, >);
698 pptn = ptn, ptn = LIST_NEXT(ptn, pt_list)) 701 pptn = ptn, ptn = LIST_NEXT(ptn, pt_list))
699 timespecsub(&pt->pt_time.it_value, 702 timespecsub(&pt->pt_time.it_value,
700 &ptn->pt_time.it_value, 703 &ptn->pt_time.it_value,
701 &pt->pt_time.it_value); 704 &pt->pt_time.it_value);
702 705
703 if (pptn) 706 if (pptn)
704 LIST_INSERT_AFTER(pptn, pt, pt_list); 707 LIST_INSERT_AFTER(pptn, pt, pt_list);
705 else 708 else
706 LIST_INSERT_HEAD(ptl, pt, pt_list); 709 LIST_INSERT_HEAD(ptl, pt, pt_list);
707 710
708 for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list)) 711 for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list))
709 timespecsub(&ptn->pt_time.it_value, 712 timespecsub(&ptn->pt_time.it_value,
710 &pt->pt_time.it_value, 713 &pt->pt_time.it_value,
711 &ptn->pt_time.it_value); 714 &ptn->pt_time.it_value);
712 715
713 pt->pt_active = 1; 716 pt->pt_active = 1;
714 } else 717 } else
715 pt->pt_active = 0; 718 pt->pt_active = 0;
716 } 719 }
717} 720}
718 721
719void 722void
720timer_gettime(struct ptimer *pt, struct itimerspec *aits) 723timer_gettime(struct ptimer *pt, struct itimerspec *aits)
721{ 724{
722 struct timespec now; 725 struct timespec now;
723 struct ptimer *ptn; 726 struct ptimer *ptn;
724 727
725 KASSERT(mutex_owned(&timer_lock)); 728 KASSERT(mutex_owned(&timer_lock));
726 729
727 *aits = pt->pt_time; 730 *aits = pt->pt_time;
728 if (!CLOCK_VIRTUAL_P(pt->pt_type)) { 731 if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
729 /* 732 /*
730 * Convert from absolute to relative time in .it_value 733 * Convert from absolute to relative time in .it_value
731 * part of real time timer. If time for real time 734 * part of real time timer. If time for real time
732 * timer has passed return 0, else return difference 735 * timer has passed return 0, else return difference
733 * between current time and time for the timer to go 736 * between current time and time for the timer to go
734 * off. 737 * off.
735 */ 738 */
736 if (timespecisset(&aits->it_value)) { 739 if (timespecisset(&aits->it_value)) {
737 if (pt->pt_type == CLOCK_REALTIME) { 740 if (pt->pt_type == CLOCK_REALTIME) {
738 getnanotime(&now); 741 getnanotime(&now);
739 } else { /* CLOCK_MONOTONIC */ 742 } else { /* CLOCK_MONOTONIC */
740 getnanouptime(&now); 743 getnanouptime(&now);
741 } 744 }
742 if (timespeccmp(&aits->it_value, &now, <)) 745 if (timespeccmp(&aits->it_value, &now, <))
743 timespecclear(&aits->it_value); 746 timespecclear(&aits->it_value);
744 else 747 else
745 timespecsub(&aits->it_value, &now, 748 timespecsub(&aits->it_value, &now,
746 &aits->it_value); 749 &aits->it_value);
747 } 750 }
748 } else if (pt->pt_active) { 751 } else if (pt->pt_active) {
749 if (pt->pt_type == CLOCK_VIRTUAL) 752 if (pt->pt_type == CLOCK_VIRTUAL)
750 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual); 753 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual);
751 else 754 else
752 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof); 755 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof);
753 for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list)) 756 for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list))
754 timespecadd(&aits->it_value, 757 timespecadd(&aits->it_value,
755 &ptn->pt_time.it_value, &aits->it_value); 758 &ptn->pt_time.it_value, &aits->it_value);
756 KASSERT(ptn != NULL); /* pt should be findable on the list */ 759 KASSERT(ptn != NULL); /* pt should be findable on the list */
757 } else 760 } else
758 timespecclear(&aits->it_value); 761 timespecclear(&aits->it_value);
759} 762}
760 763
761 764
762 765
763/* Set and arm a POSIX realtime timer */ 766/* Set and arm a POSIX realtime timer */
764int 767int
765sys___timer_settime50(struct lwp *l, 768sys___timer_settime50(struct lwp *l,
766 const struct sys___timer_settime50_args *uap, 769 const struct sys___timer_settime50_args *uap,
767 register_t *retval) 770 register_t *retval)
768{ 771{
769 /* { 772 /* {
770 syscallarg(timer_t) timerid; 773 syscallarg(timer_t) timerid;
771 syscallarg(int) flags; 774 syscallarg(int) flags;
772 syscallarg(const struct itimerspec *) value; 775 syscallarg(const struct itimerspec *) value;
773 syscallarg(struct itimerspec *) ovalue; 776 syscallarg(struct itimerspec *) ovalue;
774 } */ 777 } */
775 int error; 778 int error;
776 struct itimerspec value, ovalue, *ovp = NULL; 779 struct itimerspec value, ovalue, *ovp = NULL;
777 780
778 if ((error = copyin(SCARG(uap, value), &value, 781 if ((error = copyin(SCARG(uap, value), &value,
779 sizeof(struct itimerspec))) != 0) 782 sizeof(struct itimerspec))) != 0)
780 return (error); 783 return (error);
781 784
782 if (SCARG(uap, ovalue)) 785 if (SCARG(uap, ovalue))
783 ovp = &ovalue; 786 ovp = &ovalue;
784 787
785 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 788 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
786 SCARG(uap, flags), l->l_proc)) != 0) 789 SCARG(uap, flags), l->l_proc)) != 0)
787 return error; 790 return error;
788 791
789 if (ovp) 792 if (ovp)
790 return copyout(&ovalue, SCARG(uap, ovalue), 793 return copyout(&ovalue, SCARG(uap, ovalue),
791 sizeof(struct itimerspec)); 794 sizeof(struct itimerspec));
792 return 0; 795 return 0;
793} 796}
794 797
795int 798int
796dotimer_settime(int timerid, struct itimerspec *value, 799dotimer_settime(int timerid, struct itimerspec *value,
797 struct itimerspec *ovalue, int flags, struct proc *p) 800 struct itimerspec *ovalue, int flags, struct proc *p)
798{ 801{
799 struct timespec now; 802 struct timespec now;
800 struct itimerspec val, oval; 803 struct itimerspec val, oval;
801 struct ptimers *pts; 804 struct ptimers *pts;
802 struct ptimer *pt; 805 struct ptimer *pt;
803 int error; 806 int error;
804 807
805 pts = p->p_timers; 808 pts = p->p_timers;
806 809
807 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 810 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
808 return EINVAL; 811 return EINVAL;
809 val = *value; 812 val = *value;
810 if ((error = itimespecfix(&val.it_value)) != 0 || 813 if ((error = itimespecfix(&val.it_value)) != 0 ||
811 (error = itimespecfix(&val.it_interval)) != 0) 814 (error = itimespecfix(&val.it_interval)) != 0)
812 return error; 815 return error;
813 816
814 mutex_spin_enter(&timer_lock); 817 mutex_spin_enter(&timer_lock);
815 if ((pt = pts->pts_timers[timerid]) == NULL) { 818 if ((pt = pts->pts_timers[timerid]) == NULL) {
816 mutex_spin_exit(&timer_lock); 819 mutex_spin_exit(&timer_lock);
817 return EINVAL; 820 return EINVAL;
818 } 821 }
819 822
820 oval = pt->pt_time; 823 oval = pt->pt_time;
821 pt->pt_time = val; 824 pt->pt_time = val;
822 825
823 /* 826 /*
824 * If we've been passed a relative time for a realtime timer, 827 * If we've been passed a relative time for a realtime timer,
825 * convert it to absolute; if an absolute time for a virtual 828 * convert it to absolute; if an absolute time for a virtual
826 * timer, convert it to relative and make sure we don't set it 829 * timer, convert it to relative and make sure we don't set it
827 * to zero, which would cancel the timer, or let it go 830 * to zero, which would cancel the timer, or let it go
828 * negative, which would confuse the comparison tests. 831 * negative, which would confuse the comparison tests.
829 */ 832 */
830 if (timespecisset(&pt->pt_time.it_value)) { 833 if (timespecisset(&pt->pt_time.it_value)) {
831 if (!CLOCK_VIRTUAL_P(pt->pt_type)) { 834 if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
832 if ((flags & TIMER_ABSTIME) == 0) { 835 if ((flags & TIMER_ABSTIME) == 0) {
833 if (pt->pt_type == CLOCK_REALTIME) { 836 if (pt->pt_type == CLOCK_REALTIME) {
834 getnanotime(&now); 837 getnanotime(&now);
835 } else { /* CLOCK_MONOTONIC */ 838 } else { /* CLOCK_MONOTONIC */
836 getnanouptime(&now); 839 getnanouptime(&now);
837 } 840 }
838 timespecadd(&pt->pt_time.it_value, &now, 841 timespecadd(&pt->pt_time.it_value, &now,
839 &pt->pt_time.it_value); 842 &pt->pt_time.it_value);
840 } 843 }
841 } else { 844 } else {
842 if ((flags & TIMER_ABSTIME) != 0) { 845 if ((flags & TIMER_ABSTIME) != 0) {
843 getnanotime(&now); 846 getnanotime(&now);
844 timespecsub(&pt->pt_time.it_value, &now, 847 timespecsub(&pt->pt_time.it_value, &now,
845 &pt->pt_time.it_value); 848 &pt->pt_time.it_value);
846 if (!timespecisset(&pt->pt_time.it_value) || 849 if (!timespecisset(&pt->pt_time.it_value) ||
847 pt->pt_time.it_value.tv_sec < 0) { 850 pt->pt_time.it_value.tv_sec < 0) {
848 pt->pt_time.it_value.tv_sec = 0; 851 pt->pt_time.it_value.tv_sec = 0;
849 pt->pt_time.it_value.tv_nsec = 1; 852 pt->pt_time.it_value.tv_nsec = 1;
850 } 853 }
851 } 854 }
852 } 855 }
853 } 856 }
854 857
855 timer_settime(pt); 858 timer_settime(pt);
856 mutex_spin_exit(&timer_lock); 859 mutex_spin_exit(&timer_lock);
857 860
858 if (ovalue) 861 if (ovalue)
859 *ovalue = oval; 862 *ovalue = oval;
860 863
861 return (0); 864 return (0);
862} 865}
863 866
864/* Return the time remaining until a POSIX timer fires. */ 867/* Return the time remaining until a POSIX timer fires. */
865int 868int
866sys___timer_gettime50(struct lwp *l, 869sys___timer_gettime50(struct lwp *l,
867 const struct sys___timer_gettime50_args *uap, register_t *retval) 870 const struct sys___timer_gettime50_args *uap, register_t *retval)
868{ 871{
869 /* { 872 /* {
870 syscallarg(timer_t) timerid; 873 syscallarg(timer_t) timerid;
871 syscallarg(struct itimerspec *) value; 874 syscallarg(struct itimerspec *) value;
872 } */ 875 } */
873 struct itimerspec its; 876 struct itimerspec its;
874 int error; 877 int error;
875 878
876 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 879 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
877 &its)) != 0) 880 &its)) != 0)
878 return error; 881 return error;
879 882
880 return copyout(&its, SCARG(uap, value), sizeof(its)); 883 return copyout(&its, SCARG(uap, value), sizeof(its));
881} 884}
882 885
883int 886int
884dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its) 887dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its)
885{ 888{
886 struct ptimer *pt; 889 struct ptimer *pt;
887 struct ptimers *pts; 890 struct ptimers *pts;
888 891
889 pts = p->p_timers; 892 pts = p->p_timers;
890 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 893 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
891 return (EINVAL); 894 return (EINVAL);
892 mutex_spin_enter(&timer_lock); 895 mutex_spin_enter(&timer_lock);
893 if ((pt = pts->pts_timers[timerid]) == NULL) { 896 if ((pt = pts->pts_timers[timerid]) == NULL) {
894 mutex_spin_exit(&timer_lock); 897 mutex_spin_exit(&timer_lock);
895 return (EINVAL); 898 return (EINVAL);
896 } 899 }
897 timer_gettime(pt, its); 900 timer_gettime(pt, its);
898 mutex_spin_exit(&timer_lock); 901 mutex_spin_exit(&timer_lock);
899 902
900 return 0; 903 return 0;
901} 904}
902 905
903/* 906/*
904 * Return the count of the number of times a periodic timer expired 907 * Return the count of the number of times a periodic timer expired
905 * while a notification was already pending. The counter is reset when 908 * while a notification was already pending. The counter is reset when
906 * a timer expires and a notification can be posted. 909 * a timer expires and a notification can be posted.
907 */ 910 */
908int 911int
909sys_timer_getoverrun(struct lwp *l, const struct sys_timer_getoverrun_args *uap, 912sys_timer_getoverrun(struct lwp *l, const struct sys_timer_getoverrun_args *uap,
910 register_t *retval) 913 register_t *retval)
911{ 914{
912 /* { 915 /* {
913 syscallarg(timer_t) timerid; 916 syscallarg(timer_t) timerid;
914 } */ 917 } */
915 struct proc *p = l->l_proc; 918 struct proc *p = l->l_proc;
916 struct ptimers *pts; 919 struct ptimers *pts;
917 int timerid; 920 int timerid;
918 struct ptimer *pt; 921 struct ptimer *pt;
919 922
920 timerid = SCARG(uap, timerid); 923 timerid = SCARG(uap, timerid);
921 924
922 pts = p->p_timers; 925 pts = p->p_timers;
923 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 926 if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
924 return (EINVAL); 927 return (EINVAL);
925 mutex_spin_enter(&timer_lock); 928 mutex_spin_enter(&timer_lock);
926 if ((pt = pts->pts_timers[timerid]) == NULL) { 929 if ((pt = pts->pts_timers[timerid]) == NULL) {
927 mutex_spin_exit(&timer_lock); 930 mutex_spin_exit(&timer_lock);
928 return (EINVAL); 931 return (EINVAL);
929 } 932 }
930 *retval = pt->pt_poverruns; 933 *retval = pt->pt_poverruns;
931 mutex_spin_exit(&timer_lock); 934 mutex_spin_exit(&timer_lock);
932 935
933 return (0); 936 return (0);
934} 937}
935 938
936#ifdef KERN_SA 939#ifdef KERN_SA
937/* Glue function that triggers an upcall; called from userret(). */ 940/* Glue function that triggers an upcall; called from userret(). */
938void 941void
939timerupcall(struct lwp *l) 942timerupcall(struct lwp *l)
940{ 943{
941 struct ptimers *pt = l->l_proc->p_timers; 944 struct ptimers *pt = l->l_proc->p_timers;
942 struct proc *p = l->l_proc; 945 struct proc *p = l->l_proc;
943 unsigned int i, fired, done; 946 unsigned int i, fired, done;
944 947
945 KDASSERT(l->l_proc->p_sa); 948 KDASSERT(l->l_proc->p_sa);
946 /* Bail out if we do not own the virtual processor */ 949 /* Bail out if we do not own the virtual processor */
947 if (l->l_savp->savp_lwp != l) 950 if (l->l_savp->savp_lwp != l)
948 return ; 951 return ;
949 952
950 mutex_enter(p->p_lock); 953 mutex_enter(p->p_lock);
951 954
952 fired = pt->pts_fired; 955 fired = pt->pts_fired;
953 done = 0; 956 done = 0;
954 while ((i = ffs(fired)) != 0) { 957 while ((i = ffs(fired)) != 0) {
955 siginfo_t *si; 958 siginfo_t *si;
956 int mask = 1 << --i; 959 int mask = 1 << --i;
957 int f; 960 int f;
958 961
959 f = ~l->l_pflag & LP_SA_NOBLOCK; 962 f = ~l->l_pflag & LP_SA_NOBLOCK;
960 l->l_pflag |= LP_SA_NOBLOCK; 963 l->l_pflag |= LP_SA_NOBLOCK;
961 si = siginfo_alloc(PR_WAITOK); 964 si = siginfo_alloc(PR_WAITOK);
962 si->_info = pt->pts_timers[i]->pt_info.ksi_info; 965 si->_info = pt->pts_timers[i]->pt_info.ksi_info;
963 if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l, 966 if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l,
964 sizeof(*si), si, siginfo_free) != 0) { 967 sizeof(*si), si, siginfo_free) != 0) {
965 siginfo_free(si); 968 siginfo_free(si);
966 /* XXX What do we do here?? */ 969 /* XXX What do we do here?? */
967 } else 970 } else
968 done |= mask; 971 done |= mask;
969 fired &= ~mask; 972 fired &= ~mask;
970 l->l_pflag ^= f; 973 l->l_pflag ^= f;
971 } 974 }
972 pt->pts_fired &= ~done; 975 pt->pts_fired &= ~done;
973 if (pt->pts_fired == 0) 976 if (pt->pts_fired == 0)
974 l->l_proc->p_timerpend = 0; 977 l->l_proc->p_timerpend = 0;
975 978
976 mutex_exit(p->p_lock); 979 mutex_exit(p->p_lock);
977} 980}
978#endif /* KERN_SA */ 981#endif /* KERN_SA */
979 982
980/* 983/*
981 * Real interval timer expired: 984 * Real interval timer expired:
982 * send process whose timer expired an alarm signal. 985 * send process whose timer expired an alarm signal.
983 * If time is not set up to reload, then just return. 986 * If time is not set up to reload, then just return.
984 * Else compute next time timer should go off which is > current time. 987 * Else compute next time timer should go off which is > current time.
985 * This is where delay in processing this timeout causes multiple 988 * This is where delay in processing this timeout causes multiple
986 * SIGALRM calls to be compressed into one. 989 * SIGALRM calls to be compressed into one.
987 */ 990 */
988void 991void
989realtimerexpire(void *arg) 992realtimerexpire(void *arg)
990{ 993{
991 uint64_t last_val, next_val, interval, now_ns; 994 uint64_t last_val, next_val, interval, now_ns;
992 struct timespec now, next; 995 struct timespec now, next;
993 struct ptimer *pt; 996 struct ptimer *pt;
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;
1048 } */ 1056 } */
1049 struct proc *p = l->l_proc; 1057 struct proc *p = l->l_proc;
1050 struct itimerval aitv; 1058 struct itimerval aitv;
1051 int error; 1059 int error;
1052 1060
1053 error = dogetitimer(p, SCARG(uap, which), &aitv); 1061 error = dogetitimer(p, SCARG(uap, which), &aitv);
1054 if (error) 1062 if (error)
1055 return error; 1063 return error;
1056 return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval))); 1064 return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
1057} 1065}
1058 1066
1059int 1067int
1060dogetitimer(struct proc *p, int which, struct itimerval *itvp) 1068dogetitimer(struct proc *p, int which, struct itimerval *itvp)
1061{ 1069{
1062 struct ptimers *pts; 1070 struct ptimers *pts;
1063 struct ptimer *pt; 1071 struct ptimer *pt;
1064 struct itimerspec its; 1072 struct itimerspec its;
1065 1073
1066 if ((u_int)which > ITIMER_MONOTONIC) 1074 if ((u_int)which > ITIMER_MONOTONIC)
1067 return (EINVAL); 1075 return (EINVAL);
1068 1076
1069 mutex_spin_enter(&timer_lock); 1077 mutex_spin_enter(&timer_lock);
1070 pts = p->p_timers; 1078 pts = p->p_timers;
1071 if (pts == NULL || (pt = pts->pts_timers[which]) == NULL) { 1079 if (pts == NULL || (pt = pts->pts_timers[which]) == NULL) {
1072 timerclear(&itvp->it_value); 1080 timerclear(&itvp->it_value);
1073 timerclear(&itvp->it_interval); 1081 timerclear(&itvp->it_interval);
1074 } else { 1082 } else {
1075 timer_gettime(pt, &its); 1083 timer_gettime(pt, &its);
1076 TIMESPEC_TO_TIMEVAL(&itvp->it_value, &its.it_value); 1084 TIMESPEC_TO_TIMEVAL(&itvp->it_value, &its.it_value);
1077 TIMESPEC_TO_TIMEVAL(&itvp->it_interval, &its.it_interval); 1085 TIMESPEC_TO_TIMEVAL(&itvp->it_interval, &its.it_interval);
1078 } 1086 }
1079 mutex_spin_exit(&timer_lock);  1087 mutex_spin_exit(&timer_lock);
1080 1088
1081 return 0; 1089 return 0;
1082} 1090}
1083 1091
1084/* BSD routine to set/arm an interval timer. */ 1092/* BSD routine to set/arm an interval timer. */
1085/* ARGSUSED */ 1093/* ARGSUSED */
1086int 1094int
1087sys___setitimer50(struct lwp *l, const struct sys___setitimer50_args *uap, 1095sys___setitimer50(struct lwp *l, const struct sys___setitimer50_args *uap,
1088 register_t *retval) 1096 register_t *retval)
1089{ 1097{
1090 /* { 1098 /* {
1091 syscallarg(int) which; 1099 syscallarg(int) which;
1092 syscallarg(const struct itimerval *) itv; 1100 syscallarg(const struct itimerval *) itv;
1093 syscallarg(struct itimerval *) oitv; 1101 syscallarg(struct itimerval *) oitv;
1094 } */ 1102 } */
1095 struct proc *p = l->l_proc; 1103 struct proc *p = l->l_proc;
1096 int which = SCARG(uap, which); 1104 int which = SCARG(uap, which);
1097 struct sys___getitimer50_args getargs; 1105 struct sys___getitimer50_args getargs;
1098 const struct itimerval *itvp; 1106 const struct itimerval *itvp;
1099 struct itimerval aitv; 1107 struct itimerval aitv;
1100 int error; 1108 int error;
1101 1109
1102 if ((u_int)which > ITIMER_MONOTONIC) 1110 if ((u_int)which > ITIMER_MONOTONIC)
1103 return (EINVAL); 1111 return (EINVAL);
1104 itvp = SCARG(uap, itv); 1112 itvp = SCARG(uap, itv);
1105 if (itvp && 1113 if (itvp &&
1106 (error = copyin(itvp, &aitv, sizeof(struct itimerval)) != 0)) 1114 (error = copyin(itvp, &aitv, sizeof(struct itimerval)) != 0))
1107 return (error); 1115 return (error);
1108 if (SCARG(uap, oitv) != NULL) { 1116 if (SCARG(uap, oitv) != NULL) {
1109 SCARG(&getargs, which) = which; 1117 SCARG(&getargs, which) = which;
1110 SCARG(&getargs, itv) = SCARG(uap, oitv); 1118 SCARG(&getargs, itv) = SCARG(uap, oitv);
1111 if ((error = sys___getitimer50(l, &getargs, retval)) != 0) 1119 if ((error = sys___getitimer50(l, &getargs, retval)) != 0)
1112 return (error); 1120 return (error);
1113 } 1121 }
1114 if (itvp == 0) 1122 if (itvp == 0)
1115 return (0); 1123 return (0);
1116 1124
1117 return dosetitimer(p, which, &aitv); 1125 return dosetitimer(p, which, &aitv);
1118} 1126}
1119 1127
1120int 1128int
1121dosetitimer(struct proc *p, int which, struct itimerval *itvp) 1129dosetitimer(struct proc *p, int which, struct itimerval *itvp)
1122{ 1130{
1123 struct timespec now; 1131 struct timespec now;
1124 struct ptimers *pts; 1132 struct ptimers *pts;
1125 struct ptimer *pt, *spare; 1133 struct ptimer *pt, *spare;
1126 1134
1127 KASSERT((u_int)which <= CLOCK_MONOTONIC); 1135 KASSERT((u_int)which <= CLOCK_MONOTONIC);
1128 if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval)) 1136 if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
1129 return (EINVAL); 1137 return (EINVAL);
1130 1138
1131 /* 1139 /*
1132 * Don't bother allocating data structures if the process just 1140 * Don't bother allocating data structures if the process just
1133 * wants to clear the timer. 1141 * wants to clear the timer.
1134 */ 1142 */
1135 spare = NULL; 1143 spare = NULL;
1136 pts = p->p_timers; 1144 pts = p->p_timers;
1137 retry: 1145 retry:
1138 if (!timerisset(&itvp->it_value) && (pts == NULL || 1146 if (!timerisset(&itvp->it_value) && (pts == NULL ||
1139 pts->pts_timers[which] == NULL)) 1147 pts->pts_timers[which] == NULL))
1140 return (0); 1148 return (0);
1141 if (pts == NULL) 1149 if (pts == NULL)
1142 pts = timers_alloc(p); 1150 pts = timers_alloc(p);
1143 mutex_spin_enter(&timer_lock); 1151 mutex_spin_enter(&timer_lock);
1144 pt = pts->pts_timers[which]; 1152 pt = pts->pts_timers[which];
1145 if (pt == NULL) { 1153 if (pt == NULL) {
1146 if (spare == NULL) { 1154 if (spare == NULL) {
1147 mutex_spin_exit(&timer_lock); 1155 mutex_spin_exit(&timer_lock);
1148 spare = pool_get(&ptimer_pool, PR_WAITOK); 1156 spare = pool_get(&ptimer_pool, PR_WAITOK);
1149 goto retry; 1157 goto retry;
1150 } 1158 }
1151 pt = spare; 1159 pt = spare;
1152 spare = NULL; 1160 spare = NULL;
1153 pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 1161 pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
1154 pt->pt_ev.sigev_value.sival_int = which; 1162 pt->pt_ev.sigev_value.sival_int = which;
1155 pt->pt_overruns = 0; 1163 pt->pt_overruns = 0;
1156 pt->pt_proc = p; 1164 pt->pt_proc = p;
1157 pt->pt_type = which; 1165 pt->pt_type = which;
1158 pt->pt_entry = which; 1166 pt->pt_entry = which;
1159 pt->pt_queued = false; 1167 pt->pt_queued = false;
1160 if (pt->pt_type == CLOCK_REALTIME) 1168 if (pt->pt_type == CLOCK_REALTIME)
1161 callout_init(&pt->pt_ch, CALLOUT_MPSAFE); 1169 callout_init(&pt->pt_ch, CALLOUT_MPSAFE);
1162 else 1170 else
1163 pt->pt_active = 0; 1171 pt->pt_active = 0;
1164 1172
1165 switch (which) { 1173 switch (which) {
1166 case ITIMER_REAL: 1174 case ITIMER_REAL:
1167 case ITIMER_MONOTONIC: 1175 case ITIMER_MONOTONIC:
1168 pt->pt_ev.sigev_signo = SIGALRM; 1176 pt->pt_ev.sigev_signo = SIGALRM;
1169 break; 1177 break;
1170 case ITIMER_VIRTUAL: 1178 case ITIMER_VIRTUAL:
1171 pt->pt_ev.sigev_signo = SIGVTALRM; 1179 pt->pt_ev.sigev_signo = SIGVTALRM;
1172 break; 1180 break;
1173 case ITIMER_PROF: 1181 case ITIMER_PROF:
1174 pt->pt_ev.sigev_signo = SIGPROF; 1182 pt->pt_ev.sigev_signo = SIGPROF;
1175 break; 1183 break;
1176 } 1184 }
1177 pts->pts_timers[which] = pt; 1185 pts->pts_timers[which] = pt;
1178 } 1186 }
1179 1187
1180 TIMEVAL_TO_TIMESPEC(&itvp->it_value, &pt->pt_time.it_value); 1188 TIMEVAL_TO_TIMESPEC(&itvp->it_value, &pt->pt_time.it_value);
1181 TIMEVAL_TO_TIMESPEC(&itvp->it_interval, &pt->pt_time.it_interval); 1189 TIMEVAL_TO_TIMESPEC(&itvp->it_interval, &pt->pt_time.it_interval);
1182 1190
1183 if (timespecisset(&pt->pt_time.it_value)) { 1191 if (timespecisset(&pt->pt_time.it_value)) {
1184 /* Convert to absolute time */ 1192 /* Convert to absolute time */
1185 /* XXX need to wrap in splclock for timecounters case? */ 1193 /* XXX need to wrap in splclock for timecounters case? */
1186 switch (which) { 1194 switch (which) {
1187 case ITIMER_REAL: 1195 case ITIMER_REAL:
1188 getnanotime(&now); 1196 getnanotime(&now);
1189 timespecadd(&pt->pt_time.it_value, &now, 1197 timespecadd(&pt->pt_time.it_value, &now,
1190 &pt->pt_time.it_value); 1198 &pt->pt_time.it_value);
1191 break; 1199 break;
1192 case ITIMER_MONOTONIC: 1200 case ITIMER_MONOTONIC:
1193 getnanouptime(&now); 1201 getnanouptime(&now);
1194 timespecadd(&pt->pt_time.it_value, &now, 1202 timespecadd(&pt->pt_time.it_value, &now,
1195 &pt->pt_time.it_value); 1203 &pt->pt_time.it_value);
1196 break; 1204 break;
1197 default: 1205 default:
1198 break; 1206 break;
1199 } 1207 }
1200 } 1208 }
1201 timer_settime(pt); 1209 timer_settime(pt);
1202 mutex_spin_exit(&timer_lock); 1210 mutex_spin_exit(&timer_lock);
1203 if (spare != NULL) 1211 if (spare != NULL)
1204 pool_put(&ptimer_pool, spare); 1212 pool_put(&ptimer_pool, spare);
1205 1213
1206 return (0); 1214 return (0);
1207} 1215}
1208 1216
1209/* Utility routines to manage the array of pointers to timers. */ 1217/* Utility routines to manage the array of pointers to timers. */
1210struct ptimers * 1218struct ptimers *
1211timers_alloc(struct proc *p) 1219timers_alloc(struct proc *p)
1212{ 1220{
1213 struct ptimers *pts; 1221 struct ptimers *pts;
1214 int i; 1222 int i;
1215 1223
1216 pts = pool_get(&ptimers_pool, PR_WAITOK); 1224 pts = pool_get(&ptimers_pool, PR_WAITOK);
1217 LIST_INIT(&pts->pts_virtual); 1225 LIST_INIT(&pts->pts_virtual);
1218 LIST_INIT(&pts->pts_prof); 1226 LIST_INIT(&pts->pts_prof);
1219 for (i = 0; i < TIMER_MAX; i++) 1227 for (i = 0; i < TIMER_MAX; i++)
1220 pts->pts_timers[i] = NULL; 1228 pts->pts_timers[i] = NULL;
1221 pts->pts_fired = 0; 1229 pts->pts_fired = 0;
1222 mutex_spin_enter(&timer_lock); 1230 mutex_spin_enter(&timer_lock);
1223 if (p->p_timers == NULL) { 1231 if (p->p_timers == NULL) {
1224 p->p_timers = pts; 1232 p->p_timers = pts;
1225 mutex_spin_exit(&timer_lock); 1233 mutex_spin_exit(&timer_lock);
1226 return pts; 1234 return pts;
1227 } 1235 }
1228 mutex_spin_exit(&timer_lock); 1236 mutex_spin_exit(&timer_lock);
1229 pool_put(&ptimers_pool, pts); 1237 pool_put(&ptimers_pool, pts);
1230 return p->p_timers; 1238 return p->p_timers;
1231} 1239}
1232 1240
1233/* 1241/*
1234 * Clean up the per-process timers. If "which" is set to TIMERS_ALL, 1242 * Clean up the per-process timers. If "which" is set to TIMERS_ALL,
1235 * then clean up all timers and free all the data structures. If 1243 * then clean up all timers and free all the data structures. If
1236 * "which" is set to TIMERS_POSIX, only clean up the timers allocated 1244 * "which" is set to TIMERS_POSIX, only clean up the timers allocated
1237 * by timer_create(), not the BSD setitimer() timers, and only free the 1245 * by timer_create(), not the BSD setitimer() timers, and only free the
1238 * structure if none of those remain. 1246 * structure if none of those remain.
1239 */ 1247 */
1240void 1248void
1241timers_free(struct proc *p, int which) 1249timers_free(struct proc *p, int which)
1242{ 1250{
1243 struct ptimers *pts; 1251 struct ptimers *pts;
1244 struct ptimer *ptn; 1252 struct ptimer *ptn;
1245 struct timespec ts; 1253 struct timespec ts;
1246 int i; 1254 int i;
1247 1255
1248 if (p->p_timers == NULL) 1256 if (p->p_timers == NULL)
1249 return; 1257 return;
1250 1258
1251 pts = p->p_timers; 1259 pts = p->p_timers;
1252 mutex_spin_enter(&timer_lock); 1260 mutex_spin_enter(&timer_lock);
1253 if (which == TIMERS_ALL) { 1261 if (which == TIMERS_ALL) {
1254 p->p_timers = NULL; 1262 p->p_timers = NULL;
1255 i = 0; 1263 i = 0;
1256 } else { 1264 } else {
1257 timespecclear(&ts); 1265 timespecclear(&ts);
1258 for (ptn = LIST_FIRST(&pts->pts_virtual); 1266 for (ptn = LIST_FIRST(&pts->pts_virtual);
1259 ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL]; 1267 ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL];
1260 ptn = LIST_NEXT(ptn, pt_list)) { 1268 ptn = LIST_NEXT(ptn, pt_list)) {
1261 KASSERT(ptn->pt_type == CLOCK_VIRTUAL); 1269 KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
1262 timespecadd(&ts, &ptn->pt_time.it_value, &ts); 1270 timespecadd(&ts, &ptn->pt_time.it_value, &ts);
1263 } 1271 }
1264 LIST_FIRST(&pts->pts_virtual) = NULL; 1272 LIST_FIRST(&pts->pts_virtual) = NULL;
1265 if (ptn) { 1273 if (ptn) {
1266 KASSERT(ptn->pt_type == CLOCK_VIRTUAL); 1274 KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
1267 timespecadd(&ts, &ptn->pt_time.it_value, 1275 timespecadd(&ts, &ptn->pt_time.it_value,
1268 &ptn->pt_time.it_value); 1276 &ptn->pt_time.it_value);
1269 LIST_INSERT_HEAD(&pts->pts_virtual, ptn, pt_list); 1277 LIST_INSERT_HEAD(&pts->pts_virtual, ptn, pt_list);
1270 } 1278 }
1271 timespecclear(&ts); 1279 timespecclear(&ts);
1272 for (ptn = LIST_FIRST(&pts->pts_prof); 1280 for (ptn = LIST_FIRST(&pts->pts_prof);
1273 ptn && ptn != pts->pts_timers[ITIMER_PROF]; 1281 ptn && ptn != pts->pts_timers[ITIMER_PROF];
1274 ptn = LIST_NEXT(ptn, pt_list)) { 1282 ptn = LIST_NEXT(ptn, pt_list)) {
1275 KASSERT(ptn->pt_type == CLOCK_PROF); 1283 KASSERT(ptn->pt_type == CLOCK_PROF);
1276 timespecadd(&ts, &ptn->pt_time.it_value, &ts); 1284 timespecadd(&ts, &ptn->pt_time.it_value, &ts);
1277 } 1285 }
1278 LIST_FIRST(&pts->pts_prof) = NULL; 1286 LIST_FIRST(&pts->pts_prof) = NULL;
1279 if (ptn) { 1287 if (ptn) {
1280 KASSERT(ptn->pt_type == CLOCK_PROF); 1288 KASSERT(ptn->pt_type == CLOCK_PROF);
1281 timespecadd(&ts, &ptn->pt_time.it_value, 1289 timespecadd(&ts, &ptn->pt_time.it_value,
1282 &ptn->pt_time.it_value); 1290 &ptn->pt_time.it_value);
1283 LIST_INSERT_HEAD(&pts->pts_prof, ptn, pt_list); 1291 LIST_INSERT_HEAD(&pts->pts_prof, ptn, pt_list);
1284 } 1292 }
1285 i = 3; 1293 i = 3;
1286 } 1294 }
1287 for ( ; i < TIMER_MAX; i++) { 1295 for ( ; i < TIMER_MAX; i++) {
1288 if (pts->pts_timers[i] != NULL) { 1296 if (pts->pts_timers[i] != NULL) {
1289 itimerfree(pts, i); 1297 itimerfree(pts, i);
1290 mutex_spin_enter(&timer_lock); 1298 mutex_spin_enter(&timer_lock);
1291 } 1299 }
1292 } 1300 }
1293 if (pts->pts_timers[0] == NULL && pts->pts_timers[1] == NULL && 1301 if (pts->pts_timers[0] == NULL && pts->pts_timers[1] == NULL &&
1294 pts->pts_timers[2] == NULL) { 1302 pts->pts_timers[2] == NULL) {
1295 p->p_timers = NULL; 1303 p->p_timers = NULL;
1296 mutex_spin_exit(&timer_lock); 1304 mutex_spin_exit(&timer_lock);
1297 pool_put(&ptimers_pool, pts); 1305 pool_put(&ptimers_pool, pts);
1298 } else 1306 } else
1299 mutex_spin_exit(&timer_lock); 1307 mutex_spin_exit(&timer_lock);
1300} 1308}
1301 1309
1302static void 1310static void
1303itimerfree(struct ptimers *pts, int index) 1311itimerfree(struct ptimers *pts, int index)
1304{ 1312{
1305 struct ptimer *pt; 1313 struct ptimer *pt;
1306 1314
1307 KASSERT(mutex_owned(&timer_lock)); 1315 KASSERT(mutex_owned(&timer_lock));
1308 1316
1309 pt = pts->pts_timers[index]; 1317 pt = pts->pts_timers[index];
1310 pts->pts_timers[index] = NULL; 1318 pts->pts_timers[index] = NULL;
1311 if (!CLOCK_VIRTUAL_P(pt->pt_type)) 1319 if (!CLOCK_VIRTUAL_P(pt->pt_type))
1312 callout_halt(&pt->pt_ch, &timer_lock); 1320 callout_halt(&pt->pt_ch, &timer_lock);
1313 if (pt->pt_queued) 1321 if (pt->pt_queued)
1314 TAILQ_REMOVE(&timer_queue, pt, pt_chain); 1322 TAILQ_REMOVE(&timer_queue, pt, pt_chain);
1315 mutex_spin_exit(&timer_lock); 1323 mutex_spin_exit(&timer_lock);
1316 if (!CLOCK_VIRTUAL_P(pt->pt_type)) 1324 if (!CLOCK_VIRTUAL_P(pt->pt_type))
1317 callout_destroy(&pt->pt_ch); 1325 callout_destroy(&pt->pt_ch);
1318 pool_put(&ptimer_pool, pt); 1326 pool_put(&ptimer_pool, pt);
1319} 1327}
1320 1328
1321/* 1329/*
1322 * Decrement an interval timer by a specified number 1330 * Decrement an interval timer by a specified number
1323 * of nanoseconds, which must be less than a second, 1331 * of nanoseconds, which must be less than a second,
1324 * i.e. < 1000000000. If the timer expires, then reload 1332 * i.e. < 1000000000. If the timer expires, then reload
1325 * it. In this case, carry over (nsec - old value) to 1333 * it. In this case, carry over (nsec - old value) to
1326 * reduce the value reloaded into the timer so that 1334 * reduce the value reloaded into the timer so that
1327 * the timer does not drift. This routine assumes 1335 * the timer does not drift. This routine assumes
1328 * that it is called in a context where the timers 1336 * that it is called in a context where the timers
1329 * on which it is operating cannot change in value. 1337 * on which it is operating cannot change in value.
1330 */ 1338 */
1331static int 1339static int
1332itimerdecr(struct ptimer *pt, int nsec) 1340itimerdecr(struct ptimer *pt, int nsec)
1333{ 1341{
1334 struct itimerspec *itp; 1342 struct itimerspec *itp;
1335 1343
1336 KASSERT(mutex_owned(&timer_lock)); 1344 KASSERT(mutex_owned(&timer_lock));
1337 KASSERT(CLOCK_VIRTUAL_P(pt->pt_type)); 1345 KASSERT(CLOCK_VIRTUAL_P(pt->pt_type));
1338 1346
1339 itp = &pt->pt_time; 1347 itp = &pt->pt_time;
1340 if (itp->it_value.tv_nsec < nsec) { 1348 if (itp->it_value.tv_nsec < nsec) {
1341 if (itp->it_value.tv_sec == 0) { 1349 if (itp->it_value.tv_sec == 0) {
1342 /* expired, and already in next interval */ 1350 /* expired, and already in next interval */
1343 nsec -= itp->it_value.tv_nsec; 1351 nsec -= itp->it_value.tv_nsec;
1344 goto expire; 1352 goto expire;
1345 } 1353 }
1346 itp->it_value.tv_nsec += 1000000000; 1354 itp->it_value.tv_nsec += 1000000000;
1347 itp->it_value.tv_sec--; 1355 itp->it_value.tv_sec--;
1348 } 1356 }
1349 itp->it_value.tv_nsec -= nsec; 1357 itp->it_value.tv_nsec -= nsec;
1350 nsec = 0; 1358 nsec = 0;
1351 if (timespecisset(&itp->it_value)) 1359 if (timespecisset(&itp->it_value))
1352 return (1); 1360 return (1);
1353 /* expired, exactly at end of interval */ 1361 /* expired, exactly at end of interval */
1354expire: 1362expire:
1355 if (timespecisset(&itp->it_interval)) { 1363 if (timespecisset(&itp->it_interval)) {
1356 itp->it_value = itp->it_interval; 1364 itp->it_value = itp->it_interval;
1357 itp->it_value.tv_nsec -= nsec; 1365 itp->it_value.tv_nsec -= nsec;
1358 if (itp->it_value.tv_nsec < 0) { 1366 if (itp->it_value.tv_nsec < 0) {
1359 itp->it_value.tv_nsec += 1000000000; 1367 itp->it_value.tv_nsec += 1000000000;
1360 itp->it_value.tv_sec--; 1368 itp->it_value.tv_sec--;
1361 } 1369 }
1362 timer_settime(pt); 1370 timer_settime(pt);
1363 } else 1371 } else
1364 itp->it_value.tv_nsec = 0; /* sec is already 0 */ 1372 itp->it_value.tv_nsec = 0; /* sec is already 0 */
1365 return (0); 1373 return (0);
1366} 1374}
1367 1375
1368static void 1376static void
1369itimerfire(struct ptimer *pt) 1377itimerfire(struct ptimer *pt)
1370{ 1378{
1371 1379
1372 KASSERT(mutex_owned(&timer_lock)); 1380 KASSERT(mutex_owned(&timer_lock));
1373 1381
1374 /* 1382 /*
1375 * XXX Can overrun, but we don't do signal queueing yet, anyway. 1383 * XXX Can overrun, but we don't do signal queueing yet, anyway.
1376 * XXX Relying on the clock interrupt is stupid. 1384 * XXX Relying on the clock interrupt is stupid.
1377 */ 1385 */
1378 if ((pt->pt_ev.sigev_notify == SIGEV_SA && pt->pt_proc->p_sa == NULL) || 1386 if ((pt->pt_ev.sigev_notify == SIGEV_SA && pt->pt_proc->p_sa == NULL) ||
1379 (pt->pt_ev.sigev_notify != SIGEV_SIGNAL && 1387 (pt->pt_ev.sigev_notify != SIGEV_SIGNAL &&
1380 pt->pt_ev.sigev_notify != SIGEV_SA) || pt->pt_queued) 1388 pt->pt_ev.sigev_notify != SIGEV_SA) || pt->pt_queued)
1381 return; 1389 return;
1382 TAILQ_INSERT_TAIL(&timer_queue, pt, pt_chain); 1390 TAILQ_INSERT_TAIL(&timer_queue, pt, pt_chain);
1383 pt->pt_queued = true; 1391 pt->pt_queued = true;
1384 softint_schedule(timer_sih); 1392 softint_schedule(timer_sih);
1385} 1393}
1386 1394
1387void 1395void
1388timer_tick(lwp_t *l, bool user) 1396timer_tick(lwp_t *l, bool user)
1389{ 1397{
1390 struct ptimers *pts; 1398 struct ptimers *pts;
1391 struct ptimer *pt; 1399 struct ptimer *pt;
1392 proc_t *p; 1400 proc_t *p;
1393 1401
1394 p = l->l_proc; 1402 p = l->l_proc;
1395 if (p->p_timers == NULL) 1403 if (p->p_timers == NULL)
1396 return; 1404 return;
1397 1405
1398 mutex_spin_enter(&timer_lock); 1406 mutex_spin_enter(&timer_lock);
1399 if ((pts = l->l_proc->p_timers) != NULL) { 1407 if ((pts = l->l_proc->p_timers) != NULL) {
1400 /* 1408 /*
1401 * Run current process's virtual and profile time, as needed. 1409 * Run current process's virtual and profile time, as needed.
1402 */ 1410 */
1403 if (user && (pt = LIST_FIRST(&pts->pts_virtual)) != NULL) 1411 if (user && (pt = LIST_FIRST(&pts->pts_virtual)) != NULL)
1404 if (itimerdecr(pt, tick * 1000) == 0) 1412 if (itimerdecr(pt, tick * 1000) == 0)
1405 itimerfire(pt); 1413 itimerfire(pt);
1406 if ((pt = LIST_FIRST(&pts->pts_prof)) != NULL) 1414 if ((pt = LIST_FIRST(&pts->pts_prof)) != NULL)
1407 if (itimerdecr(pt, tick * 1000) == 0) 1415 if (itimerdecr(pt, tick * 1000) == 0)
1408 itimerfire(pt); 1416 itimerfire(pt);
1409 } 1417 }
1410 mutex_spin_exit(&timer_lock); 1418 mutex_spin_exit(&timer_lock);
1411} 1419}
1412 1420
1413#ifdef KERN_SA 1421#ifdef KERN_SA
1414/* 1422/*
1415 * timer_sa_intr: 1423 * timer_sa_intr:
1416 * 1424 *
1417 * SIGEV_SA handling for timer_intr(). We are called (and return) 1425 * SIGEV_SA handling for timer_intr(). We are called (and return)
1418 * with the timer lock held. We know that the process had SA enabled 1426 * with the timer lock held. We know that the process had SA enabled
1419 * when this timer was enqueued. As timer_intr() is a soft interrupt 1427 * when this timer was enqueued. As timer_intr() is a soft interrupt
1420 * handler, SA should still be enabled by the time we get here. 1428 * handler, SA should still be enabled by the time we get here.
1421 */ 1429 */
1422static void 1430static void
1423timer_sa_intr(struct ptimer *pt, proc_t *p) 1431timer_sa_intr(struct ptimer *pt, proc_t *p)
1424{ 1432{
1425 unsigned int i; 1433 unsigned int i;
1426 struct sadata *sa; 1434 struct sadata *sa;
1427 struct sadata_vp *vp; 1435 struct sadata_vp *vp;
1428 1436
1429 /* Cause the process to generate an upcall when it returns. */ 1437 /* Cause the process to generate an upcall when it returns. */
1430 if (!p->p_timerpend) { 1438 if (!p->p_timerpend) {
1431 /* 1439 /*
1432 * XXX stop signals can be processed inside tsleep, 1440 * XXX stop signals can be processed inside tsleep,
1433 * which can be inside sa_yield's inner loop, which 1441 * which can be inside sa_yield's inner loop, which
1434 * makes testing for sa_idle alone insuffucent to 1442 * makes testing for sa_idle alone insuffucent to
1435 * determine if we really should call setrunnable. 1443 * determine if we really should call setrunnable.
1436 */ 1444 */
1437 pt->pt_poverruns = pt->pt_overruns; 1445 pt->pt_poverruns = pt->pt_overruns;
1438 pt->pt_overruns = 0; 1446 pt->pt_overruns = 0;
1439 i = 1 << pt->pt_entry; 1447 i = 1 << pt->pt_entry;
1440 p->p_timers->pts_fired = i; 1448 p->p_timers->pts_fired = i;
1441 p->p_timerpend = 1; 1449 p->p_timerpend = 1;
1442 1450
1443 sa = p->p_sa; 1451 sa = p->p_sa;
1444 mutex_enter(&sa->sa_mutex); 1452 mutex_enter(&sa->sa_mutex);
1445 SLIST_FOREACH(vp, &sa->sa_vps, savp_next) { 1453 SLIST_FOREACH(vp, &sa->sa_vps, savp_next) {
1446 struct lwp *vp_lwp = vp->savp_lwp; 1454 struct lwp *vp_lwp = vp->savp_lwp;
1447 lwp_lock(vp_lwp); 1455 lwp_lock(vp_lwp);
1448 lwp_need_userret(vp_lwp); 1456 lwp_need_userret(vp_lwp);
1449 if (vp_lwp->l_flag & LW_SA_IDLE) { 1457 if (vp_lwp->l_flag & LW_SA_IDLE) {
1450 vp_lwp->l_flag &= ~LW_SA_IDLE; 1458 vp_lwp->l_flag &= ~LW_SA_IDLE;
1451 lwp_unsleep(vp_lwp, true); 1459 lwp_unsleep(vp_lwp, true);
1452 break; 1460 break;
1453 } 1461 }
1454 lwp_unlock(vp_lwp); 1462 lwp_unlock(vp_lwp);
1455 } 1463 }
1456 mutex_exit(&sa->sa_mutex); 1464 mutex_exit(&sa->sa_mutex);
1457 } else { 1465 } else {
1458 i = 1 << pt->pt_entry; 1466 i = 1 << pt->pt_entry;
1459 if ((p->p_timers->pts_fired & i) == 0) { 1467 if ((p->p_timers->pts_fired & i) == 0) {
1460 pt->pt_poverruns = pt->pt_overruns; 1468 pt->pt_poverruns = pt->pt_overruns;
1461 pt->pt_overruns = 0; 1469 pt->pt_overruns = 0;
1462 p->p_timers->pts_fired |= i; 1470 p->p_timers->pts_fired |= i;
1463 } else 1471 } else
1464 pt->pt_overruns++; 1472 pt->pt_overruns++;
1465 } 1473 }
1466} 1474}
1467#endif /* KERN_SA */ 1475#endif /* KERN_SA */
1468 1476
1469static void 1477static void
1470timer_intr(void *cookie) 1478timer_intr(void *cookie)
1471{ 1479{
1472 ksiginfo_t ksi; 1480 ksiginfo_t ksi;
1473 struct ptimer *pt; 1481 struct ptimer *pt;
1474 proc_t *p; 1482 proc_t *p;
1475  1483
1476 mutex_enter(proc_lock); 1484 mutex_enter(proc_lock);
1477 mutex_spin_enter(&timer_lock); 1485 mutex_spin_enter(&timer_lock);
1478 while ((pt = TAILQ_FIRST(&timer_queue)) != NULL) { 1486 while ((pt = TAILQ_FIRST(&timer_queue)) != NULL) {
1479 TAILQ_REMOVE(&timer_queue, pt, pt_chain); 1487 TAILQ_REMOVE(&timer_queue, pt, pt_chain);
1480 KASSERT(pt->pt_queued); 1488 KASSERT(pt->pt_queued);
1481 pt->pt_queued = false; 1489 pt->pt_queued = false;
1482 1490
1483 if (pt->pt_proc->p_timers == NULL) { 1491 if (pt->pt_proc->p_timers == NULL) {
1484 /* Process is dying. */ 1492 /* Process is dying. */
1485 continue; 1493 continue;
1486 } 1494 }
1487 p = pt->pt_proc; 1495 p = pt->pt_proc;
1488#ifdef KERN_SA 1496#ifdef KERN_SA
1489 if (pt->pt_ev.sigev_notify == SIGEV_SA) { 1497 if (pt->pt_ev.sigev_notify == SIGEV_SA) {
1490 timer_sa_intr(pt, p); 1498 timer_sa_intr(pt, p);
1491 continue; 1499 continue;
1492 } 1500 }
1493#endif /* KERN_SA */ 1501#endif /* KERN_SA */
1494 if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL) 1502 if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL)
1495 continue; 1503 continue;
1496 if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) { 1504 if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) {
1497 pt->pt_overruns++; 1505 pt->pt_overruns++;
1498 continue; 1506 continue;
1499 } 1507 }
1500 1508
1501 KSI_INIT(&ksi); 1509 KSI_INIT(&ksi);
1502 ksi.ksi_signo = pt->pt_ev.sigev_signo; 1510 ksi.ksi_signo = pt->pt_ev.sigev_signo;
1503 ksi.ksi_code = SI_TIMER; 1511 ksi.ksi_code = SI_TIMER;
1504 ksi.ksi_value = pt->pt_ev.sigev_value; 1512 ksi.ksi_value = pt->pt_ev.sigev_value;
1505 pt->pt_poverruns = pt->pt_overruns; 1513 pt->pt_poverruns = pt->pt_overruns;
1506 pt->pt_overruns = 0; 1514 pt->pt_overruns = 0;
1507 mutex_spin_exit(&timer_lock); 1515 mutex_spin_exit(&timer_lock);
1508 kpsignal(p, &ksi, NULL); 1516 kpsignal(p, &ksi, NULL);
1509 mutex_spin_enter(&timer_lock); 1517 mutex_spin_enter(&timer_lock);
1510 } 1518 }
1511 mutex_spin_exit(&timer_lock); 1519 mutex_spin_exit(&timer_lock);
1512 mutex_exit(proc_lock); 1520 mutex_exit(proc_lock);
1513} 1521}
1514 1522
1515/* 1523/*
1516 * Check if the time will wrap if set to ts. 1524 * Check if the time will wrap if set to ts.
1517 * 1525 *
1518 * ts - timespec describing the new time 1526 * ts - timespec describing the new time
1519 * delta - the delta between the current time and ts 1527 * delta - the delta between the current time and ts
1520 */ 1528 */
1521bool 1529bool
1522time_wraps(struct timespec *ts, struct timespec *delta) 1530time_wraps(struct timespec *ts, struct timespec *delta)
1523{ 1531{
1524 1532
1525 /* 1533 /*
1526 * Don't allow the time to be set forward so far it 1534 * Don't allow the time to be set forward so far it
1527 * will wrap and become negative, thus allowing an 1535 * will wrap and become negative, thus allowing an
1528 * attacker to bypass the next check below. The 1536 * attacker to bypass the next check below. The
1529 * cutoff is 1 year before rollover occurs, so even 1537 * cutoff is 1 year before rollover occurs, so even
1530 * if the attacker uses adjtime(2) to move the time 1538 * if the attacker uses adjtime(2) to move the time
1531 * past the cutoff, it will take a very long time 1539 * past the cutoff, it will take a very long time
1532 * to get to the wrap point. 1540 * to get to the wrap point.
1533 */ 1541 */
1534 if ((ts->tv_sec > LLONG_MAX - 365*24*60*60) || 1542 if ((ts->tv_sec > LLONG_MAX - 365*24*60*60) ||
1535 (delta->tv_sec < 0 || delta->tv_nsec < 0)) 1543 (delta->tv_sec < 0 || delta->tv_nsec < 0))
1536 return true; 1544 return true;
1537 1545
1538 return false; 1546 return false;
1539} 1547}

cvs diff -r1.8 -r1.9 src/sys/kern/subr_time.c (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,225 +1,237 @@ @@ -1,225 +1,237 @@
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.
15 * 3. Neither the name of the University nor the names of its contributors 15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
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
50tvhzto(const struct timeval *tvp) 50tvhzto(const struct timeval *tvp)
51{ 51{
52 struct timeval now, tv; 52 struct timeval now, tv;
53 53
54 tv = *tvp; /* Don't modify original tvp. */ 54 tv = *tvp; /* Don't modify original tvp. */
55 getmicrotime(&now); 55 getmicrotime(&now);
56 timersub(&tv, &now, &tv); 56 timersub(&tv, &now, &tv);
57 return tvtohz(&tv); 57 return tvtohz(&tv);
58} 58}
59 59
60/* 60/*
61 * Compute number of ticks in the specified amount of time. 61 * Compute number of ticks in the specified amount of time.
62 */ 62 */
63int 63int
64tvtohz(const struct timeval *tv) 64tvtohz(const struct timeval *tv)
65{ 65{
66 unsigned long ticks; 66 unsigned long ticks;
67 long sec, usec; 67 long sec, usec;
68 68
69 /* 69 /*
70 * If the number of usecs in the whole seconds part of the time 70 * If the number of usecs in the whole seconds part of the time
71 * difference fits in a long, then the total number of usecs will 71 * difference fits in a long, then the total number of usecs will
72 * fit in an unsigned long. Compute the total and convert it to 72 * fit in an unsigned long. Compute the total and convert it to
73 * ticks, rounding up and adding 1 to allow for the current tick 73 * ticks, rounding up and adding 1 to allow for the current tick
74 * to expire. Rounding also depends on unsigned long arithmetic 74 * to expire. Rounding also depends on unsigned long arithmetic
75 * to avoid overflow. 75 * to avoid overflow.
76 * 76 *
77 * Otherwise, if the number of ticks in the whole seconds part of 77 * Otherwise, if the number of ticks in the whole seconds part of
78 * the time difference fits in a long, then convert the parts to 78 * the time difference fits in a long, then convert the parts to
79 * ticks separately and add, using similar rounding methods and 79 * ticks separately and add, using similar rounding methods and
80 * overflow avoidance. This method would work in the previous 80 * overflow avoidance. This method would work in the previous
81 * case, but it is slightly slower and assumes that hz is integral. 81 * case, but it is slightly slower and assumes that hz is integral.
82 * 82 *
83 * Otherwise, round the time difference down to the maximum 83 * Otherwise, round the time difference down to the maximum
84 * representable value. 84 * representable value.
85 * 85 *
86 * If ints are 32-bit, then the maximum value for any timeout in 86 * If ints are 32-bit, then the maximum value for any timeout in
87 * 10ms ticks is 248 days. 87 * 10ms ticks is 248 days.
88 */ 88 */
89 sec = tv->tv_sec; 89 sec = tv->tv_sec;
90 usec = tv->tv_usec; 90 usec = tv->tv_usec;
91 91
92 KASSERT(usec >= 0 && usec < 1000000); 92 KASSERT(usec >= 0 && usec < 1000000);
93 93
94 /* catch overflows in conversion time_t->int */ 94 /* catch overflows in conversion time_t->int */
95 if (tv->tv_sec > INT_MAX) 95 if (tv->tv_sec > INT_MAX)
96 return INT_MAX; 96 return INT_MAX;
97 if (tv->tv_sec < 0) 97 if (tv->tv_sec < 0)
98 return 0; 98 return 0;
99 99
100 if (sec < 0 || (sec == 0 && usec == 0)) { 100 if (sec < 0 || (sec == 0 && usec == 0)) {
101 /* 101 /*
102 * Would expire now or in the past. Return 0 ticks. 102 * Would expire now or in the past. Return 0 ticks.
103 * This is different from the legacy tvhzto() interface, 103 * This is different from the legacy tvhzto() interface,
104 * and callers need to check for it. 104 * and callers need to check for it.
105 */ 105 */
106 ticks = 0; 106 ticks = 0;
107 } else if (sec <= (LONG_MAX / 1000000)) 107 } else if (sec <= (LONG_MAX / 1000000))
108 ticks = (((sec * 1000000) + (unsigned long)usec + (tick - 1)) 108 ticks = (((sec * 1000000) + (unsigned long)usec + (tick - 1))
109 / tick) + 1; 109 / tick) + 1;
110 else if (sec <= (LONG_MAX / hz)) 110 else if (sec <= (LONG_MAX / hz))
111 ticks = (sec * hz) + 111 ticks = (sec * hz) +
112 (((unsigned long)usec + (tick - 1)) / tick) + 1; 112 (((unsigned long)usec + (tick - 1)) / tick) + 1;
113 else 113 else
114 ticks = LONG_MAX; 114 ticks = LONG_MAX;
115 115
116 if (ticks > INT_MAX) 116 if (ticks > INT_MAX)
117 ticks = INT_MAX; 117 ticks = INT_MAX;
118 118
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);
145 return tvtohz(&tv); 157 return tvtohz(&tv);
146} 158}
147 159
148/* 160/*
149 * Check that a proposed value to load into the .it_value or 161 * Check that a proposed value to load into the .it_value or
150 * .it_interval part of an interval timer is acceptable, and 162 * .it_interval part of an interval timer is acceptable, and
151 * fix it to have at least minimal value (i.e. if it is less 163 * fix it to have at least minimal value (i.e. if it is less
152 * than the resolution of the clock, round it up.) 164 * than the resolution of the clock, round it up.)
153 */ 165 */
154int 166int
155itimerfix(struct timeval *tv) 167itimerfix(struct timeval *tv)
156{ 168{
157 169
158 if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) 170 if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
159 return (EINVAL); 171 return (EINVAL);
160 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 172 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
161 tv->tv_usec = tick; 173 tv->tv_usec = tick;
162 return (0); 174 return (0);
163} 175}
164 176
165int 177int
166itimespecfix(struct timespec *ts) 178itimespecfix(struct timespec *ts)
167{ 179{
168 180
169 if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 181 if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000)
170 return (EINVAL); 182 return (EINVAL);
171 if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) 183 if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000)
172 ts->tv_nsec = tick * 1000; 184 ts->tv_nsec = tick * 1000;
173 return (0); 185 return (0);
174} 186}
175 187
176int 188int
177inittimeleft(struct timespec *ts, struct timespec *sleepts) 189inittimeleft(struct timespec *ts, struct timespec *sleepts)
178{ 190{
179 191
180 if (itimespecfix(ts)) { 192 if (itimespecfix(ts)) {
181 return -1; 193 return -1;
182 } 194 }
183 getnanouptime(sleepts); 195 getnanouptime(sleepts);
184 return 0; 196 return 0;
185} 197}
186 198
187int 199int
188gettimeleft(struct timespec *ts, struct timespec *sleepts) 200gettimeleft(struct timespec *ts, struct timespec *sleepts)
189{ 201{
190 struct timespec sleptts; 202 struct timespec sleptts;
191 203
192 /* 204 /*
193 * Reduce ts by elapsed time based on monotonic time scale. 205 * Reduce ts by elapsed time based on monotonic time scale.
194 */ 206 */
195 getnanouptime(&sleptts); 207 getnanouptime(&sleptts);
196 timespecadd(ts, sleepts, ts); 208 timespecadd(ts, sleepts, ts);
197 timespecsub(ts, &sleptts, ts); 209 timespecsub(ts, &sleptts, ts);
198 *sleepts = sleptts; 210 *sleepts = sleptts;
199 211
200 return tstohz(ts); 212 return tstohz(ts);
201} 213}
202 214
203/* 215/*
204 * Calculate delta and convert from struct timespec to the ticks. 216 * Calculate delta and convert from struct timespec to the ticks.
205 */ 217 */
206int 218int
207abstimeout2timo(struct timespec *ts, int *timo) 219abstimeout2timo(struct timespec *ts, int *timo)
208{ 220{
209 struct timespec tsd; 221 struct timespec tsd;
210 int error; 222 int error;
211 223
212 getnanotime(&tsd); 224 getnanotime(&tsd);
213 timespecsub(ts, &tsd, &tsd); 225 timespecsub(ts, &tsd, &tsd);
214 if (tsd.tv_sec < 0 || (tsd.tv_sec == 0 && tsd.tv_nsec <= 0)) { 226 if (tsd.tv_sec < 0 || (tsd.tv_sec == 0 && tsd.tv_nsec <= 0)) {
215 return ETIMEDOUT; 227 return ETIMEDOUT;
216 } 228 }
217 error = itimespecfix(&tsd); 229 error = itimespecfix(&tsd);
218 if (error) { 230 if (error) {
219 return error; 231 return error;
220 } 232 }
221 *timo = tstohz(&tsd); 233 *timo = tstohz(&tsd);
222 KASSERT(*timo != 0); 234 KASSERT(*timo != 0);
223 235
224 return 0; 236 return 0;
225} 237}

cvs diff -r1.29 -r1.30 src/sys/sys/timevar.h (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,189 +1,190 @@ @@ -1,189 +1,190 @@
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.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Copyright (c) 1982, 1986, 1993 30 * Copyright (c) 1982, 1986, 1993
31 * The Regents of the University of California. All rights reserved. 31 * The Regents of the University of California. All rights reserved.
32 * 32 *
33 * Redistribution and use in source and binary forms, with or without 33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions 34 * modification, are permitted provided that the following conditions
35 * are met: 35 * are met:
36 * 1. Redistributions of source code must retain the above copyright 36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer. 37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright 38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the 39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution. 40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors 41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software 42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission. 43 * without specific prior written permission.
44 * 44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 55 * SUCH DAMAGE.
56 * 56 *
57 * @(#)time.h 8.5 (Berkeley) 5/4/95 57 * @(#)time.h 8.5 (Berkeley) 5/4/95
58 */ 58 */
59 59
60#ifndef _SYS_TIMEVAR_H_ 60#ifndef _SYS_TIMEVAR_H_
61#define _SYS_TIMEVAR_H_ 61#define _SYS_TIMEVAR_H_
62 62
63#include <sys/callout.h> 63#include <sys/callout.h>
64#include <sys/queue.h> 64#include <sys/queue.h>
65#include <sys/signal.h> 65#include <sys/signal.h>
66#include <sys/systm.h> 66#include <sys/systm.h>
67 67
68/* 68/*
69 * Structure used to manage timers in a process. 69 * Structure used to manage timers in a process.
70 */ 70 */
71struct ptimer { 71struct ptimer {
72 union { 72 union {
73 callout_t pt_ch; 73 callout_t pt_ch;
74 struct { 74 struct {
75 LIST_ENTRY(ptimer) pt_list; 75 LIST_ENTRY(ptimer) pt_list;
76 int pt_active; 76 int pt_active;
77 } pt_nonreal; 77 } pt_nonreal;
78 } pt_data; 78 } pt_data;
79 struct sigevent pt_ev; 79 struct sigevent pt_ev;
80 struct itimerspec pt_time; 80 struct itimerspec pt_time;
81 struct ksiginfo pt_info; 81 struct ksiginfo pt_info;
82 int pt_overruns; /* Overruns currently accumulating */ 82 int pt_overruns; /* Overruns currently accumulating */
83 int pt_poverruns; /* Overruns associated w/ a delivery */ 83 int pt_poverruns; /* Overruns associated w/ a delivery */
84 int pt_type; 84 int pt_type;
85 int pt_entry; 85 int pt_entry;
86 int pt_queued; 86 int pt_queued;
87 struct proc *pt_proc; 87 struct proc *pt_proc;
88 TAILQ_ENTRY(ptimer) pt_chain; 88 TAILQ_ENTRY(ptimer) pt_chain;
89}; 89};
90 90
91#define pt_ch pt_data.pt_ch 91#define pt_ch pt_data.pt_ch
92#define pt_list pt_data.pt_nonreal.pt_list 92#define pt_list pt_data.pt_nonreal.pt_list
93#define pt_active pt_data.pt_nonreal.pt_active 93#define pt_active pt_data.pt_nonreal.pt_active
94 94
95#define TIMER_MAX 32 /* See ptimers->pts_fired if you enlarge this */ 95#define TIMER_MAX 32 /* See ptimers->pts_fired if you enlarge this */
96#define TIMERS_ALL 0 96#define TIMERS_ALL 0
97#define TIMERS_POSIX 1 97#define TIMERS_POSIX 1
98 98
99LIST_HEAD(ptlist, ptimer); 99LIST_HEAD(ptlist, ptimer);
100 100
101struct ptimers { 101struct ptimers {
102 struct ptlist pts_virtual; 102 struct ptlist pts_virtual;
103 struct ptlist pts_prof; 103 struct ptlist pts_prof;
104 struct ptimer *pts_timers[TIMER_MAX]; 104 struct ptimer *pts_timers[TIMER_MAX];
105 int pts_fired; 105 int pts_fired;
106}; 106};
107 107
108/* 108/*
109 * Functions for looking at our clock: [get]{bin,nano,micro}[up]time() 109 * Functions for looking at our clock: [get]{bin,nano,micro}[up]time()
110 * 110 *
111 * Functions without the "get" prefix returns the best timestamp 111 * Functions without the "get" prefix returns the best timestamp
112 * we can produce in the given format. 112 * we can produce in the given format.
113 * 113 *
114 * "bin" == struct bintime == seconds + 64 bit fraction of seconds. 114 * "bin" == struct bintime == seconds + 64 bit fraction of seconds.
115 * "nano" == struct timespec == seconds + nanoseconds. 115 * "nano" == struct timespec == seconds + nanoseconds.
116 * "micro" == struct timeval == seconds + microseconds. 116 * "micro" == struct timeval == seconds + microseconds.
117 *  117 *
118 * Functions containing "up" returns time relative to boot and 118 * Functions containing "up" returns time relative to boot and
119 * should be used for calculating time intervals. 119 * should be used for calculating time intervals.
120 * 120 *
121 * Functions without "up" returns GMT time. 121 * Functions without "up" returns GMT time.
122 * 122 *
123 * Functions with the "get" prefix returns a less precise result 123 * Functions with the "get" prefix returns a less precise result
124 * much faster than the functions without "get" prefix and should 124 * much faster than the functions without "get" prefix and should
125 * be used where a precision of 1/HZ (eg 10 msec on a 100HZ machine) 125 * be used where a precision of 1/HZ (eg 10 msec on a 100HZ machine)
126 * is acceptable or where performance is priority. 126 * is acceptable or where performance is priority.
127 * (NB: "precision", _not_ "resolution" !)  127 * (NB: "precision", _not_ "resolution" !)
128 *  128 *
129 */ 129 */
130 130
131void binuptime(struct bintime *); 131void binuptime(struct bintime *);
132void nanouptime(struct timespec *); 132void nanouptime(struct timespec *);
133void microuptime(struct timeval *); 133void microuptime(struct timeval *);
134 134
135void bintime(struct bintime *); 135void bintime(struct bintime *);
136void nanotime(struct timespec *); 136void nanotime(struct timespec *);
137void microtime(struct timeval *); 137void microtime(struct timeval *);
138 138
139void getbinuptime(struct bintime *); 139void getbinuptime(struct bintime *);
140void getnanouptime(struct timespec *); 140void getnanouptime(struct timespec *);
141void getmicrouptime(struct timeval *); 141void getmicrouptime(struct timeval *);
142 142
143void getbintime(struct bintime *); 143void getbintime(struct bintime *);
144void getnanotime(struct timespec *); 144void getnanotime(struct timespec *);
145void getmicrotime(struct timeval *); 145void 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 *);
172void timer_gettime(struct ptimer *, struct itimerspec *); 173void timer_gettime(struct ptimer *, struct itimerspec *);
173void timer_settime(struct ptimer *); 174void timer_settime(struct ptimer *);
174struct ptimers *timers_alloc(struct proc *); 175struct ptimers *timers_alloc(struct proc *);
175void timers_free(struct proc *, int); 176void timers_free(struct proc *, int);
176void timer_tick(struct lwp *, bool); 177void timer_tick(struct lwp *, bool);
177int tstohz(const struct timespec *); 178int tstohz(const struct timespec *);
178int tvtohz(const struct timeval *); 179int tvtohz(const struct timeval *);
179int inittimeleft(struct timespec *, struct timespec *); 180int inittimeleft(struct timespec *, struct timespec *);
180int gettimeleft(struct timespec *, struct timespec *); 181int gettimeleft(struct timespec *, struct timespec *);
181void timerupcall(struct lwp *); 182void timerupcall(struct lwp *);
182void time_init(void); 183void time_init(void);
183void time_init2(void); 184void time_init2(void);
184bool time_wraps(struct timespec *, struct timespec *); 185bool time_wraps(struct timespec *, struct timespec *);
185 186
186extern time_t time_second; /* current second in the epoch */ 187extern time_t time_second; /* current second in the epoch */
187extern time_t time_uptime; /* system uptime in seconds */ 188extern time_t time_uptime; /* system uptime in seconds */
188 189
189#endif /* !_SYS_TIMEVAR_H_ */ 190#endif /* !_SYS_TIMEVAR_H_ */