g_cond_signal(gcond);
}
-static gboolean
-_thread_idle_cb(gpointer data)
-{
- tpl_gthread *gthread = (tpl_gthread *)data;
-
- TPL_LOG_D("[WAIT_IDLE]", "THREAD IDLE CALLBACK");
-
- g_mutex_lock(>hread->idle_mutex);
- gthread->is_idle = TPL_TRUE;
- 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,
- * thread will be paused here until unlock */
- TPL_LOG_D("[THREAD_PAUSE]", "try to lock pause_mutex");
- g_mutex_lock(>hread->pause_mutex);
- gthread->paused = TPL_FALSE;
- g_mutex_unlock(>hread->pause_mutex);
- TPL_LOG_D("[THREAD_RESUME]", "thread resumes");
-
- return G_SOURCE_REMOVE;
-}
-
-#define WAIT_IDLE_TIMEOUT 500
-
-tpl_result_t
-tpl_gthread_wait_idle(tpl_gthread *gthread)
-{
- gint64 end_time;
- gboolean ret = TRUE;
- tpl_result_t res = TPL_ERROR_NONE;
- tpl_gid_t id;
-
- TPL_LOG_D("[WAIT_IDLE]", "BEGIN");
-
- g_mutex_lock(>hread->idle_mutex);
-
- id = tpl_gthread_add_idle(gthread, (tpl_gsource_func)_thread_idle_cb, gthread);
- if (!id) {
- TPL_WARN("Failed to attach idle gsource.");
- } else {
- /* 500ms timeout */
- end_time = g_get_monotonic_time() +
- (WAIT_IDLE_TIMEOUT * G_TIME_SPAN_MILLISECOND);
- do {
- ret = g_cond_wait_until(>hread->idle_cond,
- >hread->idle_mutex,
- end_time);
- if (!ret) {
- tpl_gsource_remove(gthread, id);
- TPL_ERR("wait_idle timeout!");
- res = TPL_ERROR_TIME_OUT;
- break;
- }
- } while (!gthread->is_idle);
- }
-
- gthread->is_idle = TPL_FALSE;
-
- g_mutex_unlock(>hread->idle_mutex);
-
- TPL_LOG_D("[WAIT_IDLE]", "END");
-
- return res;
-}
-
-tpl_bool_t
-tpl_gthread_pause_in_idle(tpl_gthread *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);
-
- 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_gthread_continue(tpl_gthread *gthread)
-{
- TPL_CHECK_ON_NULL_RETURN(gthread);
-
- if (!gthread->paused) return;
- g_mutex_unlock(>hread->pause_mutex);
-}
-
tpl_gid_t
tpl_gthread_add_idle(tpl_gthread *gthread, tpl_gsource_func idle_cb, void *data)
{
void
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
- */
-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.
- */
-tpl_bool_t
-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);
-
/**
* attach new idle source with callback func
*