From 3c06dae07c6c51e77cee42ba9fbb71d054f08ef7 Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Wed, 16 Jun 2021 15:03:23 +0900 Subject: [PATCH] e_hwc_windows: Fix deadlock when e_hwc_window is freed after tbm_surface of E_Hwc_Window_Update is referenced, it is possible that unreferenced api of tbm_surface (tbm_surface_internal_unref) is called when e_hwc_window is freed. e_hwc_windows add rendererd_windows list to user_data of tbm_surface of target_window rendered_windows list has reference of e_hwc_window and unreference of e_hwc_window can be called when rendered_windows list is freed in user_data delete callback of tbm_surface. but it cause deadlock problem when tbm_surface_internal_unref is called in callback of tbm_surface because libtbm doesn't allow that tbm_surface api is called in callback of tbm_surface. so e_hwc_windows doesn't use user_data of tbm_surface for rendered_buffer and rendered_windows list. they are added to member of E_Hwc_Window_Comp_Info. E_Hwc_Window_Comp_Info isn't freed in user_data deleted callback. Change-Id: I40deba667bbfb7bbfba2807830e823faa90c07b4 --- src/bin/e_hwc_windows.c | 179 ++++++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/src/bin/e_hwc_windows.c b/src/bin/e_hwc_windows.c index 119ac2d..380557a 100644 --- a/src/bin/e_hwc_windows.c +++ b/src/bin/e_hwc_windows.c @@ -64,15 +64,15 @@ struct _E_Hwc_Windows_Comp_Info Eina_Bool skip; E_Egl_Sync *release_fence; Eina_List *pending_update_list; + + Eina_List *rendered_windows; + Eina_List *rendered_buffers; }; static Eina_Bool ehws_trace = EINA_FALSE; static Eina_Bool ehws_dump_enable = EINA_FALSE; -static uint64_t ehws_rendered_windows_key; -#define EHWS_RENDERED_WINDOWS_KEY (unsigned long)(&ehws_rendered_windows_key) -static uint64_t ehws_rendered_buffers_key; -#define EHWS_RENDERED_BUFFERS_KEY (unsigned long)(&ehws_rendered_buffers_key) +static int E_EVENT_HWC_WINDOWS_COMP_INFO_FREE = -1; static uint64_t ehws_comp_buffer_info_key; #define EHWS_BUFFER_COMP_INFO_KEY (unsigned long)(&ehws_comp_buffer_info_key) @@ -194,18 +194,86 @@ _e_hwc_windows_aligned_width_get(tbm_surface_h tsurface) } static void -_e_hwc_windows_comp_info_free(void *data) +_e_hwc_windows_comp_info_rendered_buffers_set(E_Hwc_Windows_Comp_Info *comp_info, + Eina_List *rendered_buffers) +{ + E_Comp_Wl_Buffer_Ref *buffer_ref; + + EINA_SAFETY_ON_NULL_RETURN(comp_info); + + if (comp_info->rendered_buffers == rendered_buffers) + return; + + if (comp_info->rendered_buffers) + { + if (eina_list_count(comp_info->rendered_buffers)) + { + EINA_LIST_FREE(comp_info->rendered_buffers, buffer_ref) + { + e_comp_wl_buffer_reference(buffer_ref, NULL); + E_FREE(buffer_ref); + } + } + } + + comp_info->rendered_buffers = rendered_buffers; +} + +static void +_e_hwc_windows_comp_info_rendered_windows_set(E_Hwc_Windows_Comp_Info *comp_info, + Eina_List *rendered_windows) +{ + E_Hwc_Window *hwc_window = NULL; + + EINA_SAFETY_ON_NULL_RETURN(comp_info); + + if (comp_info->rendered_windows == rendered_windows) + return; + + if (comp_info->rendered_windows) + { + if (eina_list_count(comp_info->rendered_windows)) + { + EINA_LIST_FREE(comp_info->rendered_windows, hwc_window) + e_hwc_window_unref(hwc_window); + } + } + + comp_info->rendered_windows = rendered_windows; +} + +static void +_e_hwc_windows_comp_info_free(void *data EINA_UNUSED, void *event) { E_Hwc_Windows_Comp_Info *comp_info; + E_Hwc_Window_Update_Data *update; - comp_info = (E_Hwc_Windows_Comp_Info *)data; + comp_info = (E_Hwc_Windows_Comp_Info *)event; if (!comp_info) return; + EINA_LIST_FREE(comp_info->pending_update_list, update) + e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update); + + _e_hwc_windows_comp_info_rendered_windows_set(comp_info, NULL); + _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL); + e_presentation_time_container_finish(&comp_info->presentation_container); E_FREE(comp_info); } +static void +_e_hwc_windows_comp_info_cb_tbm_surface_destroy(void *data) +{ + E_Hwc_Windows_Comp_Info *comp_info; + + comp_info = (E_Hwc_Windows_Comp_Info *)data; + if (!comp_info) return; + + ecore_event_add(E_EVENT_HWC_WINDOWS_COMP_INFO_FREE, comp_info, + _e_hwc_windows_comp_info_free, NULL); +} + static E_Hwc_Windows_Comp_Info * _e_hwc_windows_comp_info_get(tbm_surface_h tbm_surface) { @@ -222,7 +290,7 @@ _e_hwc_windows_comp_info_get(tbm_surface_h tbm_surface) e_presentation_time_container_init(&comp_info->presentation_container); tbm_surface_internal_add_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY, - _e_hwc_windows_comp_info_free); + _e_hwc_windows_comp_info_cb_tbm_surface_destroy); tbm_surface_internal_set_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY, comp_info); @@ -469,14 +537,14 @@ _e_hwc_windows_offscreen_commit(E_Hwc *hwc) static Eina_List * _e_hwc_windows_target_window_rendered_windows_get(tbm_surface_h target_tsurface) { - Eina_List *rendered_windows = NULL; + E_Hwc_Windows_Comp_Info *comp_info; if (!target_tsurface) return NULL; - tbm_surface_internal_get_user_data(target_tsurface, EHWS_RENDERED_WINDOWS_KEY, - (void**)&rendered_windows); + comp_info = _e_hwc_windows_comp_info_get(target_tsurface); + if (!comp_info) return NULL; - return rendered_windows; + return comp_info->rendered_windows; } static void @@ -1028,37 +1096,6 @@ _e_hwc_windows_visible_windows_list_get(E_Hwc *hwc) return windows_list; } -static void -_e_hwc_windows_rendered_buffers_free(void *data) -{ - Eina_List *rendered_buffers = (Eina_List *)data; - E_Comp_Wl_Buffer_Ref *buffer_ref; - - if (!rendered_buffers) return; - - if (eina_list_count(rendered_buffers)) - { - EINA_LIST_FREE(rendered_buffers, buffer_ref) - { - e_comp_wl_buffer_reference(buffer_ref, NULL); - E_FREE(buffer_ref); - } - } -} - -static void -_e_hwc_windows_rendered_windows_free(void *data) -{ - Eina_List *rendered_windows = (Eina_List *)data; - E_Hwc_Window *hwc_window = NULL; - - if (eina_list_count(rendered_windows)) - { - EINA_LIST_FREE(rendered_windows, hwc_window) - e_hwc_window_unref(hwc_window); - } -} - static Eina_Bool _e_hwc_windows_pending_update_data_enqueue(E_Hwc_Windows_Comp_Info *comp_info) { @@ -1152,13 +1189,6 @@ _e_hwc_windows_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_ EHWSTRACE("{%s} dequeue ts:%p", NULL, target_hwc_window->hwc, "@TARGET WINDOW@", tsurface); - tbm_surface_internal_add_user_data(tsurface, - EHWS_RENDERED_BUFFERS_KEY, - _e_hwc_windows_rendered_buffers_free); - - tbm_surface_internal_add_user_data(tsurface, - EHWS_RENDERED_WINDOWS_KEY, - _e_hwc_windows_rendered_windows_free); target_hwc_window->dequeued_tsurface = tsurface; if (!eina_list_data_find(target_hwc_window->rendering_tsurfaces, tsurface)) @@ -1177,14 +1207,15 @@ _e_hwc_windows_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_ if (trace == TBM_SURFACE_QUEUE_TRACE_ACQUIRE) { - tbm_surface_internal_set_user_data(tsurface, EHWS_RENDERED_BUFFERS_KEY, NULL); - target_hwc_window->rendering_tsurfaces = eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface); comp_info = _e_hwc_windows_comp_info_get(tsurface); if (comp_info) - _e_hwc_windows_pending_update_data_enqueue(comp_info); + { + _e_hwc_windows_pending_update_data_enqueue(comp_info); + _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL); + } } /* tsurface has been released at the queue */ @@ -1192,16 +1223,16 @@ _e_hwc_windows_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_ { EHWSTRACE("{%s} release ts:%p", NULL, target_hwc_window->hwc, "@TARGET WINDOW@", tsurface); - tbm_surface_internal_delete_user_data(tsurface, EHWS_RENDERED_BUFFERS_KEY); - - tbm_surface_internal_delete_user_data(tsurface, EHWS_RENDERED_WINDOWS_KEY); - target_hwc_window->rendering_tsurfaces = eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface); comp_info = _e_hwc_windows_comp_info_get(tsurface); if (comp_info) - comp_info->skip = EINA_FALSE; + { + comp_info->skip = EINA_FALSE; + _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL); + _e_hwc_windows_comp_info_rendered_windows_set(comp_info, NULL); + } } } @@ -1229,6 +1260,7 @@ _e_hwc_windows_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd E_Hwc_Window *hwc_window = NULL; Eina_List *acquirable_buffers = NULL; E_Hwc_Window_Queue_Buffer *queue_buffer = NULL; + E_Hwc_Windows_Comp_Info *comp_info; fd = ecore_main_fd_handler_fd_get(fd_handler); if (fd < 0) return ECORE_CALLBACK_RENEW; @@ -1248,9 +1280,10 @@ _e_hwc_windows_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd { if (!queue_buffer->tsurface) continue; - tbm_surface_internal_set_user_data(queue_buffer->tsurface, - EHWS_RENDERED_BUFFERS_KEY, - NULL); + comp_info = _e_hwc_windows_comp_info_get(queue_buffer->tsurface); + if (!comp_info) continue; + + _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL); } return ECORE_CALLBACK_RENEW; @@ -1431,6 +1464,15 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE return; } + comp_info = _e_hwc_windows_comp_info_get(target_hwc_window->dequeued_tsurface); + if (!comp_info) + { + EHWSERR("fail to get comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface); + return; + } + + _e_hwc_windows_pending_update_data_dequeue(target_hwc_window, comp_info); + visible_windows = _e_hwc_windows_visible_windows_list_get(target_hwc_window->hwc); EINA_LIST_FREE(visible_windows, hwc_window) { @@ -1440,12 +1482,6 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE e_hwc_windows_rendered_window_add(hwc_window); } - comp_info = _e_hwc_windows_comp_info_get(target_hwc_window->dequeued_tsurface); - if (comp_info) - _e_hwc_windows_pending_update_data_dequeue(target_hwc_window, comp_info); - else - EHWSERR("fail to get comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface); - fence_enabled = e_hwc_windows_fence_enabled_get(target_hwc_window->hwc); /* all ecs have been composited so we can attach a list of composited e_hwc_windows to the surface @@ -1463,7 +1499,7 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE if (!ec) continue; cdata = e_client_cdata_get(ec); - if (comp_info && cdata) + if (cdata) e_presentation_time_container_feedback_merge(&comp_info->presentation_container, &cdata->presentation_container); @@ -1502,13 +1538,8 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE rendered_buffers = eina_list_append(rendered_buffers, buffer_ref); } - tbm_surface_internal_set_user_data(target_hwc_window->dequeued_tsurface, - EHWS_RENDERED_BUFFERS_KEY, - rendered_buffers); - - tbm_surface_internal_set_user_data(target_hwc_window->dequeued_tsurface, - EHWS_RENDERED_WINDOWS_KEY, - rendered_windows); + _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, rendered_buffers); + _e_hwc_windows_comp_info_rendered_windows_set(comp_info, rendered_windows); eina_list_free(target_hwc_window->rendered_windows); target_hwc_window->rendered_windows = NULL; -- 2.7.4