Input: use full RCU API
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 13 Oct 2007 19:46:55 +0000 (15:46 -0400)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 13 Oct 2007 19:46:55 +0000 (15:46 -0400)
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 <dtor@mail.ru>
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/mousedev.c

index 27026f7..1d62c8b 100644 (file)
@@ -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)
index 3070c7a..2f2b020 100644 (file)
@@ -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);
 
index f306c97..2b201f9 100644 (file)
@@ -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)
index cc36edb..79146d6 100644 (file)
@@ -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)