From 19b30808589a85e6e41fcad17b0ade5020991c2c Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 22 Aug 2017 11:50:07 +0900 Subject: [PATCH] tpl_wayland_egl_thread: Modified the procedure of finalizing disp_source. - Added twe_wl_disp_del_source, an event gsource to delete twe_wl_disp_source. - When delete twe_wl_disp_source, calling _twe_thread_wl_disp_del_trigger() wakes up twe_wl_disp_del_source and removes twe_wl_disp_source in the thread. Change-Id: I6a9ab462e8ab464663ee60db1548d822c50d7f00 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 168 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 158 insertions(+), 10 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 6f5f608..f16063d 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -21,10 +21,11 @@ static int buffer_info_key; #define CLIENT_QUEUE_SIZE 3 -typedef struct _twe_wl_disp_source twe_wl_disp_source; -typedef struct _twe_wl_surf_source twe_wl_surf_source; -typedef struct _twe_wl_buffer_info twe_wl_buffer_info; -typedef struct _twe_tdm_source twe_tdm_source; +typedef struct _twe_wl_disp_source twe_wl_disp_source; +typedef struct _twe_wl_surf_source twe_wl_surf_source; +typedef struct _twe_wl_buffer_info twe_wl_buffer_info; +typedef struct _twe_tdm_source twe_tdm_source; +typedef struct _twe_wl_disp_del_source twe_wl_disp_del_source; struct _twe_thread_context { int ref_cnt; @@ -55,11 +56,19 @@ struct _twe_wl_disp_source { struct wayland_tbm_client *wl_tbm_client; struct tizen_surface_shm *tss; /* used for surface buffer_flush */ tpl_bool_t prepared; + twe_wl_disp_del_source *disp_del_source; twe_thread *thread; tpl_object_t obj; /* TODO : surface list */ }; +struct _twe_wl_disp_del_source { + GSource gsource; + gpointer tag; + int event_fd; + twe_wl_disp_source* disp_source; +}; + struct _twe_wl_surf_source { GSource gsource; gpointer tag; @@ -400,9 +409,12 @@ _twe_thread_wl_disp_finalize(GSource *source) twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; TPL_OBJECT_LOCK(&disp_source->obj); + /* If disp_source is in prepared state, cancel it */ - if (disp_source->prepared) + if (disp_source->prepared) { wl_display_cancel_read(disp_source->disp); + disp_source->prepared = TPL_FALSE; + } if (wl_display_dispatch_queue_pending(disp_source->disp, disp_source->ev_queue) == -1) { @@ -553,6 +565,135 @@ _twe_display_shm_fini(twe_wl_disp_source *disp_source) } } +static void +_twe_thread_wl_disp_del(twe_wl_disp_source *disp_source) +{ + if (g_source_is_destroyed(&disp_source->gsource)) { + TPL_ERR("disp_source(%p) already destroyed.", disp_source); + return; + } + + g_source_remove_poll(&disp_source->gsource, &disp_source->gfd); + g_source_destroy(&disp_source->gsource); + g_source_unref(&disp_source->gsource); + + TPL_LOG_T("WL_EGL", "[DEL] twe_display(%p) wl_display(%p)", + disp_source, disp_source->disp); +} + +static gboolean +_twe_thread_wl_disp_del_dispatch(GSource *source, GSourceFunc cb, gpointer data) +{ + twe_wl_disp_del_source *disp_del_source = (twe_wl_disp_del_source *)source; + GIOCondition cond; + + if (g_source_is_destroyed(source)) { + TPL_ERR("disp_del source(%p) already destroyed.", source); + return G_SOURCE_REMOVE; + } + + cond = g_source_query_unix_fd(source, disp_del_source->tag); + + if (cond & G_IO_IN) { + ssize_t s; + uint64_t u; + + s = read(disp_del_source->event_fd, &u, sizeof(uint64_t)); + if (s != sizeof(uint64_t)) + TPL_ERR("Failed to read from event_fd(%d)", + disp_del_source->event_fd); + + _twe_thread_wl_disp_del(disp_del_source->disp_source); + } + + return G_SOURCE_CONTINUE; +} + +static void +_twe_thread_wl_disp_del_finalize(GSource *source) +{ + twe_wl_disp_del_source *disp_del_source = + (twe_wl_disp_del_source *)source; + + TPL_LOG_T("WL_EGL", "gsource(%p) event_fd(%d)", + source, disp_del_source->event_fd); + + g_source_remove_unix_fd(source, disp_del_source->tag); + + close(disp_del_source->event_fd); + + disp_del_source->tag = NULL; + disp_del_source->event_fd = -1; + + return; +} + +static GSourceFuncs _twe_wl_disp_del_funcs = { + .prepare = NULL, + .check = NULL, + .dispatch = _twe_thread_wl_disp_del_dispatch, + .finalize = _twe_thread_wl_disp_del_finalize, +}; + +static void +_twe_thread_wl_disp_del_trigger(twe_wl_disp_source *disp_source) +{ + twe_wl_disp_del_source *disp_del_source = disp_source->disp_del_source; + uint64_t value = 1; + int ret; + + ret = write(disp_del_source->event_fd, &value, sizeof(uint64_t)); + if (ret == -1) { + TPL_ERR("failed to send acquirable event. twe_wl_disp_del_source(%p)", + disp_del_source); + return; + } +} + +twe_wl_disp_del_source * +_twe_display_del_source_init(twe_thread *thread, + twe_wl_disp_source *disp_source) +{ + twe_thread_context *ctx = thread->ctx; + twe_wl_disp_del_source *source = NULL; + + if (!disp_source) { + TPL_ERR("Invalid parameter. disp_source is NULL"); + return NULL; + } + + source = (twe_wl_disp_del_source *)g_source_new(&_twe_wl_disp_del_funcs, + sizeof(twe_wl_disp_del_source)); + if (!source) { + TPL_ERR("[THREAD] Failed to create GSource"); + return NULL; + } + + source->event_fd = eventfd(0, EFD_CLOEXEC); + if (source->event_fd < 0) { + TPL_ERR("[THREAD] Failed to create eventfd. errno(%d)", errno); + g_source_unref(&source->gsource); + return NULL; + } + + source->tag = g_source_add_unix_fd(&source->gsource, + source->event_fd, + G_IO_IN); + source->disp_source = disp_source; + + g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop)); + g_source_unref(&source->gsource); + + return source; +} + +void +_twe_display_del_source_fini(twe_wl_disp_del_source *source) +{ + g_source_destroy(&source->gsource); + g_source_unref(&source->gsource); +} + twe_display_h twe_display_add(twe_thread* thread, struct wl_display *display) { @@ -587,6 +728,8 @@ twe_display_add(twe_thread* thread, struct wl_display *display) _twe_display_shm_init(source); + source->disp_del_source = _twe_display_del_source_init(thread, source); + g_source_set_callback(&source->gsource, NULL, display, NULL); g_source_add_poll(&source->gsource, &source->gfd); g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop)); @@ -603,6 +746,8 @@ twe_display_del(twe_display_h twe_display) { gboolean is_destroyed = FALSE; twe_wl_disp_source *source = (twe_wl_disp_source *)twe_display; + twe_wl_disp_del_source *disp_del_source = NULL; + if (!source || (is_destroyed = g_source_is_destroyed(&source->gsource))) { TPL_ERR("twe_display(%p) is invalid. | is_destroyed(%s)", @@ -610,16 +755,19 @@ twe_display_del(twe_display_h twe_display) return TPL_ERROR_INVALID_PARAMETER; } + disp_del_source = source->disp_del_source; + _twe_display_shm_fini(source); _twe_display_fini_wl_tbm_client(source->wl_tbm_client); source->wl_tbm_client = NULL; - g_source_remove_poll(&source->gsource, &source->gfd); - g_source_destroy(&source->gsource); - g_source_unref(&source->gsource); + _twe_thread_wl_disp_del_trigger(source); + + while (!g_source_is_destroyed(&source->gsource)) { + /* Waiting for destroying disp_source */ + } - TPL_LOG_T("WL_EGL", "del| twe_display(%p) wl_display(%p)", - source, source->disp); + _twe_display_del_source_fini(disp_del_source); return TPL_ERROR_NONE; } -- 2.7.4