svn commit: r237796 - in projects/calloutng/sys: kern sys

Davide Italiano davide at FreeBSD.org
Fri Jun 29 16:06:06 UTC 2012


Author: davide
Date: Fri Jun 29 16:06:06 2012
New Revision: 237796
URL: http://svn.freebsd.org/changeset/base/237796

Log:
  Experiment a new  approach used for low-precision events, try to align
  them to some time borders on insert.
  This approach can make system load more bursty, but it is very cheap to
  be implemented and may be quite effective. Moreover, it can easily coexist
  with the previously implemented "real-time aggregation".
  
  Discussed with:		mav

Modified:
  projects/calloutng/sys/kern/kern_timeout.c
  projects/calloutng/sys/sys/callout.h

Modified: projects/calloutng/sys/kern/kern_timeout.c
==============================================================================
--- projects/calloutng/sys/kern/kern_timeout.c	Fri Jun 29 15:57:25 2012	(r237795)
+++ projects/calloutng/sys/kern/kern_timeout.c	Fri Jun 29 16:06:06 2012	(r237796)
@@ -497,8 +497,7 @@ callout_cc_add(struct callout *c, struct
     struct bintime to_bintime, void (*func)(void *), void *arg, int cpu, 
     int flags)
 {
-	struct timeval tv;
-	int bucket;	
+	int bucket, r_shift, r_val;	
 	
 	CC_LOCK_ASSERT(cc);
 	if (bintime_cmp(&to_bintime, &cc->cc_lastscan, <)) {
@@ -510,25 +509,38 @@ callout_cc_add(struct callout *c, struct
 		c->c_flags |= CALLOUT_DIRECT;
 	c->c_flags &= ~CALLOUT_PROCESSED;
 	c->c_func = func;
-	c->c_time = to_bintime; 
-	tv.tv_sec = 0;
-	if (flags & C_10US) { 
-		tv.tv_usec = 10;
-		timeval2bintime(&tv, &c->c_precision);
-	}
-	else if (flags & C_100US) {
-		tv.tv_usec = 100;
-		timeval2bintime(&tv, &c->c_precision);
-	} 
-	else if (flags & C_1MS) {
-		tv.tv_usec = 1000;
-		timeval2bintime(&tv, &c->c_precision);
+	c->c_time = to_bintime;
+	bintime_clear(&c->c_precision);
+	if (flags & 0x2) {  
+		r_shift = ((flags >> 2) & PRECISION_RANGE);
+		r_val = (r_shift != 0) ? (uint64_t)1 << (64 - r_shift) : 0;
+		/* 
+		 * Round as far as precision specified is coarse (up to 8ms).
+		 * In order to play safe, round to to half of the interval and
+		 * set half precision.
+		 */	
+		if (r_shift < 6) {
+			r_val = (r_shift != 0) ? r_val >> 2 : 
+			    ((uint64_t)1 << (64 - 1)) - 1;
+			/*
+			 * Round only if c_time is not a multiple of the
+			 * rounding factor.
+			 */
+			if ((c->c_time.frac & r_val) != r_val) {
+				c->c_time.frac |= r_val - 1;
+				c->c_time.frac += 1;
+				if (c->c_time.frac == 0)
+					c->c_time.sec += 1;
+			}
+		}
+		c->c_precision.frac = r_val;
+		CTR6(KTR_CALLOUT, "rounding %d.%u%u to %d.%u%u", 
+		    to_bintime.sec, (u_int) (to_bintime.frac >> 32), 
+		    (u_int) (to_bintime.frac & 0xffffffff), c->c_time.sec, 
+		    (u_int) (c->c_time.frac >> 32), 
+		    (u_int) (c->c_time.frac & 0xffffffff)); 
 	} 
-	else { 
-		c->c_precision.sec = 0;
-		c->c_precision.frac = 0;
-	}
-	bucket = get_bucket(&c->c_time);	
+	bucket = get_bucket(&c->c_time);
 	TAILQ_INSERT_TAIL(&cc->cc_callwheel[bucket & callwheelmask], 
 	    c, c_links.tqe);
 	/*
@@ -536,10 +548,10 @@ callout_cc_add(struct callout *c, struct
 	 * that has been inserted.
 	 */
 	if (callout_new_inserted != NULL && 
-	    (bintime_cmp(&to_bintime, &cc->cc_firstevent, <) ||
+	    (bintime_cmp(&c->c_time, &cc->cc_firstevent, <) ||
 	    (cc->cc_firstevent.sec == 0 && cc->cc_firstevent.frac == 0))) {
-		cc->cc_firstevent = to_bintime;
-		(*callout_new_inserted)(cpu, to_bintime);
+		cc->cc_firstevent = c->c_time;
+		(*callout_new_inserted)(cpu, c->c_time);
 	}
 }
 

Modified: projects/calloutng/sys/sys/callout.h
==============================================================================
--- projects/calloutng/sys/sys/callout.h	Fri Jun 29 15:57:25 2012	(r237795)
+++ projects/calloutng/sys/sys/callout.h	Fri Jun 29 16:06:06 2012	(r237796)
@@ -51,9 +51,28 @@
 #define	CALLOUT_DIRECT 		0x1000 /* allow exec from hw int context */
 
 #define	C_DIRECT_EXEC		0x0001 /* direct execution of callout */
-#define	C_10US			0x0002 /* precision field */
-#define	C_100US			0x0004 /* precision field */	
-#define	C_1MS			0x0008 /* precision field */	
+#define	C_P1S			0x0002 /* fields related to precision */ 
+#define	C_P500MS		0x0006 	
+#define	C_P250MS		0x000a 	
+#define	C_P125MS		0x000e
+#define	C_P64MS			0x0012
+#define	C_P32MS			0x0016
+#define	C_P16MS			0x001a
+#define	C_P8MS			0x001e
+#define	C_P4MS			0x0022
+#define	C_P2MS			0x0026
+#define	C_P1MS			0x002a
+#define	C_P500US		0x002e
+#define	C_P250US		0x0032
+#define	C_P125US		0x0036
+#define	C_P64US			0x003a
+#define	C_P32US			0x003e
+#define	C_P16US			0x0042
+#define	C_P8US			0x0046
+#define	C_P4US			0x004a
+#define	C_P2US			0x004e
+#define	PRECISION_BITS		7	
+#define	PRECISION_RANGE		((1 << PRECISION_BITS) - 1)	
 
 struct callout_handle {
 	struct callout *callout;


More information about the svn-src-projects mailing list