/* 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);
+ gthread->paused = TPL_FALSE;
g_mutex_unlock(>hread->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(>hread->idle_mutex);
- if (gthread->is_idle) {
- g_mutex_unlock(>hread->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(>hread->idle_mutex);
- return;
+ return res;
}
g_source_set_priority(idle_source, G_PRIORITY_LOW);
end_time);
if (!ret) {
TPL_ERR("wait_idle timeout!");
+ res = TPL_ERROR_TIME_OUT;
break;
}
} while (!gthread->is_idle);
g_mutex_unlock(>hread->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(>hread->pause_mutex);
+ if (gthread->paused) {
+ g_mutex_unlock(>hread->pause_mutex);
+ sched_yield();
+ } else {
+ break;
+ }
+ } while (++cnt <= 100);
- g_mutex_lock(>hread->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(>hread->pause_mutex);
+ } else {
+ gthread->paused = TPL_TRUE;
+ }
+
+ return gthread->paused;
}
void
TPL_CHECK_ON_NULL_RETURN(gthread);
if (!gthread->paused) return;
- gthread->paused = TPL_FALSE;
g_mutex_unlock(>hread->pause_mutex);
}
\ No newline at end of file