changeset 14110:623d25456fad

3935 timer_settime() for a one-shot should use cyclic_reprogram() 3936 cyclic_remove_here() blocked with cyp_rpend of UINT32_MAX 3937 cyclic processing fails when cy_pend is greater than INT32_MAX Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Dan McDonald <danmcd@nexenta.com>
author Bryan Cantrill <bryan@joyent.com>
date Tue, 24 May 2011 23:08:51 -0700
parents 9365fdf3a618
children eae3d706a928
files usr/src/uts/common/os/clock_highres.c usr/src/uts/common/os/cyclic.c
diffstat 2 files changed, 31 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/clock_highres.c	Thu Aug 01 22:41:15 2013 +0000
+++ b/usr/src/uts/common/os/clock_highres.c	Tue May 24 23:08:51 2011 -0700
@@ -24,7 +24,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012, Joyent Inc. All rights reserved.
+ */
 
 #include <sys/timer.h>
 #include <sys/systm.h>
@@ -112,6 +114,25 @@
 	cyctime.cyt_when = ts2hrt(&when->it_value);
 	cyctime.cyt_interval = ts2hrt(&when->it_interval);
 
+	if (cyctime.cyt_when != 0 && cyctime.cyt_interval == 0 &&
+	    it->it_itime.it_interval.tv_sec == 0 &&
+	    it->it_itime.it_interval.tv_nsec == 0 &&
+	    (cyc = *cycp) != CYCLIC_NONE) {
+		/*
+		 * If our existing timer is a one-shot and our new timer is a
+		 * one-shot, we'll save ourselves a world of grief and just
+		 * reprogram the cyclic.
+		 */
+		it->it_itime = *when;
+
+		if (!(flags & TIMER_ABSTIME))
+			cyctime.cyt_when += gethrtime();
+
+		hrt2ts(cyctime.cyt_when, &it->it_itime.it_value);
+		(void) cyclic_reprogram(cyc, cyctime.cyt_when);
+		return (0);
+	}
+
 	mutex_enter(&cpu_lock);
 	if ((cyc = *cycp) != CYCLIC_NONE) {
 		cyclic_remove(cyc);
@@ -162,17 +183,14 @@
 
 	if (cyctime.cyt_interval == 0) {
 		/*
-		 * If this is a one-shot, then we set the interval to assure
-		 * that the cyclic will next fire INT64_MAX nanoseconds after
-		 * boot (which corresponds to over 292 years -- yes, Buck Rogers
-		 * may have his 292-year-uptime-Solaris box malfunction).  If
-		 * this timer is never touched, this cyclic will simply
-		 * consume space in the cyclic subsystem.  As soon as
+		 * If this is a one-shot, then we set the interval to be
+		 * inifinite.  If this timer is never touched, this cyclic will
+		 * simply consume space in the cyclic subsystem.  As soon as
 		 * timer_settime() or timer_delete() is called, the cyclic is
 		 * removed (so it's not possible to run the machine out
 		 * of resources by creating one-shots).
 		 */
-		cyctime.cyt_interval = INT64_MAX - cyctime.cyt_when;
+		cyctime.cyt_interval = CY_INFINITY;
 	}
 
 	it->it_itime = *when;
@@ -185,8 +203,6 @@
 
 	if (cyctime.cyt_when != 0)
 		*cycp = cyc = cyclic_add(&hdlr, &cyctime);
-	else
-		*cycp = cyc = CYCLIC_NONE;
 
 	/*
 	 * Now that we have the cyclic created, we need to bind it to our
--- a/usr/src/uts/common/os/cyclic.c	Thu Aug 01 22:41:15 2013 +0000
+++ b/usr/src/uts/common/os/cyclic.c	Tue May 24 23:08:51 2011 -0700
@@ -24,6 +24,10 @@
  */
 
 /*
+ * Copyright (c) 2012, Joyent Inc. All rights reserved.
+ */
+
+/*
  *  The Cyclic Subsystem
  *  --------------------
  *
@@ -1139,7 +1143,7 @@
 	CYC_TRACE(cpu, level, "softint-top", cyclics, pc);
 
 	while (consndx != pc->cypc_prodndx) {
-		int pend, npend, opend;
+		uint32_t pend, npend, opend;
 		int consmasked = consndx & sizemask;
 		cyclic_t *cyclic = &cyclics[buf[consmasked]];
 		cyc_func_t handler = cyclic->cy_handler;