diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-10-13 15:46:55 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-10-13 15:46:55 -0400 |
commit | 82ba56c273911f7eda79849cfa0fc2d2e5a3b75b (patch) | |
tree | 1b169cbda51caed72440e1ff034780df5a4dda33 | |
parent | 70093178b6eda34e4a4fb18cc4a48a9eacc01d98 (diff) |
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 <dtor@mail.ru>
-rw-r--r-- | drivers/input/evdev.c | 22 | ||||
-rw-r--r-- | drivers/input/input.c | 36 | ||||
-rw-r--r-- | drivers/input/joydev.c | 11 | ||||
-rw-r--r-- | 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, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * Pass incoming event to all connected clients. Note that we are | 66 | * Pass incoming event to all connected clients. |
67 | * caleld under a spinlock with interrupts off so we don't need | ||
68 | * to use rcu_read_lock() here. Writers will be using syncronize_sched() | ||
69 | * instead of synchrnoize_rcu(). | ||
70 | */ | 67 | */ |
71 | static void evdev_event(struct input_handle *handle, | 68 | static void evdev_event(struct input_handle *handle, |
72 | unsigned int type, unsigned int code, int value) | 69 | unsigned int type, unsigned int code, int value) |
@@ -80,6 +77,8 @@ static void evdev_event(struct input_handle *handle, | |||
80 | event.code = code; | 77 | event.code = code; |
81 | event.value = value; | 78 | event.value = value; |
82 | 79 | ||
80 | rcu_read_lock(); | ||
81 | |||
83 | client = rcu_dereference(evdev->grab); | 82 | client = rcu_dereference(evdev->grab); |
84 | if (client) | 83 | if (client) |
85 | evdev_pass_event(client, &event); | 84 | evdev_pass_event(client, &event); |
@@ -87,6 +86,8 @@ static void evdev_event(struct input_handle *handle, | |||
87 | list_for_each_entry_rcu(client, &evdev->client_list, node) | 86 | list_for_each_entry_rcu(client, &evdev->client_list, node) |
88 | evdev_pass_event(client, &event); | 87 | evdev_pass_event(client, &event); |
89 | 88 | ||
89 | rcu_read_unlock(); | ||
90 | |||
90 | wake_up_interruptible(&evdev->wait); | 91 | wake_up_interruptible(&evdev->wait); |
91 | } | 92 | } |
92 | 93 | ||
@@ -142,12 +143,7 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client) | |||
142 | return error; | 143 | return error; |
143 | 144 | ||
144 | rcu_assign_pointer(evdev->grab, client); | 145 | rcu_assign_pointer(evdev->grab, client); |
145 | /* | 146 | synchronize_rcu(); |
146 | * We don't use synchronize_rcu() here because read-side | ||
147 | * critical section is protected by a spinlock instead | ||
148 | * of rcu_read_lock(). | ||
149 | */ | ||
150 | synchronize_sched(); | ||
151 | 147 | ||
152 | return 0; | 148 | return 0; |
153 | } | 149 | } |
@@ -158,7 +154,7 @@ static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) | |||
158 | return -EINVAL; | 154 | return -EINVAL; |
159 | 155 | ||
160 | rcu_assign_pointer(evdev->grab, NULL); | 156 | rcu_assign_pointer(evdev->grab, NULL); |
161 | synchronize_sched(); | 157 | synchronize_rcu(); |
162 | input_release_device(&evdev->handle); | 158 | input_release_device(&evdev->handle); |
163 | 159 | ||
164 | return 0; | 160 | return 0; |
@@ -170,7 +166,7 @@ static void evdev_attach_client(struct evdev *evdev, | |||
170 | spin_lock(&evdev->client_lock); | 166 | spin_lock(&evdev->client_lock); |
171 | list_add_tail_rcu(&client->node, &evdev->client_list); | 167 | list_add_tail_rcu(&client->node, &evdev->client_list); |
172 | spin_unlock(&evdev->client_lock); | 168 | spin_unlock(&evdev->client_lock); |
173 | synchronize_sched(); | 169 | synchronize_rcu(); |
174 | } | 170 | } |
175 | 171 | ||
176 | static void evdev_detach_client(struct evdev *evdev, | 172 | static void evdev_detach_client(struct evdev *evdev, |
@@ -179,7 +175,7 @@ static void evdev_detach_client(struct evdev *evdev, | |||
179 | spin_lock(&evdev->client_lock); | 175 | spin_lock(&evdev->client_lock); |
180 | list_del_rcu(&client->node); | 176 | list_del_rcu(&client->node); |
181 | spin_unlock(&evdev->client_lock); | 177 | spin_unlock(&evdev->client_lock); |
182 | synchronize_sched(); | 178 | synchronize_rcu(); |
183 | } | 179 | } |
184 | 180 | ||
185 | static int evdev_open_device(struct evdev *evdev) | 181 | 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) | |||
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Pass event through all open handles. This function is called with | 67 | * Pass event through all open handles. This function is called with |
68 | * dev->event_lock held and interrupts disabled. Because of that we | 68 | * dev->event_lock held and interrupts disabled. |
69 | * do not need to use rcu_read_lock() here although we are using RCU | ||
70 | * to access handle list. Note that because of that write-side uses | ||
71 | * synchronize_sched() instead of synchronize_ru(). | ||
72 | */ | 69 | */ |
73 | static void input_pass_event(struct input_dev *dev, | 70 | static void input_pass_event(struct input_dev *dev, |
74 | unsigned int type, unsigned int code, int value) | 71 | unsigned int type, unsigned int code, int value) |
75 | { | 72 | { |
76 | struct input_handle *handle = rcu_dereference(dev->grab); | 73 | struct input_handle *handle; |
74 | |||
75 | rcu_read_lock(); | ||
77 | 76 | ||
77 | handle = rcu_dereference(dev->grab); | ||
78 | if (handle) | 78 | if (handle) |
79 | handle->handler->event(handle, type, code, value); | 79 | handle->handler->event(handle, type, code, value); |
80 | else | 80 | else |
@@ -82,6 +82,7 @@ static void input_pass_event(struct input_dev *dev, | |||
82 | if (handle->open) | 82 | if (handle->open) |
83 | handle->handler->event(handle, | 83 | handle->handler->event(handle, |
84 | type, code, value); | 84 | type, code, value); |
85 | rcu_read_unlock(); | ||
85 | } | 86 | } |
86 | 87 | ||
87 | /* | 88 | /* |
@@ -293,9 +294,11 @@ void input_inject_event(struct input_handle *handle, | |||
293 | if (is_event_supported(type, dev->evbit, EV_MAX)) { | 294 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
294 | spin_lock_irqsave(&dev->event_lock, flags); | 295 | spin_lock_irqsave(&dev->event_lock, flags); |
295 | 296 | ||
297 | rcu_read_lock(); | ||
296 | grab = rcu_dereference(dev->grab); | 298 | grab = rcu_dereference(dev->grab); |
297 | if (!grab || grab == handle) | 299 | if (!grab || grab == handle) |
298 | input_handle_event(dev, type, code, value); | 300 | input_handle_event(dev, type, code, value); |
301 | rcu_read_unlock(); | ||
299 | 302 | ||
300 | spin_unlock_irqrestore(&dev->event_lock, flags); | 303 | spin_unlock_irqrestore(&dev->event_lock, flags); |
301 | } | 304 | } |
@@ -325,11 +328,7 @@ int input_grab_device(struct input_handle *handle) | |||
325 | } | 328 | } |
326 | 329 | ||
327 | rcu_assign_pointer(dev->grab, handle); | 330 | rcu_assign_pointer(dev->grab, handle); |
328 | /* | 331 | synchronize_rcu(); |
329 | * Not using synchronize_rcu() because read-side is protected | ||
330 | * by a spinlock with interrupts off instead of rcu_read_lock(). | ||
331 | */ | ||
332 | synchronize_sched(); | ||
333 | 332 | ||
334 | out: | 333 | out: |
335 | mutex_unlock(&dev->mutex); | 334 | mutex_unlock(&dev->mutex); |
@@ -344,7 +343,7 @@ static void __input_release_device(struct input_handle *handle) | |||
344 | if (dev->grab == handle) { | 343 | if (dev->grab == handle) { |
345 | rcu_assign_pointer(dev->grab, NULL); | 344 | rcu_assign_pointer(dev->grab, NULL); |
346 | /* Make sure input_pass_event() notices that grab is gone */ | 345 | /* Make sure input_pass_event() notices that grab is gone */ |
347 | synchronize_sched(); | 346 | synchronize_rcu(); |
348 | 347 | ||
349 | list_for_each_entry(handle, &dev->h_list, d_node) | 348 | list_for_each_entry(handle, &dev->h_list, d_node) |
350 | if (handle->open && handle->handler->start) | 349 | if (handle->open && handle->handler->start) |
@@ -404,7 +403,7 @@ int input_open_device(struct input_handle *handle) | |||
404 | * Make sure we are not delivering any more events | 403 | * Make sure we are not delivering any more events |
405 | * through this handle | 404 | * through this handle |
406 | */ | 405 | */ |
407 | synchronize_sched(); | 406 | synchronize_rcu(); |
408 | } | 407 | } |
409 | } | 408 | } |
410 | 409 | ||
@@ -451,11 +450,11 @@ void input_close_device(struct input_handle *handle) | |||
451 | 450 | ||
452 | if (!--handle->open) { | 451 | if (!--handle->open) { |
453 | /* | 452 | /* |
454 | * synchronize_sched() makes sure that input_pass_event() | 453 | * synchronize_rcu() makes sure that input_pass_event() |
455 | * completed and that no more input events are delivered | 454 | * completed and that no more input events are delivered |
456 | * through this handle | 455 | * through this handle |
457 | */ | 456 | */ |
458 | synchronize_sched(); | 457 | synchronize_rcu(); |
459 | } | 458 | } |
460 | 459 | ||
461 | mutex_unlock(&dev->mutex); | 460 | mutex_unlock(&dev->mutex); |
@@ -1477,12 +1476,7 @@ int input_register_handle(struct input_handle *handle) | |||
1477 | return error; | 1476 | return error; |
1478 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | 1477 | list_add_tail_rcu(&handle->d_node, &dev->h_list); |
1479 | mutex_unlock(&dev->mutex); | 1478 | mutex_unlock(&dev->mutex); |
1480 | /* | 1479 | synchronize_rcu(); |
1481 | * We don't use synchronize_rcu() here because we rely | ||
1482 | * on dev->event_lock to protect read-side critical | ||
1483 | * section in input_pass_event(). | ||
1484 | */ | ||
1485 | synchronize_sched(); | ||
1486 | 1480 | ||
1487 | /* | 1481 | /* |
1488 | * Since we are supposed to be called from ->connect() | 1482 | * Since we are supposed to be called from ->connect() |
@@ -1521,7 +1515,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
1521 | mutex_lock(&dev->mutex); | 1515 | mutex_lock(&dev->mutex); |
1522 | list_del_rcu(&handle->d_node); | 1516 | list_del_rcu(&handle->d_node); |
1523 | mutex_unlock(&dev->mutex); | 1517 | mutex_unlock(&dev->mutex); |
1524 | synchronize_sched(); | 1518 | synchronize_rcu(); |
1525 | } | 1519 | } |
1526 | EXPORT_SYMBOL(input_unregister_handle); | 1520 | EXPORT_SYMBOL(input_unregister_handle); |
1527 | 1521 | ||
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, | |||
149 | 149 | ||
150 | event.time = jiffies_to_msecs(jiffies); | 150 | event.time = jiffies_to_msecs(jiffies); |
151 | 151 | ||
152 | rcu_read_lock(); | ||
152 | list_for_each_entry_rcu(client, &joydev->client_list, node) | 153 | list_for_each_entry_rcu(client, &joydev->client_list, node) |
153 | joydev_pass_event(client, &event); | 154 | joydev_pass_event(client, &event); |
155 | rcu_read_unlock(); | ||
154 | 156 | ||
155 | wake_up_interruptible(&joydev->wait); | 157 | wake_up_interruptible(&joydev->wait); |
156 | } | 158 | } |
@@ -178,12 +180,7 @@ static void joydev_attach_client(struct joydev *joydev, | |||
178 | spin_lock(&joydev->client_lock); | 180 | spin_lock(&joydev->client_lock); |
179 | list_add_tail_rcu(&client->node, &joydev->client_list); | 181 | list_add_tail_rcu(&client->node, &joydev->client_list); |
180 | spin_unlock(&joydev->client_lock); | 182 | spin_unlock(&joydev->client_lock); |
181 | /* | 183 | synchronize_rcu(); |
182 | * We don't use synchronize_rcu() here because read-side | ||
183 | * critical section is protected by a spinlock (dev->event_lock) | ||
184 | * instead of rcu_read_lock(). | ||
185 | */ | ||
186 | synchronize_sched(); | ||
187 | } | 184 | } |
188 | 185 | ||
189 | static void joydev_detach_client(struct joydev *joydev, | 186 | static void joydev_detach_client(struct joydev *joydev, |
@@ -192,7 +189,7 @@ static void joydev_detach_client(struct joydev *joydev, | |||
192 | spin_lock(&joydev->client_lock); | 189 | spin_lock(&joydev->client_lock); |
193 | list_del_rcu(&client->node); | 190 | list_del_rcu(&client->node); |
194 | spin_unlock(&joydev->client_lock); | 191 | spin_unlock(&joydev->client_lock); |
195 | synchronize_sched(); | 192 | synchronize_rcu(); |
196 | } | 193 | } |
197 | 194 | ||
198 | static int joydev_open_device(struct joydev *joydev) | 195 | 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, | |||
265 | unsigned int new_head; | 265 | unsigned int new_head; |
266 | int wake_readers = 0; | 266 | int wake_readers = 0; |
267 | 267 | ||
268 | rcu_read_lock(); | ||
268 | list_for_each_entry_rcu(client, &mousedev->client_list, node) { | 269 | list_for_each_entry_rcu(client, &mousedev->client_list, node) { |
269 | 270 | ||
270 | /* Just acquire the lock, interrupts already disabled */ | 271 | /* Just acquire the lock, interrupts already disabled */ |
@@ -309,6 +310,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, | |||
309 | wake_readers = 1; | 310 | wake_readers = 1; |
310 | } | 311 | } |
311 | } | 312 | } |
313 | rcu_read_unlock(); | ||
312 | 314 | ||
313 | if (wake_readers) | 315 | if (wake_readers) |
314 | wake_up_interruptible(&mousedev->wait); | 316 | wake_up_interruptible(&mousedev->wait); |
@@ -499,12 +501,7 @@ static void mousedev_attach_client(struct mousedev *mousedev, | |||
499 | spin_lock(&mousedev->client_lock); | 501 | spin_lock(&mousedev->client_lock); |
500 | list_add_tail_rcu(&client->node, &mousedev->client_list); | 502 | list_add_tail_rcu(&client->node, &mousedev->client_list); |
501 | spin_unlock(&mousedev->client_lock); | 503 | spin_unlock(&mousedev->client_lock); |
502 | /* | 504 | synchronize_rcu(); |
503 | * We don't use synchronize_rcu() here because read-side | ||
504 | * critical section is protected by a spinlock (dev->event_lock) | ||
505 | * instead of rcu_read_lock(). | ||
506 | */ | ||
507 | synchronize_sched(); | ||
508 | } | 505 | } |
509 | 506 | ||
510 | static void mousedev_detach_client(struct mousedev *mousedev, | 507 | static void mousedev_detach_client(struct mousedev *mousedev, |
@@ -513,7 +510,7 @@ static void mousedev_detach_client(struct mousedev *mousedev, | |||
513 | spin_lock(&mousedev->client_lock); | 510 | spin_lock(&mousedev->client_lock); |
514 | list_del_rcu(&client->node); | 511 | list_del_rcu(&client->node); |
515 | spin_unlock(&mousedev->client_lock); | 512 | spin_unlock(&mousedev->client_lock); |
516 | synchronize_sched(); | 513 | synchronize_rcu(); |
517 | } | 514 | } |
518 | 515 | ||
519 | static int mousedev_release(struct inode *inode, struct file *file) | 516 | static int mousedev_release(struct inode *inode, struct file *file) |