From 6704e986a0022ac3300342b113461a2d6256c5ea Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 12 Aug 2020 10:43:48 +0200 Subject: [PATCH] backends/native: Surround device state queries/updates with RW lock Wrap all keyboard state updates, and all pointer/stylus/touch cursor position with a write lock, and ::query_state() (The only entrypoint to this state from other threads) with a read lock. The principle is that query_state may be called from different threads (UI so far, but maybe KMS too in the future), while the input thread may (or may not) be updating it. This state is fetched "atomically" (eg. x/y will be consistently old or new, if the input thread were updating it at the same time). There's other places deep in backends/native that read this state, they all will run in the input thread, so they count as "other readers" to the other thread. Those changes are already mutually exclusive with updates, so they don't explicitly need the RW lock. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403 --- .../native/meta-input-device-native.c | 4 ++ src/backends/native/meta-seat-impl.c | 55 +++++++++++++++++-- src/backends/native/meta-seat-impl.h | 1 + 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/backends/native/meta-input-device-native.c b/src/backends/native/meta-input-device-native.c index ef0972712..8400004fb 100644 --- a/src/backends/native/meta-input-device-native.c +++ b/src/backends/native/meta-input-device-native.c @@ -438,6 +438,8 @@ update_internal_xkb_state (MetaInputDeviceNative *device, xkb_mod_mask_t group_mods; struct xkb_state *xkb_state; + g_rw_lock_writer_lock (&seat_impl->state_lock); + xkb_state = meta_seat_impl_get_xkb_state (seat_impl); depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED); @@ -460,6 +462,8 @@ update_internal_xkb_state (MetaInputDeviceNative *device, locked_mods, 0, 0, group_mods); notify_stickykeys_mask (device); + + g_rw_lock_writer_unlock (&seat_impl->state_lock); } static void diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c index c1b27ef33..0afebf48d 100644 --- a/src/backends/native/meta-seat-impl.c +++ b/src/backends/native/meta-seat-impl.c @@ -437,6 +437,8 @@ new_absolute_motion_event (MetaSeatImpl *seat, clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); + g_rw_lock_writer_lock (&seat->state_lock); + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) { MetaInputDeviceNative *device_evdev = @@ -460,6 +462,8 @@ new_absolute_motion_event (MetaSeatImpl *seat, seat->pointer_y = y; } + g_rw_lock_writer_unlock (&seat->state_lock); + return event; } @@ -2010,10 +2014,14 @@ process_device_event (MetaSeatImpl *seat, y = libinput_event_touch_get_y_transformed (touch_event, stage_height); + g_rw_lock_writer_lock (&seat->state_lock); + touch_state = meta_seat_impl_acquire_touch_state (seat, seat_slot); touch_state->coords.x = x; touch_state->coords.y = y; + g_rw_lock_writer_unlock (&seat->state_lock); + meta_seat_impl_notify_touch_event (seat, device, CLUTTER_TOUCH_BEGIN, time_us, @@ -2047,7 +2055,10 @@ process_device_event (MetaSeatImpl *seat, touch_state->seat_slot, touch_state->coords.x, touch_state->coords.y); + + g_rw_lock_writer_lock (&seat->state_lock); meta_seat_impl_release_touch_state (seat, seat_slot); + g_rw_lock_writer_unlock (&seat->state_lock); break; } @@ -2076,13 +2087,18 @@ process_device_event (MetaSeatImpl *seat, y = libinput_event_touch_get_y_transformed (touch_event, stage_height); + g_rw_lock_writer_lock (&seat->state_lock); touch_state = meta_seat_impl_lookup_touch_state (seat, seat_slot); + if (touch_state) + { + touch_state->coords.x = x; + touch_state->coords.y = y; + } + g_rw_lock_writer_unlock (&seat->state_lock); + if (!touch_state) break; - touch_state->coords.x = x; - touch_state->coords.y = y; - meta_seat_impl_notify_touch_event (seat, device, CLUTTER_TOUCH_UPDATE, time_us, @@ -2443,6 +2459,8 @@ meta_seat_impl_constructed (GObject *object) struct udev *udev; struct xkb_keymap *xkb_keymap; + g_rw_lock_writer_lock (&seat->state_lock); + device = meta_input_device_native_new_virtual ( seat, CLUTTER_POINTER_DEVICE, CLUTTER_INPUT_MODE_MASTER); @@ -2504,6 +2522,8 @@ meta_seat_impl_constructed (GObject *object) xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); } + g_rw_lock_writer_unlock (&seat->state_lock); + seat->has_touchscreen = has_touchscreen (seat); update_touch_mode (seat); @@ -2599,6 +2619,8 @@ meta_seat_impl_finalize (GObject *object) g_free (seat->seat_id); + g_rw_lock_clear (&seat->state_lock); + G_OBJECT_CLASS (meta_seat_impl_parent_class)->finalize (object); } @@ -2661,6 +2683,9 @@ meta_seat_impl_query_state (MetaSeatImpl *seat, { MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); MetaSeatImpl *seat_native = META_SEAT_IMPL (seat); + gboolean retval = FALSE; + + g_rw_lock_reader_lock (&seat->state_lock); if (sequence) { @@ -2670,7 +2695,7 @@ meta_seat_impl_query_state (MetaSeatImpl *seat, slot = meta_event_native_sequence_get_slot (sequence); touch_state = meta_seat_impl_lookup_touch_state (seat_native, slot); if (!touch_state) - return FALSE; + goto out; if (coords) { @@ -2681,7 +2706,7 @@ meta_seat_impl_query_state (MetaSeatImpl *seat, if (modifiers) *modifiers = meta_xkb_translate_modifiers (seat_native->xkb, 0); - return TRUE; + retval = TRUE; } else { @@ -2697,8 +2722,12 @@ meta_seat_impl_query_state (MetaSeatImpl *seat, seat_native->button_state); } - return TRUE; + retval = TRUE; } + + out: + g_rw_lock_reader_unlock (&seat->state_lock); + return retval; } static void @@ -2769,6 +2798,8 @@ meta_seat_impl_class_init (MetaSeatImplClass *klass) static void meta_seat_impl_init (MetaSeatImpl *seat) { + g_rw_lock_init (&seat->state_lock); + seat->device_id_next = INITIAL_DEVICE_ID; seat->repeat = TRUE; @@ -2810,6 +2841,8 @@ meta_seat_impl_update_xkb_state (MetaSeatImpl *seat) xkb_mod_mask_t locked_mods; struct xkb_keymap *xkb_keymap; + g_rw_lock_writer_lock (&seat->state_lock); + xkb_keymap = meta_keymap_native_get_keyboard_map (seat->keymap); latched_mods = xkb_state_serialize_mods (seat->xkb, @@ -2830,6 +2863,8 @@ meta_seat_impl_update_xkb_state (MetaSeatImpl *seat) seat->scroll_lock_led = xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); meta_seat_impl_sync_leds (seat); + + g_rw_lock_writer_unlock (&seat->state_lock); } gint @@ -2990,6 +3025,8 @@ meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat, g_return_if_fail (META_IS_SEAT_IMPL (seat)); + g_rw_lock_writer_lock (&seat->state_lock); + state = seat->xkb; depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED); @@ -2999,6 +3036,8 @@ meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat, xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx); seat->layout_idx = idx; + + g_rw_lock_writer_unlock (&seat->state_lock); } /** @@ -3031,6 +3070,8 @@ meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat, g_return_if_fail (META_IS_SEAT_IMPL (seat)); + g_rw_lock_writer_lock (&seat->state_lock); + keymap = seat->keymap; xkb_keymap = meta_keymap_native_get_keyboard_map (keymap); @@ -3054,6 +3095,8 @@ meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat, group_mods); meta_seat_impl_sync_leds (seat); + + g_rw_lock_writer_unlock (&seat->state_lock); } /** diff --git a/src/backends/native/meta-seat-impl.h b/src/backends/native/meta-seat-impl.h index 1b20e80c2..8cc5cae15 100644 --- a/src/backends/native/meta-seat-impl.h +++ b/src/backends/native/meta-seat-impl.h @@ -59,6 +59,7 @@ struct _MetaSeatImpl MetaEventSource *event_source; struct libinput *libinput; struct libinput_seat *libinput_seat; + GRWLock state_lock; GSList *devices;