[PATCH] hvc_console polling mode timer backoff

Michael Ellerman michael at ellerman.id.au
Fri Apr 13 17:47:39 EST 2007


On Thu, 2007-04-12 at 11:14 -0500, Will Schmidt wrote:
> Add a backoff mechanism to hvc_console's polling logic.   This change
> drops the timers/second ratio from ~90 to ~1 while the console is idle.
> This is very noticable when watching /proc/timer_stats output.
> 
> This only affects when the hvc_console is running in poll mode, i.e. power4
> and cell systems.
> 
> I've tested on Power4, Michael Ellerman has tested on cell.

I played with this a bit more, and a ~2% increment seems to work nicely.
It stays low for the first 10-20 seconds, but then approaches the max
much faster once there's no activity for a while.

A few examples:
http://michael.ellerman.id.au/files/cell-backoff.svg

As you can (sort of) see on the graph, after 30 seconds the delay is
still around 1/2 a second which is basically unnoticable IMHO.

Because this is a super tight performance critical inner loop I've
changed it to use a shift instead of divide. So now it's more like 1.5%,
but still the point is it increases faster as time passes.

It'd be good if some more people can bang on this and see what they
think of the interactivity.

Index: cell/drivers/char/hvc_console.c
===================================================================
--- cell.orig/drivers/char/hvc_console.c
+++ cell/drivers/char/hvc_console.c
@@ -47,8 +47,6 @@
 #define HVC_MAJOR	229
 #define HVC_MINOR	0
 
-#define TIMEOUT		(10)
-
 /*
  * Wait this long per iteration while trying to push buffered data to the
  * hypervisor before allowing the tty to complete a close operation.
@@ -550,6 +548,26 @@ static int hvc_chars_in_buffer(struct tt
 	return hp->n_outbuf;
 }
 
+/*
+ * timeout will vary between the MIN and MAX values defined here.  By default
+ * and during console activity we will use a default MIN_TIMEOUT of 10.  When
+ * the console is idle, we increase the timeout value on each pass through
+ * msleep until we reach the max.  This may be noticable as a brief (average
+ * one second) delay on the console before the console responds to input when
+ * there has been no input for sometime.
+ */
+#define MIN_TIMEOUT		(10)
+#define MAX_TIMEOUT		(2000)
+static u32 timeout = MIN_TIMEOUT;
+
+#include <linux/debugfs.h>
+static int hvc_debug_init(void)
+{
+	debugfs_create_u32("hvc_timeout", 0400, NULL, &timeout);
+	return 0;
+}
+__initcall(hvc_debug_init);
+
 #define HVC_POLL_READ	0x00000001
 #define HVC_POLL_WRITE	0x00000002
 
@@ -642,9 +660,14 @@ static int hvc_poll(struct hvc_struct *h
  bail:
 	spin_unlock_irqrestore(&hp->lock, flags);
 
-	if (read_total)
+	if (read_total) {
+		/* Activity is occurring, so reset the polling backoff value to
+		   a minimum for performance. */
+		timeout = MIN_TIMEOUT;
+
 		tty_flip_buffer_push(tty);
-	
+	}
+
 	return poll_mask;
 }
 
@@ -688,8 +711,12 @@ int khvcd(void *unused)
 		if (!hvc_kicked) {
 			if (poll_mask == 0)
 				schedule();
-			else
-				msleep_interruptible(TIMEOUT);
+			else {
+				if (timeout < MAX_TIMEOUT)
+					timeout += (timeout >> 6) + 1;
+
+				msleep_interruptible(timeout);
+			}
 		}
 		__set_current_state(TASK_RUNNING);
 	} while (!kthread_should_stop());





More information about the Linuxppc-dev mailing list