From 82ba56c273911f7eda79849cfa0fc2d2e5a3b75b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Oct 2007 15:46:55 -0400 Subject: Input: use full RCU API RT guys alerted me to the fact that in their tree spinlocks are preemptible and it is better to use full RCU API (rcu_read_lock()/rcu_read_unlock()) to be safe. Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 22 +++++++++------------- drivers/input/input.c | 36 +++++++++++++++--------------------- drivers/input/joydev.c | 11 ++++------- drivers/input/mousedev.c | 11 ++++------- 4 files changed, 32 insertions(+), 48 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 27026f7d3c03..1d62c8b88e12 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -63,10 +63,7 @@ static void evdev_pass_event(struct evdev_client *client, } /* - * Pass incoming event to all connected clients. Note that we are - * caleld under a spinlock with interrupts off so we don't need - * to use rcu_read_lock() here. Writers will be using syncronize_sched() - * instead of synchrnoize_rcu(). + * Pass incoming event to all connected clients. */ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) @@ -80,6 +77,8 @@ static void evdev_event(struct input_handle *handle, event.code = code; event.value = value; + rcu_read_lock(); + client = rcu_dereference(evdev->grab); if (client) evdev_pass_event(client, &event); @@ -87,6 +86,8 @@ static void evdev_event(struct input_handle *handle, list_for_each_entry_rcu(client, &evdev->client_list, node) evdev_pass_event(client, &event); + rcu_read_unlock(); + wake_up_interruptible(&evdev->wait); } @@ -142,12 +143,7 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client) return error; rcu_assign_pointer(evdev->grab, client); - /* - * We don't use synchronize_rcu() here because read-side - * critical section is protected by a spinlock instead - * of rcu_read_lock(). - */ - synchronize_sched(); + synchronize_rcu(); return 0; } @@ -158,7 +154,7 @@ static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) return -EINVAL; rcu_assign_pointer(evdev->grab, NULL); - synchronize_sched(); + synchronize_rcu(); input_release_device(&evdev->handle); return 0; @@ -170,7 +166,7 @@ static void evdev_attach_client(struct evdev *evdev, spin_lock(&evdev->client_lock); list_add_tail_rcu(&client->node, &evdev->client_list); spin_unlock(&evdev->client_lock); - synchronize_sched(); + synchronize_rcu(); } static void evdev_detach_client(struct evdev *evdev, @@ -179,7 +175,7 @@ static void evdev_detach_client(struct evdev *evdev, spin_lock(&evdev->client_lock); list_del_rcu(&client->node); spin_unlock(&evdev->client_lock); - synchronize_sched(); + synchronize_rcu(); } static int evdev_open_device(struct evdev *evdev) diff --git a/drivers/input/input.c b/drivers/input/input.c index 3070c7aa1237..2f2b020cd629 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -65,16 +65,16 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) /* * Pass event through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. Because of that we - * do not need to use rcu_read_lock() here although we are using RCU - * to access handle list. Note that because of that write-side uses - * synchronize_sched() instead of synchronize_ru(). + * dev->event_lock held and interrupts disabled. */ static void input_pass_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct input_handle *handle = rcu_dereference(dev->grab); + struct input_handle *handle; + + rcu_read_lock(); + handle = rcu_dereference(dev->grab); if (handle) handle->handler->event(handle, type, code, value); else @@ -82,6 +82,7 @@ static void input_pass_event(struct input_dev *dev, if (handle->open) handle->handler->event(handle, type, code, value); + rcu_read_unlock(); } /* @@ -293,9 +294,11 @@ void input_inject_event(struct input_handle *handle, if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); + rcu_read_lock(); grab = rcu_dereference(dev->grab); if (!grab || grab == handle) input_handle_event(dev, type, code, value); + rcu_read_unlock(); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -325,11 +328,7 @@ int input_grab_device(struct input_handle *handle) } rcu_assign_pointer(dev->grab, handle); - /* - * Not using synchronize_rcu() because read-side is protected - * by a spinlock with interrupts off instead of rcu_read_lock(). - */ - synchronize_sched(); + synchronize_rcu(); out: mutex_unlock(&dev->mutex); @@ -344,7 +343,7 @@ static void __input_release_device(struct input_handle *handle) if (dev->grab == handle) { rcu_assign_pointer(dev->grab, NULL); /* Make sure input_pass_event() notices that grab is gone */ - synchronize_sched(); + synchronize_rcu(); list_for_each_entry(handle, &dev->h_list, d_node) if (handle->open && handle->handler->start) @@ -404,7 +403,7 @@ int input_open_device(struct input_handle *handle) * Make sure we are not delivering any more events * through this handle */ - synchronize_sched(); + synchronize_rcu(); } } @@ -451,11 +450,11 @@ void input_close_device(struct input_handle *handle) if (!--handle->open) { /* - * synchronize_sched() makes sure that input_pass_event() + * synchronize_rcu() makes sure that input_pass_event() * completed and that no more input events are delivered * through this handle */ - synchronize_sched(); + synchronize_rcu(); } mutex_unlock(&dev->mutex); @@ -1477,12 +1476,7 @@ int input_register_handle(struct input_handle *handle) return error; list_add_tail_rcu(&handle->d_node, &dev->h_list); mutex_unlock(&dev->mutex); - /* - * We don't use synchronize_rcu() here because we rely - * on dev->event_lock to protect read-side critical - * section in input_pass_event(). - */ - synchronize_sched(); + synchronize_rcu(); /* * Since we are supposed to be called from ->connect() @@ -1521,7 +1515,7 @@ void input_unregister_handle(struct input_handle *handle) mutex_lock(&dev->mutex); list_del_rcu(&handle->d_node); mutex_unlock(&dev->mutex); - synchronize_sched(); + synchronize_rcu(); } EXPORT_SYMBOL(input_unregister_handle); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index f306c97f556d..2b201f9aa024 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -149,8 +149,10 @@ static void joydev_event(struct input_handle *handle, event.time = jiffies_to_msecs(jiffies); + rcu_read_lock(); list_for_each_entry_rcu(client, &joydev->client_list, node) joydev_pass_event(client, &event); + rcu_read_unlock(); wake_up_interruptible(&joydev->wait); } @@ -178,12 +180,7 @@ static void joydev_attach_client(struct joydev *joydev, spin_lock(&joydev->client_lock); list_add_tail_rcu(&client->node, &joydev->client_list); spin_unlock(&joydev->client_lock); - /* - * We don't use synchronize_rcu() here because read-side - * critical section is protected by a spinlock (dev->event_lock) - * instead of rcu_read_lock(). - */ - synchronize_sched(); + synchronize_rcu(); } static void joydev_detach_client(struct joydev *joydev, @@ -192,7 +189,7 @@ static void joydev_detach_client(struct joydev *joydev, spin_lock(&joydev->client_lock); list_del_rcu(&client->node); spin_unlock(&joydev->client_lock); - synchronize_sched(); + synchronize_rcu(); } static int joydev_open_device(struct joydev *joydev) diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index cc36edbb912f..79146d6ed2ab 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -265,6 +265,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, unsigned int new_head; int wake_readers = 0; + rcu_read_lock(); list_for_each_entry_rcu(client, &mousedev->client_list, node) { /* Just acquire the lock, interrupts already disabled */ @@ -309,6 +310,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, wake_readers = 1; } } + rcu_read_unlock(); if (wake_readers) wake_up_interruptible(&mousedev->wait); @@ -499,12 +501,7 @@ static void mousedev_attach_client(struct mousedev *mousedev, spin_lock(&mousedev->client_lock); list_add_tail_rcu(&client->node, &mousedev->client_list); spin_unlock(&mousedev->client_lock); - /* - * We don't use synchronize_rcu() here because read-side - * critical section is protected by a spinlock (dev->event_lock) - * instead of rcu_read_lock(). - */ - synchronize_sched(); + synchronize_rcu(); } static void mousedev_detach_client(struct mousedev *mousedev, @@ -513,7 +510,7 @@ static void mousedev_detach_client(struct mousedev *mousedev, spin_lock(&mousedev->client_lock); list_del_rcu(&client->node); spin_unlock(&mousedev->client_lock); - synchronize_sched(); + synchronize_rcu(); } static int mousedev_release(struct inode *inode, struct file *file) -- cgit v1.2.2