utils_gthread: cancel pause when wait_idle failed 43/286743/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 4 Jan 2023 07:29:57 +0000 (16:29 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Thu, 12 Jan 2023 07:13:39 +0000 (16:13 +0900)
 - If the tpl_gthread_wait_idle fails with timeout,
  it should be unlock pause_mutex immediately.

Change-Id: If33cc3c0b617ca34bb63d110d927e0dd7c022526
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/tpl_utils_gthread.c
src/tpl_utils_gthread.h

index bdc1109..68c2faf 100644 (file)
@@ -481,33 +481,30 @@ _thread_idle_cb(gpointer data)
        /* If the caller thread of tpl_gthread_wait_idle locked the pause_mutex,
         * thread will be paused here until unlock */
        g_mutex_lock(&gthread->pause_mutex);
+       gthread->paused = TPL_FALSE;
        g_mutex_unlock(&gthread->pause_mutex);
 
        return G_SOURCE_REMOVE;
 }
 
-void
+tpl_result_t
 tpl_gthread_wait_idle(tpl_gthread *gthread)
 {
-       TPL_CHECK_ON_NULL_RETURN(gthread);
-
        GSource *idle_source = NULL;
        gint64 end_time;
        gboolean ret = TRUE;
+       tpl_result_t res = TPL_ERROR_NONE;
 
        TPL_DEBUG("[WAIT IDLE] BEGIN");
 
        g_mutex_lock(&gthread->idle_mutex);
-       if (gthread->is_idle) {
-               g_mutex_unlock(&gthread->idle_mutex);
-               return;
-       }
 
        idle_source = g_idle_source_new();
        if (idle_source == NULL) {
                TPL_WARN("Failed to create and attach idle source");
+               res = TPL_ERROR_INVALID_OPERATION;
                g_mutex_unlock(&gthread->idle_mutex);
-               return;
+               return res;
        }
 
        g_source_set_priority(idle_source, G_PRIORITY_LOW);
@@ -526,6 +523,7 @@ tpl_gthread_wait_idle(tpl_gthread *gthread)
                                                                end_time);
                if (!ret) {
                        TPL_ERR("wait_idle timeout!");
+                       res = TPL_ERROR_TIME_OUT;
                        break;
                }
        } while (!gthread->is_idle);
@@ -535,16 +533,47 @@ tpl_gthread_wait_idle(tpl_gthread *gthread)
        g_mutex_unlock(&gthread->idle_mutex);
 
        TPL_DEBUG("[WAIT IDLE] END");
+
+       return res;
 }
 
-void
+tpl_bool_t
 tpl_gthread_pause_in_idle(tpl_gthread *gthread)
 {
-       TPL_CHECK_ON_NULL_RETURN(gthread);
+       TPL_CHECK_ON_NULL_RETURN_VAL(gthread, TPL_FALSE);
+
+       tpl_result_t res;
+       int cnt = 0;
+
+       /* Assume three threads. (M, C, wl-egl-thread)
+        * C thread : already locked pause_mutex and doing their own job.
+        * M thread : call pause_in_idle and trying to lock pause_mutex.
+        * wl-egl-thread : trying to lock pause_mutex in _thread_idle_cb.
+        *
+        * When C thread calls tpl_gthread_continue and unlock pause_mutex,
+        * M thread may receive schedule and lock pause_mutex.
+        * In that case, M thread should yield to wl-egl-thread, which is
+        * paused in thread_idle_cb(). */
+       do {
+               g_mutex_lock(&gthread->pause_mutex);
+               if (gthread->paused) {
+                       g_mutex_unlock(&gthread->pause_mutex);
+                       sched_yield();
+               } else {
+                       break;
+               }
+       } while (++cnt <= 100);
 
-       g_mutex_lock(&gthread->pause_mutex);
-       tpl_gthread_wait_idle(gthread);
-       gthread->paused = TPL_TRUE;
+       res = tpl_gthread_wait_idle(gthread);
+       if (res != TPL_ERROR_NONE) {
+               TPL_ERR("Failed to wait idle. | res(%d)", res);
+               gthread->paused = TPL_FALSE;
+               g_mutex_unlock(&gthread->pause_mutex);
+       } else {
+               gthread->paused = TPL_TRUE;
+       }
+
+       return gthread->paused;
 }
 
 void
@@ -553,6 +582,5 @@ tpl_gthread_continue(tpl_gthread *gthread)
        TPL_CHECK_ON_NULL_RETURN(gthread);
 
        if (!gthread->paused) return;
-       gthread->paused = TPL_FALSE;
        g_mutex_unlock(&gthread->pause_mutex);
 }
\ No newline at end of file
index 66552c4..c6ae5a4 100644 (file)
@@ -205,16 +205,20 @@ tpl_gcond_signal(tpl_gcond *gcond);
  * attach idle source and waiting for idle callback
  *
  * @param gthread Pointer to tpl_gthread
+ *
+ * @return tpl_result_t result of wait_idle
  */
-void
+tpl_result_t
 tpl_gthread_wait_idle(tpl_gthread *gthread);
 
 /**
  * pause thread when idle callback is called
  *
  * @param gthread Pointer to tpl_gthread
+ *
+ * @return TPL_TRUE if succeed to pause, TPL_FALSE otherwise.
  */
-void
+tpl_bool_t
 tpl_gthread_pause_in_idle(tpl_gthread *gthread);
 
 /**