From 7dfe9d051ec17276e10a6f935b45c7c0d63f1770 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 29 Sep 2022 21:04:56 +0900 Subject: [PATCH 01/16] Delete wrong g_main_context_unref - GMainContext is also destroyed when GMainLoop is destroyed. Therefore, it is the wrong code to do context_unref before loop_unref. Change-Id: Ib57eab7ba4345565977102abb0df3268d7f42acb Signed-off-by: Joonbum Ko --- src/tpl_utils_gthread.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tpl_utils_gthread.c b/src/tpl_utils_gthread.c index 20bab7f..f1dab0c 100644 --- a/src/tpl_utils_gthread.c +++ b/src/tpl_utils_gthread.c @@ -70,12 +70,14 @@ tpl_gthread_create(const char *thread_name, return NULL; } + // context's ref count was increased in g_main_loop_new g_main_context_unref(context); new_thread = calloc(1, sizeof(tpl_gthread)); if (!new_thread) { TPL_ERR("Failed to allocate tpl_gthread"); - g_main_context_unref(context); + + // context is also destroyed when loop is destroyed. g_main_loop_unref(loop); return NULL; -- 2.7.4 From 2ef4882ca7d468582e58e90736c4762ce7313b0e Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 30 Sep 2022 16:23:50 +0900 Subject: [PATCH 02/16] Changed the order of lock/unlock at buffer_clear. - The lock/unlock order of buffer->mutex and display->wl_event_mutex is important. display->mutex must surround buffer->mutex - Before applying this patch, deadlock issue may be occured in buffer_clear. Change-Id: I90d9b36874def4e4c7f0bd36742b3bbd00faab44 Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index f6c0375..4434972 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -2116,11 +2116,13 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) need_to_wait = (status < COMMITTED); if (need_to_wait) { - tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); + /* The lock/unlock order of buffer->mutex and display->wl_event_mutex + * is important. display->mutex must surround buffer->mutex */ + tpl_gmutex_unlock(&wl_egl_buffer->mutex); wait_result = tpl_gcond_timed_wait(&wl_egl_buffer->cond, - &wl_egl_buffer->mutex, - 200); /* 200ms */ - tpl_gmutex_lock(&wl_egl_display->wl_event_mutex); + &wl_egl_display->wl_event_mutex, + 200); /* 200ms */ + tpl_gmutex_lock(&wl_egl_buffer->mutex); if (wait_result == TPL_ERROR_TIME_OUT) TPL_WARN("timeout occured waiting signaled. wl_egl_buffer(%p)", -- 2.7.4 From 8325bf951c6608d237629e5eb9411dee6845f7af Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 30 Sep 2022 16:33:54 +0900 Subject: [PATCH 03/16] Modified to call tpl_gsource_destroy only once. - tpl_gsource_destroy means 'sending destroy message to thread'. So it need not to be called in loop. Change-Id: Ifd5706d738a2385396acaa3723138b2f564de4c2 Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 4434972..487cf63 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -970,8 +970,9 @@ __tpl_wl_egl_display_init(tpl_display_t *display) free_display: if (wl_egl_display->tdm.tdm_source) { tpl_gmutex_lock(&wl_egl_display->tdm.tdm_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_display->tdm.tdm_source, TPL_TRUE); while (!wl_egl_display->tdm.gsource_finalized) { - tpl_gsource_destroy(wl_egl_display->tdm.tdm_source, TPL_TRUE); tpl_gcond_wait(&wl_egl_display->tdm.tdm_cond, &wl_egl_display->tdm.tdm_mutex); } tpl_gmutex_unlock(&wl_egl_display->tdm.tdm_mutex); @@ -979,8 +980,9 @@ free_display: if (wl_egl_display->disp_source) { tpl_gmutex_lock(&wl_egl_display->disp_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); while (!wl_egl_display->gsource_finalized) { - tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); tpl_gcond_wait(&wl_egl_display->disp_cond, &wl_egl_display->disp_mutex); } tpl_gmutex_unlock(&wl_egl_display->disp_mutex); @@ -1024,8 +1026,9 @@ __tpl_wl_egl_display_fini(tpl_display_t *display) * caller should use tpl_gcond_wait() in the loop with checking finalized flag * */ tpl_gmutex_lock(&wl_egl_display->tdm.tdm_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_display->tdm.tdm_source, TPL_TRUE); while (!wl_egl_display->tdm.gsource_finalized) { - tpl_gsource_destroy(wl_egl_display->tdm.tdm_source, TPL_TRUE); tpl_gcond_wait(&wl_egl_display->tdm.tdm_cond, &wl_egl_display->tdm.tdm_mutex); } wl_egl_display->tdm.tdm_source = NULL; @@ -1038,8 +1041,9 @@ __tpl_wl_egl_display_fini(tpl_display_t *display) * caller should use tpl_gcond_wait() in the loop with checking finalized flag * */ tpl_gmutex_lock(&wl_egl_display->disp_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); while (wl_egl_display->disp_source && !wl_egl_display->gsource_finalized) { - tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); tpl_gcond_wait(&wl_egl_display->disp_cond, &wl_egl_display->disp_mutex); } wl_egl_display->disp_source = NULL; @@ -2200,8 +2204,9 @@ __tpl_wl_egl_surface_fini(tpl_surface_t *surface) * caller should use tpl_gcond_wait() in the loop with checking finalized flag * */ tpl_gmutex_lock(&wl_egl_surface->surf_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_surface->surf_source, TPL_TRUE); while (wl_egl_surface->surf_source && !wl_egl_surface->gsource_finalized) { - tpl_gsource_destroy(wl_egl_surface->surf_source, TPL_TRUE); tpl_gcond_wait(&wl_egl_surface->surf_cond, &wl_egl_surface->surf_mutex); } wl_egl_surface->surf_source = NULL; -- 2.7.4 From 8f0f90756b5f0cd8ef7a6142bfce0269123e903c Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 30 Sep 2022 16:35:33 +0900 Subject: [PATCH 04/16] Package version up to 1.9.8 Change-Id: I7a1bda7114b8cf98de0cd8f2f02dfb6b8d2c25fa Signed-off-by: Joonbum Ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index cb1653c..c4422ec 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 9 -%define TPL_VERSION_PATCH 7 +%define TPL_VERSION_PATCH 8 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From 999b176b6427f1e09450bec792b081c636f4370c Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 5 Oct 2022 10:49:43 +0900 Subject: [PATCH 05/16] Remove unncessary header Change-Id: I810ec7c149bbb782d8e04167f66810171226d728 Signed-off-by: Joonbum Ko --- src/tpl_wl_vk_thread.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index 884e7c7..11e35f3 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -24,7 +24,6 @@ #endif #if TIZEN_FEATURE_ENABLE -#include #include #endif -- 2.7.4 From 50c990169dcffad91255612a7c2929df3735be97 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 5 Oct 2022 10:57:23 +0900 Subject: [PATCH 06/16] Add null checking before calling tpl_gsource_destroy. Change-Id: I431f21b80215abeafc5ab6daa45778f617cc661a Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 52 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 487cf63..fb9286f 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -1035,19 +1035,21 @@ __tpl_wl_egl_display_fini(tpl_display_t *display) tpl_gmutex_unlock(&wl_egl_display->tdm.tdm_mutex); } - /* This is a protection to prevent problems that arise in unexpected situations - * that g_cond_wait cannot work normally. - * When calling tpl_gsource_destroy() with destroy_in_thread is TPL_TRUE, - * caller should use tpl_gcond_wait() in the loop with checking finalized flag - * */ - tpl_gmutex_lock(&wl_egl_display->disp_mutex); - // Send destroy mesage to thread - tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); - while (wl_egl_display->disp_source && !wl_egl_display->gsource_finalized) { - tpl_gcond_wait(&wl_egl_display->disp_cond, &wl_egl_display->disp_mutex); + if (wl_egl_display->disp_source) { + tpl_gmutex_lock(&wl_egl_display->disp_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_display->disp_source, TPL_TRUE); + /* This is a protection to prevent problems that arise in unexpected situations + * that g_cond_wait cannot work normally. + * When calling tpl_gsource_destroy() with destroy_in_thread is TPL_TRUE, + * caller should use tpl_gcond_wait() in the loop with checking finalized flag + * */ + while (!wl_egl_display->gsource_finalized) { + tpl_gcond_wait(&wl_egl_display->disp_cond, &wl_egl_display->disp_mutex); + } + wl_egl_display->disp_source = NULL; + tpl_gmutex_unlock(&wl_egl_display->disp_mutex); } - wl_egl_display->disp_source = NULL; - tpl_gmutex_unlock(&wl_egl_display->disp_mutex); if (wl_egl_display->thread) { tpl_gthread_destroy(wl_egl_display->thread); @@ -2198,19 +2200,21 @@ __tpl_wl_egl_surface_fini(tpl_surface_t *surface) _tpl_wl_egl_surface_buffer_clear(wl_egl_surface); - /* This is a protection to prevent problems that arise in unexpected situations - * that g_cond_wait cannot work normally. - * When calling tpl_gsource_destroy() with destroy_in_thread is TPL_TRUE, - * caller should use tpl_gcond_wait() in the loop with checking finalized flag - * */ - tpl_gmutex_lock(&wl_egl_surface->surf_mutex); - // Send destroy mesage to thread - tpl_gsource_destroy(wl_egl_surface->surf_source, TPL_TRUE); - while (wl_egl_surface->surf_source && !wl_egl_surface->gsource_finalized) { - tpl_gcond_wait(&wl_egl_surface->surf_cond, &wl_egl_surface->surf_mutex); + if (wl_egl_surface->surf_source) { + tpl_gmutex_lock(&wl_egl_surface->surf_mutex); + // Send destroy mesage to thread + tpl_gsource_destroy(wl_egl_surface->surf_source, TPL_TRUE); + /* This is a protection to prevent problems that arise in unexpected situations + * that g_cond_wait cannot work normally. + * When calling tpl_gsource_destroy() with destroy_in_thread is TPL_TRUE, + * caller should use tpl_gcond_wait() in the loop with checking finalized flag + * */ + while (!wl_egl_surface->gsource_finalized) { + tpl_gcond_wait(&wl_egl_surface->surf_cond, &wl_egl_surface->surf_mutex); + } + wl_egl_surface->surf_source = NULL; + tpl_gmutex_unlock(&wl_egl_surface->surf_mutex); } - wl_egl_surface->surf_source = NULL; - tpl_gmutex_unlock(&wl_egl_surface->surf_mutex); _print_buffer_lists(wl_egl_surface); -- 2.7.4 From 0038526f2e4153b1b81b64b7b539998e5e62e5e9 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 5 Oct 2022 10:58:46 +0900 Subject: [PATCH 07/16] Package version up to 1.9.9 Change-Id: I6c7059dae6306e235be00ac9ec8bd1f7d3112136 Signed-off-by: Joonbum Ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index c4422ec..fc4fa15 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 9 -%define TPL_VERSION_PATCH 8 +%define TPL_VERSION_PATCH 9 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From 9f60156fde4f33dec22749773f4cb2399aacf12d Mon Sep 17 00:00:00 2001 From: "jinbong, Lee" Date: Wed, 19 Oct 2022 18:58:06 +0900 Subject: [PATCH 08/16] Remove unused int64, int32 hash key for fixing Svace warning Change-Id: I9bb85b566db975860e4243c39683f40e60601aed --- src/tpl_utils.h | 16 ++---------- src/tpl_utils_map.c | 74 ----------------------------------------------------- 2 files changed, 2 insertions(+), 88 deletions(-) diff --git a/src/tpl_utils.h b/src/tpl_utils.h index 21f2580..b7dfa1c 100644 --- a/src/tpl_utils.h +++ b/src/tpl_utils.h @@ -309,7 +309,7 @@ typedef struct _tpl_list_node tpl_list_node_t; typedef struct _tpl_list tpl_list_t; typedef struct tpl_util_map_entry tpl_util_map_entry_t; typedef struct tpl_util_map tpl_util_map_t; -typedef union tpl_util_key tpl_util_key_t; +typedef struct tpl_util_key tpl_util_key_t; typedef int (*tpl_util_hash_func_t)(const tpl_util_key_t key, int key_length); typedef int (*tpl_util_key_length_func_t)(const tpl_util_key_t key); @@ -324,9 +324,7 @@ enum _tpl_occurrence { TPL_ALL }; -union tpl_util_key { - uint32_t key32; - uint64_t key64; +struct tpl_util_key { void *ptr; /*pointer key or user defined key(string)*/ }; @@ -359,12 +357,6 @@ void tpl_util_map_init(tpl_util_map_t *map, int bucket_bits, tpl_util_key_compare_func_t key_compare_func, void *buckets); -void tpl_util_map_int32_init(tpl_util_map_t *map, int bucket_bits, - void *buckets); - -void tpl_util_map_int64_init(tpl_util_map_t *map, int bucket_bits, - void *buckets); - void tpl_util_map_pointer_init(tpl_util_map_t *map, int bucket_bits, void *buckets); @@ -375,10 +367,6 @@ tpl_util_map_create(int bucket_bits, tpl_util_hash_func_t hash_func, tpl_util_key_length_func_t key_length_func, tpl_util_key_compare_func_t key_compare_func); -tpl_util_map_t *tpl_util_map_int32_create(int bucket_bits); - -tpl_util_map_t *tpl_util_map_int64_create(int bucket_bits); - tpl_util_map_t *tpl_util_map_pointer_create(int bucket_bits); void tpl_util_map_destroy(tpl_util_map_t *map); diff --git a/src/tpl_utils_map.c b/src/tpl_utils_map.c index 0336bc4..dbfa74a 100644 --- a/src/tpl_utils_map.c +++ b/src/tpl_utils_map.c @@ -26,52 +26,6 @@ __get_bucket(tpl_util_map_t *map, const tpl_util_key_t key) } static int -__int64_hash(const tpl_util_key_t key, int key_length) -{ - uint64_t _key = key.key64; - - /* Hash functions from Thomas Wang https://gist.github.com/badboy/6267743 */ - _key = ~_key + (_key << 18); - _key ^= _key >> 31; - _key *= 21; - _key ^= _key >> 11; - _key += _key << 6; - _key ^= _key >> 22; - - return (int)_key;; -} - -static int -__int64_key_compare(const tpl_util_key_t key0, int key0_length, - const tpl_util_key_t key1, int key1_length) -{ - return (int)(key0.key64 - key1.key64); -} - -static int -__int32_hash(const tpl_util_key_t key, int key_length) -{ - uint32_t _key = (uint32_t)key.key32; - - /* Hash functions from Thomas Wang https://gist.github.com/badboy/6267743 */ - _key = ~_key + (_key << 15); - _key ^= _key >> 12; - _key += _key << 2; - _key ^= _key >> 4; - _key *= 2057; - _key ^= _key >> 16; - - return (int)_key; -} - -static int -__int32_key_compare(const tpl_util_key_t key0, int key0_length, - const tpl_util_key_t key1, int key1_length) -{ - return (int)(key0.key32 - key1.key32); -} - -static int __pointer_hash(const tpl_util_key_t key, int key_length) { #if INTPTR_MAX == INT32_MAX @@ -129,20 +83,6 @@ tpl_util_map_init(tpl_util_map_t *map, int bucket_bits, } void -tpl_util_map_int32_init(tpl_util_map_t *map, int bucket_bits, void *buckets) -{ - tpl_util_map_init(map, bucket_bits, __int32_hash, NULL, - __int32_key_compare, buckets); -} - -void -tpl_util_map_int64_init(tpl_util_map_t *map, int bucket_bits, void *buckets) -{ - tpl_util_map_init(map, bucket_bits, __int64_hash, NULL, - __int64_key_compare, buckets); -} - -void tpl_util_map_pointer_init(tpl_util_map_t *map, int bucket_bits, void *buckets) { tpl_util_map_init(map, bucket_bits, __pointer_hash, NULL, @@ -174,20 +114,6 @@ tpl_util_map_create(int bucket_bits, tpl_util_hash_func_t hash_func, } tpl_util_map_t * -tpl_util_map_int32_create(int bucket_bits) -{ - return tpl_util_map_create(bucket_bits, __int32_hash, NULL, - __int32_key_compare); -} - -tpl_util_map_t * -tpl_util_map_int64_create(int bucket_bits) -{ - return tpl_util_map_create(bucket_bits, __int64_hash, NULL, - __int64_key_compare); -} - -tpl_util_map_t * tpl_util_map_pointer_create(int bucket_bits) { return tpl_util_map_create(bucket_bits, __pointer_hash, NULL, -- 2.7.4 From ca6f3cf3826ede26e1669dbfe2868a13d4ffed6e Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 27 Oct 2022 20:04:52 +0900 Subject: [PATCH 09/16] wl_vk: Add missed flag setting when surface_init Change-Id: I45e7d3135a6780a1f08b10fe8913fc9ffe71af7f Signed-off-by: Joonbum Ko --- src/tpl_wl_vk_thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index 11e35f3..fe0d337 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -1209,6 +1209,7 @@ __thread_func_surf_dispatch(tpl_gsource *gsource, uint64_t message) TPL_DEBUG("wl_vk_surface(%p) initialize message received!", wl_vk_surface); _thread_wl_vk_surface_init(wl_vk_surface); + wl_vk_surface->initialized_in_thread = TPL_TRUE; tpl_gcond_signal(&wl_vk_surface->surf_cond); } else if (message == CREATE_QUEUE) { /* Create tbm_surface_queue */ TPL_DEBUG("wl_vk_surface(%p) queue creation message received!", -- 2.7.4 From 3a28f16f753bf42ac47d2dd635e21894fa459c65 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 28 Oct 2022 00:02:58 +0900 Subject: [PATCH 10/16] wl_egl: Add defense code for fake signal in buffer_clear tpl_gcond_timed_wait is changed to be called within the while loop. It will repeat the process of checking status even if it wakes up due to Fake Signal. Change-Id: Ia66810da64ba2830c166f01dcb2f2f4615fc8e4f Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index fb9286f..67c14a1 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -2116,19 +2116,17 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) status_to_string[status]); if (status >= ENQUEUED) { - tpl_bool_t need_to_wait = TPL_FALSE; tpl_result_t wait_result = TPL_ERROR_NONE; - need_to_wait = (status < COMMITTED); - - if (need_to_wait) { + while (status < COMMITTED && wait_result != TPL_ERROR_TIME_OUT) { + tpl_gmutex_unlock(&wl_egl_buffer->mutex); /* The lock/unlock order of buffer->mutex and display->wl_event_mutex * is important. display->mutex must surround buffer->mutex */ - tpl_gmutex_unlock(&wl_egl_buffer->mutex); wait_result = tpl_gcond_timed_wait(&wl_egl_buffer->cond, &wl_egl_display->wl_event_mutex, 200); /* 200ms */ tpl_gmutex_lock(&wl_egl_buffer->mutex); + status = wl_egl_buffer->status; /* update status */ if (wait_result == TPL_ERROR_TIME_OUT) TPL_WARN("timeout occured waiting signaled. wl_egl_buffer(%p)", @@ -2136,8 +2134,6 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) } } - status = wl_egl_buffer->status; /* update status */ - /* ACQUIRED, WAITING_SIGNALED, WAITING_VBLANK, COMMITTED */ /* It has been acquired but has not yet been released, so this * buffer must be released. */ -- 2.7.4 From b440363836b4c75de49eb5d063e7ef52001ce4fa Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 28 Oct 2022 08:35:20 +0900 Subject: [PATCH 11/16] Package version up to 1.9.10 Change-Id: I43791c514fa7abd274b238d7cdfbc3489e8278eb Signed-off-by: Joonbum Ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index fc4fa15..3f173a4 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 9 -%define TPL_VERSION_PATCH 9 +%define TPL_VERSION_PATCH 10 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From c48f68e29e8d1df3039b851b0dfd349cae7bd69d Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 10 Nov 2022 19:36:33 +0900 Subject: [PATCH 12/16] wl_egl: Set timeout for buffer_clear to 500ms - Some system condition problems may cause signal after 200ms. Change-Id: I40bdbf7cc862e0026228b85644eda60f15b86dec Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 67c14a1..19f27af 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -2124,7 +2124,7 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) * is important. display->mutex must surround buffer->mutex */ wait_result = tpl_gcond_timed_wait(&wl_egl_buffer->cond, &wl_egl_display->wl_event_mutex, - 200); /* 200ms */ + 500); /* 500ms */ tpl_gmutex_lock(&wl_egl_buffer->mutex); status = wl_egl_buffer->status; /* update status */ -- 2.7.4 From 2b0dded3eee64e7fa312287ee25fc20107942466 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 10 Nov 2022 23:45:49 +0900 Subject: [PATCH 13/16] wl_egl: Print additional INFO logs at buffer_clear Change-Id: I5cbd4b6b96bc149407969834d4147aeebb3cf2e2 Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 19f27af..dc0e55a 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -2089,6 +2089,7 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) buffer_status_t status = RELEASED; int idx = 0; + TPL_INFO("[BUFFER_CLEAR]", "BEGIN | wl_egl_surface(%p)", wl_egl_surface); while (wl_egl_surface->buffer_cnt) { tpl_gmutex_lock(&wl_egl_display->wl_event_mutex); tpl_gmutex_lock(&wl_egl_surface->buffers_mutex); @@ -2110,10 +2111,10 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) status = wl_egl_buffer->status; - TPL_DEBUG("[idx:%d] wl_egl_buffer(%p) tbm_surface(%p) status(%s)", - idx, wl_egl_buffer, - wl_egl_buffer->tbm_surface, - status_to_string[status]); + TPL_INFO("[BUFFER]","idx(%d)| wl_egl_buffer(%p) tbm_surface(%p) status(%s)", + idx, wl_egl_buffer, + wl_egl_buffer->tbm_surface, + status_to_string[status]); if (status >= ENQUEUED) { tpl_result_t wait_result = TPL_ERROR_NONE; @@ -2128,9 +2129,10 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) tpl_gmutex_lock(&wl_egl_buffer->mutex); status = wl_egl_buffer->status; /* update status */ - if (wait_result == TPL_ERROR_TIME_OUT) - TPL_WARN("timeout occured waiting signaled. wl_egl_buffer(%p)", - wl_egl_buffer); + if (wait_result == TPL_ERROR_TIME_OUT) { + TPL_WARN("timeout occured waiting signaled. wl_egl_buffer(%p) status(%s)", + wl_egl_buffer, status_to_string[status]); + } } } @@ -2170,6 +2172,7 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) idx++; } + TPL_INFO("[BUFFER_CLEAR]", "END | wl_egl_surface(%p)", wl_egl_surface); } static void -- 2.7.4 From a33c6ce0532bad562fe4a4ea4e97be41789b11cf Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 10 Nov 2022 23:57:16 +0900 Subject: [PATCH 14/16] Package version up to 1.9.11 Change-Id: I03d05215651ab24596e24a9a8d011cd7a4940b2f Signed-off-by: Joonbum Ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 3f173a4..f9758e2 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 9 -%define TPL_VERSION_PATCH 10 +%define TPL_VERSION_PATCH 11 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From b95029e498082dd8baf49d55213c9557155a196b Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 16 Nov 2022 17:21:08 +0900 Subject: [PATCH 15/16] utils_gthread: Add new functions to pause/continue thread tpl_gthread_wait_idle - Create a new idle source and attach it to thread context. This function will be blocked until idle callback is called. If the thread has some worksto be handled, wait for the thread to finish it. tpl_gthread_pause_in_idle - Pause the thread when idle callback is called. tpl_gthread_continue - Continue the paused thread. Change-Id: I5a2aaf3b8b9579306246234d252b643b6cc0bf3e Signed-off-by: Joonbum Ko --- src/tpl_utils_gthread.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/tpl_utils_gthread.h | 23 +++++++++++++ 2 files changed, 112 insertions(+) diff --git a/src/tpl_utils_gthread.c b/src/tpl_utils_gthread.c index f1dab0c..500507f 100644 --- a/src/tpl_utils_gthread.c +++ b/src/tpl_utils_gthread.c @@ -7,6 +7,12 @@ struct _tpl_gthread { GMutex thread_mutex; GCond thread_cond; + GMutex idle_mutex; + GCond idle_cond; + GMutex pause_mutex; + tpl_bool_t is_idle; + tpl_bool_t paused; + tpl_gthread_func init_func; void *func_data; }; @@ -86,6 +92,12 @@ tpl_gthread_create(const char *thread_name, g_mutex_init(&new_thread->thread_mutex); g_cond_init(&new_thread->thread_cond); + g_mutex_init(&new_thread->pause_mutex); + g_mutex_init(&new_thread->idle_mutex); + g_cond_init(&new_thread->idle_cond); + + new_thread->is_idle = TPL_FALSE; + new_thread->paused = TPL_FALSE; g_mutex_lock(&new_thread->thread_mutex); @@ -115,6 +127,10 @@ tpl_gthread_destroy(tpl_gthread *thread) g_mutex_unlock(&thread->thread_mutex); + g_mutex_clear(&thread->pause_mutex); + g_mutex_clear(&thread->idle_mutex); + g_cond_clear(&thread->idle_cond); + g_mutex_clear(&thread->thread_mutex); g_cond_clear(&thread->thread_cond); @@ -448,4 +464,77 @@ void tpl_gcond_signal(tpl_gcond *gcond) { g_cond_signal(gcond); +} + +static gboolean +_thread_idle_cb(gpointer data) +{ + tpl_gthread *gthread = (tpl_gthread *)data; + + TPL_DEBUG("THREAD IDLE CALLBACK"); + + g_mutex_lock(>hread->idle_mutex); + gthread->is_idle = TPL_TRUE; + g_cond_signal(>hread->idle_cond); + g_mutex_unlock(>hread->idle_mutex); + + /* If the caller thread of tpl_gthread_wait_idle locked the pause_mutex, + * thread will be paused here until unlock */ + g_mutex_lock(>hread->pause_mutex); + g_mutex_unlock(>hread->pause_mutex); + + return G_SOURCE_REMOVE; +} + +void +tpl_gthread_wait_idle(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + GSource *idle_source = NULL; + + TPL_DEBUG("[WAIT IDLE] BEGIN"); + + g_mutex_lock(>hread->idle_mutex); + gthread->is_idle = TPL_FALSE; + + idle_source = g_idle_source_new(); + if (idle_source == NULL) { + TPL_WARN("Failed to create and attach idle source"); + g_mutex_unlock(>hread->idle_mutex); + return; + } + + g_source_set_priority(idle_source, G_PRIORITY_LOW); + g_source_set_callback(idle_source, + _thread_idle_cb, (gpointer)gthread, + NULL); + g_source_attach(idle_source, g_main_loop_get_context(gthread->loop)); + g_source_unref(idle_source); + + while (!gthread->is_idle) { + g_cond_wait(>hread->idle_cond, >hread->idle_mutex); + } + g_mutex_unlock(>hread->idle_mutex); + + TPL_DEBUG("[WAIT IDLE] END"); +} + +void +tpl_gthread_pause_in_idle(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + g_mutex_lock(>hread->pause_mutex); + tpl_gthread_wait_idle(gthread); + gthread->paused = TPL_TRUE; +} + +void +tpl_gthread_continue(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + if (!gthread->paused) return; + g_mutex_unlock(>hread->pause_mutex); } \ No newline at end of file diff --git a/src/tpl_utils_gthread.h b/src/tpl_utils_gthread.h index 8185cab..66552c4 100644 --- a/src/tpl_utils_gthread.h +++ b/src/tpl_utils_gthread.h @@ -201,6 +201,29 @@ tpl_gcond_timed_wait(tpl_gcond *gcond, tpl_gmutex *gmutex, int64_t timeout_ms); void tpl_gcond_signal(tpl_gcond *gcond); +/** + * attach idle source and waiting for idle callback + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_wait_idle(tpl_gthread *gthread); + +/** + * pause thread when idle callback is called + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_pause_in_idle(tpl_gthread *gthread); + +/** + * continue thread if thread was paused + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_continue(tpl_gthread *gthread); -- 2.7.4 From da2fa54fd367453ca8d0261856494b5106d9d351 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 17 Nov 2022 17:33:11 +0900 Subject: [PATCH 16/16] wl_egl: Apply pause and wait_idle at buffer clear AS-IS Using wl_event_mutex lock to pause thread. Using wl_event_mutex is not good way to pause thread because locking wl_event_mutex can effect other wayland threads. TO-BE Using tpl_gthread_pause_in_idle is better way than before. Because locking on idle allows thread to handle other tasks. Change-Id: I47a1b82a91ede648ceb8a8a1e7967fa56950ba00 Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index dc0e55a..a00116a 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -2089,24 +2089,21 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) buffer_status_t status = RELEASED; int idx = 0; + tpl_gthread_pause_in_idle(wl_egl_display->thread); + TPL_INFO("[BUFFER_CLEAR]", "BEGIN | wl_egl_surface(%p)", wl_egl_surface); + while (wl_egl_surface->buffer_cnt) { - tpl_gmutex_lock(&wl_egl_display->wl_event_mutex); - tpl_gmutex_lock(&wl_egl_surface->buffers_mutex); wl_egl_buffer = wl_egl_surface->buffers[idx]; if (wl_egl_buffer) { wl_egl_surface->buffers[idx] = NULL; wl_egl_surface->buffer_cnt--; } else { - tpl_gmutex_unlock(&wl_egl_surface->buffers_mutex); - tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); idx++; continue; } - tpl_gmutex_unlock(&wl_egl_surface->buffers_mutex); - tpl_gmutex_lock(&wl_egl_buffer->mutex); status = wl_egl_buffer->status; @@ -2120,13 +2117,11 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) tpl_result_t wait_result = TPL_ERROR_NONE; while (status < COMMITTED && wait_result != TPL_ERROR_TIME_OUT) { - tpl_gmutex_unlock(&wl_egl_buffer->mutex); - /* The lock/unlock order of buffer->mutex and display->wl_event_mutex - * is important. display->mutex must surround buffer->mutex */ + tpl_gthread_continue(wl_egl_display->thread); wait_result = tpl_gcond_timed_wait(&wl_egl_buffer->cond, - &wl_egl_display->wl_event_mutex, + &wl_egl_buffer->mutex, 500); /* 500ms */ - tpl_gmutex_lock(&wl_egl_buffer->mutex); + tpl_gthread_pause_in_idle(wl_egl_display->thread); status = wl_egl_buffer->status; /* update status */ if (wait_result == TPL_ERROR_TIME_OUT) { @@ -2168,11 +2163,11 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface) if (need_to_release || need_to_cancel) tbm_surface_internal_unref(wl_egl_buffer->tbm_surface); - tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); - idx++; } TPL_INFO("[BUFFER_CLEAR]", "END | wl_egl_surface(%p)", wl_egl_surface); + + tpl_gthread_continue(wl_egl_display->thread); } static void @@ -2197,6 +2192,8 @@ __tpl_wl_egl_surface_fini(tpl_surface_t *surface) wl_egl_surface, wl_egl_surface->wl_surface, wl_egl_surface->tbm_queue); + tpl_gthread_wait_idle(wl_egl_display->thread); + _tpl_wl_egl_surface_buffer_clear(wl_egl_surface); if (wl_egl_surface->surf_source) { @@ -2344,14 +2341,18 @@ __tpl_wl_egl_surface_get_size(tpl_surface_t *surface, int *width, int *height) tpl_result_t _tbm_queue_force_flush(tpl_wl_egl_surface_t *wl_egl_surface) { + tpl_wl_egl_display_t *wl_egl_display = wl_egl_surface->wl_egl_display; tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + tpl_gthread_pause_in_idle(wl_egl_display->thread); + _print_buffer_lists(wl_egl_surface); if ((tsq_err = tbm_surface_queue_flush(wl_egl_surface->tbm_queue)) != TBM_SURFACE_QUEUE_ERROR_NONE) { TPL_ERR("Failed to flush tbm_surface_queue(%p) tsq_err(%d)", wl_egl_surface->tbm_queue, tsq_err); + tpl_gthread_continue(wl_egl_display->thread); return TPL_ERROR_INVALID_OPERATION; } @@ -2360,13 +2361,9 @@ _tbm_queue_force_flush(tpl_wl_egl_surface_t *wl_egl_surface) tpl_wl_egl_buffer_t *wl_egl_buffer = NULL; for (i = 0; i < BUFFER_ARRAY_SIZE; i++) { buffer_status_t status; - tpl_gmutex_lock(&wl_egl_surface->buffers_mutex); wl_egl_buffer = wl_egl_surface->buffers[i]; - tpl_gmutex_unlock(&wl_egl_surface->buffers_mutex); if (wl_egl_buffer) { - tpl_gmutex_lock(&wl_egl_buffer->mutex); status = wl_egl_buffer->status; - tpl_gmutex_unlock(&wl_egl_buffer->mutex); } else { continue; } @@ -2388,6 +2385,8 @@ _tbm_queue_force_flush(tpl_wl_egl_surface_t *wl_egl_surface) _print_buffer_lists(wl_egl_surface); + tpl_gthread_continue(wl_egl_display->thread); + return TPL_ERROR_NONE; } @@ -2584,10 +2583,6 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, wl_egl_surface->tbm_queue, CAN_DEQUEUE_TIMEOUT_MS); TPL_OBJECT_LOCK(surface); - /* After the can dequeue state, lock the wl_event_mutex to prevent other - * events from being processed in wayland_egl_thread - * during below dequeue procedure. */ - tpl_gmutex_lock(&wl_egl_display->wl_event_mutex); if (tsq_err == TBM_SURFACE_QUEUE_ERROR_TIMEOUT) { TPL_WARN("[CAN_DEQUEUE_TIMEOUT] queue(%p) will be reset. surface(%p)", @@ -2595,7 +2590,6 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, if (_tbm_queue_force_flush(wl_egl_surface) != TPL_ERROR_NONE) { TPL_ERR("Failed to timeout reset. tbm_queue(%p) surface(%p)", wl_egl_surface->tbm_queue, surface); - tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); return NULL; } else { tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; @@ -2605,10 +2599,14 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { TPL_ERR("Failed to query can_dequeue. tbm_queue(%p) surface(%p)", wl_egl_surface->tbm_queue, surface); - tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); return NULL; } + /* After the can dequeue state, lock the wl_event_mutex to prevent other + * events from being processed in wayland_egl_thread + * during below dequeue procedure. */ + tpl_gmutex_lock(&wl_egl_display->wl_event_mutex); + /* wayland client can check their states (ACTIVATED or DEACTIVATED) with * below function [wayland_tbm_client_queue_check_activate()]. * This function has to be called before tbm_surface_queue_dequeue() -- 2.7.4