Module Name:    src
Committed By:   yamt
Date:           Fri Apr  8 10:35:38 UTC 2011

Modified Files:
        src/sys/kern: kern_time.c

Log Message:
implement timer_create of CLOCK_MONOTONIC


To generate a diff of this commit:
cvs rdiff -u -r1.167 -r1.168 src/sys/kern/kern_time.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_time.c
diff -u src/sys/kern/kern_time.c:1.167 src/sys/kern/kern_time.c:1.168
--- src/sys/kern/kern_time.c:1.167	Tue Apr  5 00:27:35 2011
+++ src/sys/kern/kern_time.c	Fri Apr  8 10:35:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_time.c,v 1.167 2011/04/05 00:27:35 yamt Exp $	*/
+/*	$NetBSD: kern_time.c,v 1.168 2011/04/08 10:35:37 yamt Exp $	*/
 
 /*-
  * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.167 2011/04/05 00:27:35 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.168 2011/04/08 10:35:37 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/resourcevar.h>
@@ -95,6 +95,13 @@
 
 struct pool ptimer_pool, ptimers_pool;
 
+#define	CLOCK_VIRTUAL_P(clockid)	\
+	((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF)
+
+CTASSERT(ITIMER_REAL == CLOCK_REALTIME);
+CTASSERT(ITIMER_VIRTUAL == CLOCK_VIRTUAL);
+CTASSERT(ITIMER_PROF == CLOCK_PROF);
+
 /*
  * Initialize timekeeping.
  */
@@ -538,7 +545,8 @@
 
 	p = l->l_proc;
 
-	if (id < CLOCK_REALTIME || id > CLOCK_PROF)
+	if (id != CLOCK_REALTIME && id != CLOCK_VIRTUAL &&
+	    id != CLOCK_PROF && id != CLOCK_MONOTONIC)
 		return (EINVAL);
 
 	if ((pts = p->p_timers) == NULL)
@@ -572,6 +580,7 @@
 		pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
 		switch (id) {
 		case CLOCK_REALTIME:
+		case CLOCK_MONOTONIC:
 			pt->pt_ev.sigev_signo = SIGALRM;
 			break;
 		case CLOCK_VIRTUAL:
@@ -596,8 +605,8 @@
 	pt->pt_entry = timerid;
 	pt->pt_queued = false;
 	timespecclear(&pt->pt_time.it_value);
-	if (id == CLOCK_REALTIME)
-		callout_init(&pt->pt_ch, 0);
+	if (!CLOCK_VIRTUAL_P(id))
+		callout_init(&pt->pt_ch, CALLOUT_MPSAFE);
 	else
 		pt->pt_active = 0;
 
@@ -631,7 +640,7 @@
 		mutex_spin_exit(&timer_lock);
 		return (EINVAL);
 	}
