Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add semaphore and user count to input_dev structure; serialize open and close calls and ensure that device's open and close methods are only called when first user opens it or last user closes it.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+32 -5
+28 -5
drivers/input/input.c
··· 219 219 220 220 int input_open_device(struct input_handle *handle) 221 221 { 222 + struct input_dev *dev = handle->dev; 223 + int err; 224 + 225 + err = down_interruptible(&dev->sem); 226 + if (err) 227 + return err; 228 + 222 229 handle->open++; 223 - if (handle->dev->open) 224 - return handle->dev->open(handle->dev); 225 - return 0; 230 + 231 + if (!dev->users++ && dev->open) 232 + err = dev->open(dev); 233 + 234 + if (err) 235 + handle->open--; 236 + 237 + up(&dev->sem); 238 + 239 + return err; 226 240 } 227 241 228 242 int input_flush_device(struct input_handle* handle, struct file* file) ··· 249 235 250 236 void input_close_device(struct input_handle *handle) 251 237 { 238 + struct input_dev *dev = handle->dev; 239 + 252 240 input_release_device(handle); 253 - if (handle->dev->close) 254 - handle->dev->close(handle->dev); 241 + 242 + down(&dev->sem); 243 + 244 + if (!--dev->users && dev->close) 245 + dev->close(dev); 255 246 handle->open--; 247 + 248 + up(&dev->sem); 256 249 } 257 250 258 251 static void input_link_handle(struct input_handle *handle) ··· 435 414 struct input_device_id *id; 436 415 437 416 set_bit(EV_SYN, dev->evbit); 417 + 418 + init_MUTEX(&dev->sem); 438 419 439 420 /* 440 421 * If delay and period are pre-set by the driver, then autorepeating
+4
include/linux/input.h
··· 859 859 int (*erase_effect)(struct input_dev *dev, int effect_id); 860 860 861 861 struct input_handle *grab; 862 + 863 + struct semaphore sem; /* serializes open and close operations */ 864 + unsigned int users; 865 + 862 866 struct device *dev; 863 867 864 868 struct list_head h_list;