Stop flooding with EV_TXEMPTY

Michael Karcher wine at mkarcher.dialup.fu-berlin.de
Sun May 11 18:22:48 CDT 2008


Do not generate an EV_TXEMPTY event if the transmitter is empty,
but if it got empty. To do that, a count of characters that left
the transmitter completely is calculated, based on the count of
characters sent to the transmitter reported by the kernel and
the hardware queue state. This count is called hard_tx and deltas
in it are used to generate the EV_TXEMPTY event.
---

supercedes the "Stop flooding with EV_TXEMPTY and EV_RXCHAR"
patch.

 dlls/ntdll/serial.c |   44 +++++++++++++++++++++++++-------------------
 1 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 109804b..07ac580 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -849,7 +849,7 @@ static NTSTATUS set_XOn(int fd)
  */
 typedef struct serial_irq_info
 {
-    int rx , tx, frame, overrun, parity, brk, buf_overrun;
+    int rx , tx, hardtx, frame, overrun, parity, brk, buf_overrun;
 }serial_irq_info;
 
 /***********************************************************************
@@ -875,6 +875,7 @@ static NTSTATUS get_irq_info(int fd, serial_irq_info *irq_info)
     struct serial_icounter_struct einfo;
     if (!ioctl(fd, TIOCGICOUNT, &einfo))
     {
+        int queue;
         irq_info->rx          = einfo.rx;
         irq_info->tx          = einfo.tx;
         irq_info->frame       = einfo.frame;
@@ -882,6 +883,27 @@ static NTSTATUS get_irq_info(int fd, serial_irq_info *irq_info)
         irq_info->parity      = einfo.parity;
         irq_info->brk         = einfo.brk;
         irq_info->buf_overrun = einfo.buf_overrun;
+/* We really want to know when all characters have gone out of the transmitter */
+#if defined(TIOCSERGETLSR) 
+        /* TIOCSERGETLSR strangely just returns the transmitter-shift-reg
+           empty bit, currently on bit position 0. The ioctl() name is
+           misleading */
+	if (ioctl(fd, TIOCSERGETLSR, &queue))
+	    WARN("TIOCSERGETLSR returned error\n");
+        else
+	    if(!queue)		/* NOT empty */
+	        queue = 1;
+            else		/* empty */
+                queue = 0;
+/* TIOCOUTQ only checks for an empty buffer */
+#elif defined(TIOCOUTQ)
+	if (ioctl(fd, TIOCOUTQ, &queue))
+	{
+	    WARN("TIOCOUTQ returned error\n");
+	    queue = 0;
+        }
+#endif
+        irq_info->hardtx = irq_info->tx - queue;
         return STATUS_SUCCESS;
     }
     TRACE("TIOCGICOUNT err %s\n", strerror(errno));
@@ -902,6 +924,7 @@ static DWORD WINAPI check_events(int fd, DWORD mask,
     TRACE("mask 0x%08x\n", mask);
     TRACE("old->rx          0x%08x vs. new->rx          0x%08x\n", old->rx, new->rx);
     TRACE("old->tx          0x%08x vs. new->tx          0x%08x\n", old->tx, new->tx);
+    TRACE("old->hardtx      0x%08x vs. new->hardtx      0x%08x\n", old->hardtx, new->hardtx);
     TRACE("old->frame       0x%08x vs. new->frame       0x%08x\n", old->frame, new->frame);
     TRACE("old->overrun     0x%08x vs. new->overrun     0x%08x\n", old->overrun, new->overrun);
     TRACE("old->parity      0x%08x vs. new->parity      0x%08x\n", old->parity, new->parity);
@@ -909,6 +932,7 @@ static DWORD WINAPI check_events(int fd, DWORD mask,
     TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
 
     if (old->brk != new->brk) ret |= EV_BREAK;
+    if (old->hardtx != new->hardtx) ret |= EV_TXEMPTY;
     if ((old_mstat & MS_CTS_ON ) != (new_mstat & MS_CTS_ON )) ret |= EV_CTS;
     if ((old_mstat & MS_DSR_ON ) != (new_mstat & MS_DSR_ON )) ret |= EV_DSR;
     if ((old_mstat & MS_RING_ON) != (new_mstat & MS_RING_ON)) ret |= EV_RING;
@@ -931,24 +955,6 @@ static DWORD WINAPI check_events(int fd, DWORD mask,
             new->rx = old->rx;
         }
     }
-    if (mask & EV_TXEMPTY)
-    {
-	queue = 0;
-/* We really want to know when all characters have gone out of the transmitter */
-#if defined(TIOCSERGETLSR) 
-	if (ioctl(fd, TIOCSERGETLSR, &queue))
-	    WARN("TIOCSERGETLSR returned error\n");
-	if (queue)
-/* TIOCOUTQ only checks for an empty buffer */
-#elif defined(TIOCOUTQ)
-	if (ioctl(fd, TIOCOUTQ, &queue))
-	    WARN("TIOCOUTQ returned error\n");
-	if (!queue)
-#endif
-           ret |= EV_TXEMPTY;
-	TRACE("OUTQUEUE %d, Transmitter %sempty\n",
-              queue, (ret & EV_TXEMPTY) ? "" : "not ");
-    }
     TRACE("ret=%03x\n",ret);
     return ret & mask;
 }
-- 
1.5.5.1




More information about the wine-patches mailing list