[sane-devel] Patch to wait loop in sanei_pio.c

Toby Dickenson toby@tarind.com
Sun, 15 May 2005 21:52:04 +0100


--Boundary-00=_0Z7hC4LPKExNxs1
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Attached is a patch which improves the sanei_pio wait loop with my Epson 
GT-5000.

Firstly, sanei_pio currently waits indefinitely in a busy loop if the scanner 
is switched off. There is a loop-counter limit implemented, but never 
enabled. This patch replaces that with a timeout based on time(). It now 
nicely returns with an error message if the printer is switched off. 
Currently the timeout is fixed at 10 seconds.....  I guess that should be 
slow enough for any scanner.

Secondly, this patch reduces cpu usage by using small sleeps. Previously the 
busy loop would use 100% cpu during scanning.

The check for timeout and sleep are only made after 1000 cycles of the wait 
loop. Most of the time the loop doesnt get that far, so overall performance 
is unaffected. Ive been testing this using 
time scanimage -t 100 -y 50 --mode Color --resolution 200 > /tmp/a.pnm
real time is unchanged at 43 seconds, user time reduced 32%, from 39 to 26 
seconds.

Thanks,

--Boundary-00=_0Z7hC4LPKExNxs1
Content-Type: text/x-diff;
  charset="us-ascii";
  name="pio_loop.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="pio_loop.diff"

--- sane-backends-1.0.15.original/sanei/sanei_pio.c	2003-09-09 16:04:45.000000000 +0100
+++ sane-backends-1.0.15/sanei/sanei_pio.c	2005-05-15 21:30:04.000000000 +0100
@@ -102,4 +102,5 @@
 #include <sys/wait.h>
 #include <unistd.h>
+#include <time.h>
 
 #include "sane/saneopts.h"
@@ -146,5 +147,5 @@
     u_long base;		/* i/o base address */
     int fd;			/* >= 0 when using /dev/port */
-    int max_polls;		/* forever if <= 0 */
+    int max_time_seconds;	/* forever if <= 0 */
     u_int in_use;		/* port in use? */
   }
@@ -205,5 +206,7 @@
 pio_wait (const Port port, u_char val, u_char mask)
 {
-  int n, stat = 0;
+  int stat = 0;
+  long poll_count = 0;
+  time_t start = time(NULL);
 
   DBG (DL60, "wait on port 0x%03lx for %02x mask %02x\n",
@@ -215,10 +218,11 @@
        : "-");
 
-  for (n = 1; (port->max_polls <= 0) || (n <= port->max_polls); n++)
+  for (;;)
     {
+      ++poll_count;
       stat = inb (port->base + PIO_STAT);
       if ((stat & mask) == (val & mask))
 	{
-	  DBG (DL60, "got %02x after %d tries\n", stat, n);
+	  DBG (DL60, "got %02x after %ld tries\n", stat, poll_count);
 	  DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
 	  DBG (DL61, "   NACKNLG %s\n",
@@ -227,6 +231,12 @@
 	  return stat;
 	}
+      if(poll_count>1000)
+        {
+          if ((port->max_time_seconds>0) && (time(NULL)-start >= port->max_time_seconds) )
+	    break;
+          usleep(1);
+        }
     }
-  DBG (DL60, "got %02x aborting after %d\n", stat, port->max_polls);
+  DBG (DL60, "got %02x aborting after %ld\n", stat, poll_count);
   DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
   DBG (DL61, "   NACKNLG %s\n", stat & PIO_STAT_NACKNLG ? "on" : "off");
@@ -451,5 +461,5 @@
   port[n].base = base;
   port[n].fd = -1;
-  port[n].max_polls = 0;
+  port[n].max_time_seconds = 10;
   port[n].in_use = 1;
 

--Boundary-00=_0Z7hC4LPKExNxs1--