[PATCH] evdev: discard oldest event on buffer overflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On a buffer overflow, the head and tail pointers collide.
This makes the buffer suddenly look empty, rather than
full, which may confuse applications.

This patch moves the tail pointer up one event on a buffer
overflow, which "consumes" the oldest event in the buffer
to make room for the incoming event.  Thus, although data
is lost due to the overflow (which is unavoidable), the
data that remains is both recent and still time-ordered.

Signed-off-by: Bill Gatliff <bgat@xxxxxxxxxxxxxxx>
---
 drivers/input/evdev.c |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e3f7fc6..04a18ff 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -55,15 +55,19 @@ static void evdev_pass_event(struct evdev_client *client,
 {
 	/*
 	 * Interrupts are disabled, just acquire the lock.
-	 * Make sure we don't leave with the client buffer
-	 * "empty" by having client->head == client->tail.
 	 */
 	spin_lock(&client->buffer_lock);
-	do {
-		client->buffer[client->head++] = *event;
-		client->head &= client->bufsize - 1;
-	} while (client->head == client->tail);
-	spin_unlock(&client->buffer_lock);
+	client->buffer[client->head++] = *event;
+	client->head &= client->bufsize - 1;
+
+	/*
+	 * If we overflow the buffer, consume the oldest
+	 * event to make room for the one that just arrived
+	 */
+	if (unlikely(client->head == client->tail)) {
+		client->tail++;
+		client->tail &= client->bufsize - 1;
+	}
 
 	if (event->type == EV_SYN)
 		kill_fasync(&client->fasync, SIGIO, POLL_IN);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux