From: Joonbum Ko Date: Fri, 2 Dec 2022 07:17:32 +0000 (+0900) Subject: utils_gthread: Prevent deadlock caused by wait_idle X-Git-Tag: accepted/tizen/unified/20230116.060903~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb176af61a52c48c85cce74af397eaedcf65848d;p=platform%2Fcore%2Fuifw%2Flibtpl-egl.git utils_gthread: Prevent deadlock caused by wait_idle Deadlock situation: Multi-threaded and multi surfaces for each thread T2: call pause_in_idle()->wait_idle() cond_wait() until idle signaled T1: call wait_idle() wait for lock idle_mutex T2: _thread_idle_cb unlock idle_mutex, set is_idle to TPL_TRUE and wait to lock pause_mutex T1: change is_idle to TPL_FALSE cond_wait() T2: cannot exit from while loop still cond_wait() - is_idle changing should be set TPL_FALSE after cond_wait finished Change-Id: I44292e486a1b9f686ec28bc0ae10ddedf94a48e3 Signed-off-by: Joonbum Ko --- diff --git a/src/tpl_utils_gthread.c b/src/tpl_utils_gthread.c index 208d881..bdc1109 100644 --- a/src/tpl_utils_gthread.c +++ b/src/tpl_utils_gthread.c @@ -475,7 +475,7 @@ _thread_idle_cb(gpointer data) g_mutex_lock(>hread->idle_mutex); gthread->is_idle = TPL_TRUE; - g_cond_signal(>hread->idle_cond); + g_cond_broadcast(>hread->idle_cond); g_mutex_unlock(>hread->idle_mutex); /* If the caller thread of tpl_gthread_wait_idle locked the pause_mutex, @@ -498,7 +498,10 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) TPL_DEBUG("[WAIT IDLE] BEGIN"); g_mutex_lock(>hread->idle_mutex); - gthread->is_idle = TPL_FALSE; + if (gthread->is_idle) { + g_mutex_unlock(>hread->idle_mutex); + return; + } idle_source = g_idle_source_new(); if (idle_source == NULL) { @@ -517,8 +520,7 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) /* 200ms timeout */ end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND); - - while (!gthread->is_idle) { + do { ret = g_cond_wait_until(>hread->idle_cond, >hread->idle_mutex, end_time); @@ -526,7 +528,10 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) TPL_ERR("wait_idle timeout!"); break; } - } + } while (!gthread->is_idle); + + gthread->is_idle = TPL_FALSE; + g_mutex_unlock(>hread->idle_mutex); TPL_DEBUG("[WAIT IDLE] END");