|
@@ -39,13 +39,13 @@ struct evdev {
|
|
};
|
|
};
|
|
|
|
|
|
struct evdev_client {
|
|
struct evdev_client {
|
|
- int head;
|
|
|
|
- int tail;
|
|
|
|
|
|
+ unsigned int head;
|
|
|
|
+ unsigned int tail;
|
|
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
|
|
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
|
|
struct fasync_struct *fasync;
|
|
struct fasync_struct *fasync;
|
|
struct evdev *evdev;
|
|
struct evdev *evdev;
|
|
struct list_head node;
|
|
struct list_head node;
|
|
- int bufsize;
|
|
|
|
|
|
+ unsigned int bufsize;
|
|
struct input_event buffer[];
|
|
struct input_event buffer[];
|
|
};
|
|
};
|
|
|
|
|
|
@@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex);
|
|
static void evdev_pass_event(struct evdev_client *client,
|
|
static void evdev_pass_event(struct evdev_client *client,
|
|
struct input_event *event)
|
|
struct input_event *event)
|
|
{
|
|
{
|
|
- /*
|
|
|
|
- * Interrupts are disabled, just acquire the lock.
|
|
|
|
- * Make sure we don't leave with the client buffer
|
|
|
|
- * "empty" by having client->head == client->tail.
|
|
|
|
- */
|
|
|
|
|
|
+ /* Interrupts are disabled, just acquire the lock. */
|
|
spin_lock(&client->buffer_lock);
|
|
spin_lock(&client->buffer_lock);
|
|
- do {
|
|
|
|
- client->buffer[client->head++] = *event;
|
|
|
|
- client->head &= client->bufsize - 1;
|
|
|
|
- } while (client->head == client->tail);
|
|
|
|
|
|
+
|
|
|
|
+ client->buffer[client->head++] = *event;
|
|
|
|
+ client->head &= client->bufsize - 1;
|
|
|
|
+
|
|
|
|
+ if (unlikely(client->head == client->tail)) {
|
|
|
|
+ /*
|
|
|
|
+ * This effectively "drops" all unconsumed events, leaving
|
|
|
|
+ * EV_SYN/SYN_DROPPED plus the newest event in the queue.
|
|
|
|
+ */
|
|
|
|
+ client->tail = (client->head - 2) & (client->bufsize - 1);
|
|
|
|
+
|
|
|
|
+ client->buffer[client->tail].time = event->time;
|
|
|
|
+ client->buffer[client->tail].type = EV_SYN;
|
|
|
|
+ client->buffer[client->tail].code = SYN_DROPPED;
|
|
|
|
+ client->buffer[client->tail].value = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
spin_unlock(&client->buffer_lock);
|
|
spin_unlock(&client->buffer_lock);
|
|
|
|
|
|
if (event->type == EV_SYN)
|
|
if (event->type == EV_SYN)
|