-	if (pt->pt_type != CLOCK_REALTIME) {
+	if (CLOCK_VIRTUAL_P(pt->pt_type)) {
 		if (pt->pt_active) {
 			ptn = LIST_NEXT(pt, pt_list);
 			LIST_REMOVE(pt, pt_list);
@@ -649,9 +658,8 @@
 
 /*
  * Set up the given timer. The value in pt->pt_time.it_value is taken
- * to be an absolute time for CLOCK_REALTIME timers and a relative
- * time for virtual timers.
- * Must be called at splclock().
+ * to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC timers and
+ * a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers.
  */
 void
 timer_settime(struct ptimer *pt)
@@ -661,8 +669,8 @@
 
 	KASSERT(mutex_owned(&timer_lock));
 
-	if (pt->pt_type == CLOCK_REALTIME) {
-		callout_stop(&pt->pt_ch);
+	if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
+		callout_halt(&pt->pt_ch, &timer_lock);
 		if (timespecisset(&pt->pt_time.it_value)) {
 			/*
 			 * Don't need to check tshzto() return value, here.
@@ -719,7 +727,7 @@
 	KASSERT(mutex_owned(&timer_lock));
 
 	*aits = pt->pt_time;
-	if (pt->pt_type == CLOCK_REALTIME) {
+	if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
 		/*
 		 * Convert from absolute to relative time in .it_value
 		 * part of real time timer.  If time for real time
@@ -728,7 +736,11 @@
 		 * off.
 		 */
 		if (timespecisset(&aits->it_value)) {
-			getnanotime(&now);
+			if (pt->pt_type == CLOCK_REALTIME) {
+				getnanotime(&now);
+			} else { /* CLOCK_MONOTONIC */
+				getnanouptime(&now);
+			}
 			if (timespeccmp(&aits->it_value, &now, <))
 				timespecclear(&aits->it_value);
 			else
@@ -818,9 +830,13 @@
 	 * negative, which would confuse the comparison tests.
 	 */
 	if (timespecisset(&pt->pt_time.it_value)) {
-		if (pt->pt_type == CLOCK_REALTIME) {
+		if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
 			if ((flags & TIMER_ABSTIME) == 0) {
-				getnanotime(&now);
+				if (pt->pt_type == CLOCK_REALTIME) {
+					getnanotime(&now);
+				} else { /* CLOCK_MONOTONIC */
+					getnanouptime(&now);
+				}
 				timespecadd(&pt->pt_time.it_value, &now,
 				    &pt->pt_time.it_value);
 			}
@@ -1110,6 +1126,8 @@
 	struct ptimers *pts;
 	struct ptimer *pt, *spare;
 
+	KASSERT(which == CLOCK_REALTIME || which == CLOCK_VIRTUAL ||
+	    which == CLOCK_PROF);
 	if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
 		return (EINVAL);
 
@@ -1230,12 +1248,12 @@
 		for (ptn = LIST_FIRST(&pts->pts_virtual);
 		     ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL];
 		     ptn = LIST_NEXT(ptn, pt_list)) {
-			KASSERT(ptn->pt_type != CLOCK_REALTIME);
+			KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
 			timespecadd(&ts, &ptn->pt_time.it_value, &ts);
 		}
 		LIST_FIRST(&pts->pts_virtual) = NULL;
 		if (ptn) {
-			KASSERT(ptn->pt_type != CLOCK_REALTIME);
+			KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
 			timespecadd(&ts, &ptn->pt_time.it_value,
 			    &ptn->pt_time.it_value);
 			LIST_INSERT_HEAD(&pts->pts_virtual, ptn, pt_list);
@@ -1244,12 +1262,12 @@
 		for (ptn = LIST_FIRST(&pts->pts_prof);
 		     ptn && ptn != pts->pts_timers[ITIMER_PROF];
 		     ptn = LIST_NEXT(ptn, pt_list)) {
-			KASSERT(ptn->pt_type != CLOCK_REALTIME);
+			KASSERT(ptn->pt_type == CLOCK_PROF);
 			timespecadd(&ts, &ptn->pt_time.it_value, &ts);
 		}
 		LIST_FIRST(&pts->pts_prof) = NULL;
 		if (ptn) {
-			KASSERT(ptn->pt_type != CLOCK_REALTIME);
+			KASSERT(ptn->pt_type == CLOCK_PROF);
 			timespecadd(&ts, &ptn->pt_time.it_value,
 			    &ptn->pt_time.it_value);
 			LIST_INSERT_HEAD(&pts->pts_prof, ptn, pt_list);
@@ -1280,12 +1298,12 @@
 
 	pt = pts->pts_timers[index];
 	pts->pts_timers[index] = NULL;
-	if (pt->pt_type == CLOCK_REALTIME)
+	if (!CLOCK_VIRTUAL_P(pt->pt_type))
 		callout_halt(&pt->pt_ch, &timer_lock);
 	if (pt->pt_queued)
 		TAILQ_REMOVE(&timer_queue, pt, pt_chain);
 	mutex_spin_exit(&timer_lock);
-	if (pt->pt_type == CLOCK_REALTIME)
+	if (!CLOCK_VIRTUAL_P(pt->pt_type))
 		callout_destroy(&pt->pt_ch);
 	pool_put(&ptimer_pool, pt);
 }
@@ -1306,6 +1324,7 @@
 	struct itimerspec *itp;
 
 	KASSERT(mutex_owned(&timer_lock));
+	KASSERT(CLOCK_VIRTUAL_P(pt->pt_type));
 
 	itp = &pt->pt_time;
 	if (itp->it_value.tv_nsec < nsec) {

Reply via email to