utils_gthread: modify thread's mutex locking mechanism 30/318930/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Fri, 11 Oct 2024 02:28:36 +0000 (11:28 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Fri, 11 Oct 2024 02:28:38 +0000 (11:28 +0900)
 - Add init_done flag to struct tpl_gthread to check if
  the initialization in thread is completed.

 - Remove unncessary locking mutex thread->thread_mutex.
  This fix can be resolve deadlock problem below.

 wake up thread
 _thread_source_dispatch
  g_mutex_lock -> lock thread_mutex // this locking is not neccessary
    __gsource_remove_and_destroy
      g_source_unref
        __thread_func_surf_finalize
          tpl_gmutex_lock -> lock surf_mutex
          _thread_wl_egl_surface_fini
            _buffers_force_release
              tbm_surface_internal_unref
                __cb_wl_egl_buffer_free
                  tpl_gsource_destroy
                   -> lock thread_mutex // it will cause deadlock

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

index a0b1fb74e0925d4f684b1f0e3093dfeab9c38522..167e2161a9f6a2e3d1e2da41fdbb78249af71085 100644 (file)
@@ -12,6 +12,7 @@ struct _tpl_gthread {
        GMutex                 pause_mutex;
        tpl_bool_t             is_idle;
        tpl_bool_t             paused;
+       tpl_bool_t             init_done;
 
        tpl_gthread_func       init_func;
        void                  *func_data;
@@ -47,6 +48,7 @@ _tpl_gthread_init(gpointer data)
        if (thread->init_func)
                thread->init_func(thread->func_data);
 
+       thread->init_done = TPL_TRUE;
        g_cond_signal(&thread->thread_cond);
        g_mutex_unlock(&thread->thread_mutex);
 
@@ -98,6 +100,7 @@ tpl_gthread_create(const char *thread_name,
 
        new_thread->is_idle = TPL_FALSE;
        new_thread->paused = TPL_FALSE;
+       new_thread->init_done = TPL_FALSE;
 
        g_mutex_lock(&new_thread->thread_mutex);
 
@@ -106,8 +109,11 @@ tpl_gthread_create(const char *thread_name,
        new_thread->func_data = func_data;
        new_thread->thread    = g_thread_new(thread_name,
                                                                             _tpl_gthread_init, new_thread);
-       g_cond_wait(&new_thread->thread_cond,
-                               &new_thread->thread_mutex);
+
+       while (!new_thread->init_done) {
+               g_cond_wait(&new_thread->thread_cond,
+                                       &new_thread->thread_mutex);
+       }
 
        g_mutex_unlock(&new_thread->thread_mutex);
 
@@ -187,6 +193,7 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                ssize_t s;
                uint64_t message = 0;
 
+               g_mutex_lock(&thread->thread_mutex);
                if (gsource->fd_type == FD_TYPE_EVENT) {
                        s = read(gsource->fd, &message, sizeof(uint64_t));
                        if (s != sizeof(uint64_t)) {
@@ -194,6 +201,7 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                                                gsource->fd);
                        }
                }
+               g_mutex_unlock(&thread->thread_mutex);
 
                if (gsource->gsource_funcs && gsource->gsource_funcs->dispatch)
                        ret = gsource->gsource_funcs->dispatch(gsource, message);
@@ -202,14 +210,8 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                        gsource->intended_destroy == TPL_TRUE) {
                        tpl_gsource *del_source = (tpl_gsource *)gsource->data;
                        if (!g_source_is_destroyed(&del_source->gsource)) {
-                               g_mutex_lock(&thread->thread_mutex);
-
                                __gsource_remove_and_destroy(del_source);
                                __gsource_remove_and_destroy(gsource);
-
-                               g_cond_signal(&thread->thread_cond);
-                               g_mutex_unlock(&thread->thread_mutex);
-
                                return G_SOURCE_REMOVE;
                        }
                }
@@ -228,10 +230,7 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
        }
 
        if (gsource->type == SOURCE_TYPE_DISPOSABLE) {
-               g_mutex_lock(&thread->thread_mutex);
                __gsource_remove_and_destroy(gsource);
-               ret = G_SOURCE_REMOVE;
-               g_mutex_unlock(&thread->thread_mutex);
        }
 
        return ret;
@@ -340,14 +339,15 @@ tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread)
                return;
        }
 
-       g_mutex_lock(&thread->thread_mutex);
        if (source->type == SOURCE_TYPE_NORMAL &&
                source->finalizer) {
                tpl_gsource *finalizer = source->finalizer;
 
                if (destroy_in_thread) {
                        finalizer->intended_destroy = TPL_TRUE;
+                       g_mutex_lock(&thread->thread_mutex);
                        tpl_gsource_send_message(finalizer, 1);
+                       g_mutex_unlock(&thread->thread_mutex);
                } else {
                        __gsource_remove_and_destroy(finalizer);
                        source->finalizer = NULL;
@@ -368,8 +368,6 @@ tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread)
                else
                        __gsource_remove_and_destroy(source);
        }
-
-       g_mutex_unlock(&thread->thread_mutex);
 }
 
 void
@@ -631,9 +629,7 @@ tpl_gthread_add_idle(tpl_gthread *gthread, tpl_gsource_func idle_cb, void *data)
                                                  idle_cb, (gpointer)data,
                                                  NULL);
 
-       g_mutex_lock(&gthread->thread_mutex);
        id = g_source_attach(idle_source, g_main_loop_get_context(gthread->loop));
-       g_mutex_unlock(&gthread->thread_mutex);
        g_source_unref(idle_source);
 
        return id;