Move mutexes and condition from static memory allocation to dynamic 83/118883/6
authorVolodymyr Brynza <v.brynza@samsung.com>
Fri, 12 May 2017 11:33:52 +0000 (14:33 +0300)
committerVolodymyr Brynza <v.brynza@samsung.com>
Fri, 12 May 2017 11:33:52 +0000 (14:33 +0300)
Add reference counting to glue

Change-Id: I2380d4cc4a761374b69f062a0906a1a388a26a2c
Signed-off-by: Volodymyr Brynza <v.brynza@samsung.com>
src/common/glib-glue.c
src/common/mainloop.c

index 9bfcdf1c9675c7032ed023eb11b390477f5c07d2..7cd469fe38bb61cc0cbad10e96df6df25db6e4eb 100644 (file)
 
 #define MURPHY_LOOP_WAIT_TIME_THREAD 1
 
-static GMutex g_murphy_glue_callback_lock;
-static GMutex g_murphy_glue_internal_lock;
-static GCond g_murphy_loop_cond;
-
 
 typedef struct {
     GMainLoop *gml;
     GThread *worker;
+    GMutex glue_callback_lock;
+    GMutex glue_internal_lock;
+    GCond loop_cond;
+    gint ref_count;
 } glib_glue_t;
 
 
@@ -102,6 +102,43 @@ static guint add_timeout(void *glue_data, GSourceFunc cb, unsigned int msecs, vo
 static guint add_io_watch(void *glue_data, GSourceFunc cb, GIOCondition mask, GIOChannel *ioc, void *user_data);
 static void  remove_source(void *glue_data, guint id);
 
+static glib_glue_t* glue_new()
+{
+    glib_glue_t *glue = NULL;
+    glue = mrp_allocz(sizeof(*glue));
+    if (NULL != glue) {
+        g_mutex_init(&glue->glue_callback_lock);
+        g_mutex_init(&glue->glue_internal_lock);
+        g_cond_init(&glue->loop_cond);
+        glue->ref_count = 1;
+    }
+    return glue;
+}
+
+static glib_glue_t* glue_ref(glib_glue_t *glue)
+{
+    g_return_val_if_fail(glue != NULL, NULL);
+    g_return_val_if_fail(g_atomic_int_get(&glue->ref_count) > 0, NULL);
+
+    g_atomic_int_inc(&glue->ref_count);
+
+    return glue;
+}
+
+static void glue_unref(glib_glue_t *glue)
+{
+    g_return_if_fail(glue != NULL);
+    g_return_if_fail(g_atomic_int_get(&glue->ref_count) > 0);
+
+    if (!g_atomic_int_dec_and_test(&glue->ref_count))
+        return;
+
+    g_mutex_clear(&glue->glue_callback_lock);
+    g_mutex_clear(&glue->glue_internal_lock);
+    g_cond_clear(&glue->loop_cond);
+    mrp_free(glue);
+}
+
 static guint add_timeout(void *glue_data, GSourceFunc cb, unsigned int msecs, void *user_data)
 {
     guint id = 0;
@@ -143,8 +180,10 @@ static void remove_source(void *glue_data, guint id)
 
 static gboolean io_cb(GIOChannel *ioc, GIOCondition cond, gpointer user_data)
 {
-    g_mutex_lock(&g_murphy_glue_callback_lock);
     io_t           *io     = (io_t *)user_data;
+    glib_glue_t *glue = (glib_glue_t *)io->glue_data;
+    glue_ref(glue);
+    g_mutex_lock(&glue->glue_callback_lock);
     mrp_io_event_t  events = MRP_IO_EVENT_NONE;
     int             fd     = g_io_channel_unix_get_fd(ioc);
 
@@ -159,7 +198,8 @@ static gboolean io_cb(GIOChannel *ioc, GIOCondition cond, gpointer user_data)
 
     io->cb(io->glue_data, io, fd, events, io->user_data);
 
-    g_mutex_unlock(&g_murphy_glue_callback_lock);
+    g_mutex_unlock(&glue->glue_callback_lock);
+    glue_unref(glue);
     return TRUE;
 }
 
@@ -172,12 +212,13 @@ static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
     GIOCondition  mask = 0;
     GIOChannel   *ioc;
     io_t         *io;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     ioc = g_io_channel_unix_new(fd);
 
     if (ioc == NULL) {
-        g_mutex_unlock(&g_murphy_glue_internal_lock);
+        g_mutex_unlock(&glue->glue_internal_lock);
         return NULL;
     }
 
@@ -199,7 +240,7 @@ static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
             io->user_data = user_data;
             io->glue_data = glue_data;
 
-            g_mutex_unlock(&g_murphy_glue_internal_lock);
+            g_mutex_unlock(&glue->glue_internal_lock);
             return io;
         }
         else {
@@ -208,7 +249,7 @@ static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
         }
     }
 
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
     return NULL;
 }
 
@@ -216,12 +257,13 @@ static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
 static void del_io(void *glue_data, void *id)
 {
     io_t *io = (io_t *)id;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     remove_source(glue_data, io->gl_iow);
     g_io_channel_unref(io->gl_ioc);
     mrp_free(io);
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
 }
 
 
@@ -231,17 +273,21 @@ static gboolean timer_cb(gpointer user_data)
         return FALSE;
     }
 
-    g_mutex_lock(&g_murphy_glue_callback_lock);
     tmr_t *t = (tmr_t *)user_data;
+    glib_glue_t *glue = (glib_glue_t *)t->glue_data;
+    glue_ref(glue);
+    g_mutex_lock(&glue->glue_callback_lock);
 
     if (t->cb == NULL) {
-        g_mutex_unlock(&g_murphy_glue_callback_lock);
+        g_mutex_unlock(&glue->glue_callback_lock);
+        glue_unref(glue);
         return FALSE;
     }
 
     t->cb(t->glue_data, t, t->user_data);
 
-    g_mutex_unlock(&g_murphy_glue_callback_lock);
+    g_mutex_unlock(&glue->glue_callback_lock);
+    glue_unref(glue);
     return TRUE;
 }
 
@@ -251,8 +297,9 @@ static void *add_timer(void *glue_data, unsigned int msecs,
                        void *user_data)
 {
     tmr_t *t;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     t = mrp_allocz(sizeof(*t));
 
     if (t != NULL) {
@@ -263,14 +310,14 @@ static void *add_timer(void *glue_data, unsigned int msecs,
             t->user_data = user_data;
             t->glue_data = glue_data;
 
-            g_mutex_unlock(&g_murphy_glue_internal_lock);
+            g_mutex_unlock(&glue->glue_internal_lock);
             return t;
         }
         else
             mrp_free(t);
     }
 
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
     return NULL;
 }
 
@@ -278,24 +325,26 @@ static void *add_timer(void *glue_data, unsigned int msecs,
 static void del_timer(void *glue_data, void *id)
 {
     tmr_t *t = (tmr_t *)id;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     remove_source(glue_data, t->gl_t);
     mrp_free(t);
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
 }
 
 
 static void mod_timer(void *glue_data, void *id, unsigned int msecs)
 {
     tmr_t  *t = (tmr_t *)id;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     if (t != NULL) {
         remove_source(glue_data, t->gl_t);
         t->gl_t = add_timeout(glue_data, (GSourceFunc)timer_cb, msecs, t);
     }
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
 }
 
 
@@ -305,17 +354,21 @@ static gboolean defer_cb(void *user_data)
         return FALSE;
     }
 
-    g_mutex_lock(&g_murphy_glue_callback_lock);
     dfr_t *d = (dfr_t *)user_data;
+    glib_glue_t *glue = (glib_glue_t *)d->glue_data;
+    glue_ref(glue);
+    g_mutex_lock(&glue->glue_callback_lock);
 
     if (d->cb == NULL) {
-        g_mutex_unlock(&g_murphy_glue_callback_lock);
+        g_mutex_unlock(&glue->glue_callback_lock);
+        glue_unref(glue);
         return FALSE;
     }
 
     d->cb(d->glue_data, d, d->user_data);
 
-    g_mutex_unlock(&g_murphy_glue_callback_lock);
+    g_mutex_unlock(&glue->glue_callback_lock);
+    glue_unref(glue);
     return TRUE;
 }
 
@@ -325,8 +378,9 @@ static void *add_defer(void *glue_data,
                        void *user_data)
 {
     dfr_t *d;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     d = mrp_allocz(sizeof(*d));
 
     if (d != NULL) {
@@ -337,14 +391,14 @@ static void *add_defer(void *glue_data,
             d->user_data = user_data;
             d->glue_data = glue_data;
 
-            g_mutex_unlock(&g_murphy_glue_internal_lock);
+            g_mutex_unlock(&glue->glue_internal_lock);
             return d;
         }
         else
             mrp_free(d);
     }
 
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
     return NULL;
 }
 
@@ -352,25 +406,27 @@ static void *add_defer(void *glue_data,
 static void del_defer(void *glue_data, void *id)
 {
     dfr_t *d = (dfr_t *)id;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     if (d->gl_t != 0)
         remove_source(glue_data, d->gl_t);
 
     mrp_free(d);
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
 }
 
 
 static void mod_defer(void *glue_data, void *id, int enabled)
 {
     dfr_t *d = (dfr_t *)id;
+    glib_glue_t *glue = (glib_glue_t *)glue_data;
 
     if (d == NULL) {
         return;
     }
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     if (enabled && !d->gl_t) {
         d->gl_t = add_timeout(glue_data, (GSourceFunc)defer_cb, 0, d);
     }
@@ -378,7 +434,7 @@ static void mod_defer(void *glue_data, void *id, int enabled)
         remove_source(glue_data, d->gl_t);
         d->gl_t = 0;
     }
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
 }
 
 
@@ -387,7 +443,7 @@ static void unregister(void *data)
     glib_glue_t *glue = (glib_glue_t *)data;
     GMainContext *def_ctx = g_main_context_default();
     GMainContext *loop_ctx = g_main_loop_get_context(glue->gml);
-    g_mutex_lock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
     if (loop_ctx && def_ctx != loop_ctx) {
         GSource *idle = g_idle_source_new();
         gint64 end_time = 0;
@@ -398,7 +454,7 @@ static void unregister(void *data)
         g_source_attach(idle, g_main_loop_get_context(glue->gml));
         g_source_unref(idle);
         end_time = g_get_monotonic_time() + MURPHY_LOOP_WAIT_TIME_THREAD * G_TIME_SPAN_SECOND;
-        if (g_cond_wait_until(&g_murphy_loop_cond, &g_murphy_glue_internal_lock, end_time)) {
+        if (g_cond_wait_until(&glue->loop_cond, &glue->glue_internal_lock, end_time)) {
             g_thread_join(glue->worker);
             glue->worker = NULL;
         }
@@ -409,8 +465,8 @@ static void unregister(void *data)
         glue->gml = NULL;
     }
 
-    mrp_free(glue);
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_unlock(&glue->glue_internal_lock);
+    glue_unref(glue);
 }
 
 
@@ -439,9 +495,9 @@ thread_main (gpointer data)
 
     g_main_context_pop_thread_default (thread_main_context);
 
-    g_mutex_lock(&g_murphy_glue_internal_lock);
-    g_cond_signal(&g_murphy_loop_cond);
-    g_mutex_unlock(&g_murphy_glue_internal_lock);
+    g_mutex_lock(&glue->glue_internal_lock);
+    g_cond_signal(&glue->loop_cond);
+    g_mutex_unlock(&glue->glue_internal_lock);
 
     return NULL;
 }
@@ -450,7 +506,7 @@ int mrp_mainloop_register_with_glib(mrp_mainloop_t *ml, GMainLoop *gml)
 {
     glib_glue_t *glue;
 
-    glue = mrp_allocz(sizeof(*glue));
+    glue = glue_new();
 
     if (glue != NULL) {
         glue->gml = g_main_loop_ref(gml);
@@ -463,17 +519,15 @@ int mrp_mainloop_register_with_glib(mrp_mainloop_t *ml, GMainLoop *gml)
             if (loop_ctx && def_ctx != loop_ctx) {
                 glue->worker = g_thread_try_new(NULL, thread_main, glue, NULL);
                 if (glue->worker == NULL) {
-                    g_main_loop_unref(gml);
-                    mrp_free(glue);
+                    mrp_log_error("Thread creation failed");
                     return FALSE;
                 }
             }
             return TRUE;
         }
-        else {
-            g_main_loop_unref(gml);
-            mrp_free(glue);
-        }
+        mrp_log_error("Failed to set operation to superloop");
+        g_main_loop_unref(gml);
+        glue_unref(glue);
     }
 
     return FALSE;
@@ -503,19 +557,3 @@ mrp_mainloop_t *mrp_mainloop_glib_get(GMainLoop *gml)
 
     return NULL;
 }
-
-
-MRP_INIT static void mrp_main_loop_init_lock()
-{
-    g_mutex_init(&g_murphy_glue_callback_lock);
-    g_mutex_init(&g_murphy_glue_internal_lock);
-    g_cond_init(&g_murphy_loop_cond);
-}
-
-
-MRP_EXIT static void mrp_main_loop_clear_lock()
-{
-    g_mutex_clear(&g_murphy_glue_callback_lock);
-    g_mutex_clear(&g_murphy_glue_internal_lock);
-    g_cond_clear(&g_murphy_loop_cond);
-}
index 6519c9d3d6bac75976e5bb3c7c7ad3f86db605ad..cff438512a9fdaf616b05e91e0163ea87610b347 100644 (file)
@@ -2043,7 +2043,9 @@ static void dispatch_wakeup(mrp_mainloop_t *ml)
 
         if (!is_deleted(w)) {
             mrp_debug("dispatching wakeup cb %p", w);
+            pthread_mutex_unlock(&ml->lock);
             wakeup_cb(w, event, now);
+            pthread_mutex_lock(&ml->lock);
         }
         else
             mrp_debug("skipping deleted wakeup cb %p", w);
@@ -2064,7 +2066,9 @@ static void dispatch_deferred(mrp_mainloop_t *ml)
 
         if (!is_deleted(d) && !d->inactive) {
             mrp_debug("dispatching active deferred cb %p", d);
+            pthread_mutex_unlock(&ml->lock);
             d->cb(d, d->user_data);
+            pthread_mutex_lock(&ml->lock);
         }
         else
             mrp_debug("skipping %s deferred cb %p",
@@ -2094,7 +2098,9 @@ static void dispatch_timers(mrp_mainloop_t *ml)
             if (t->expire <= now) {
                 mrp_debug("dispatching expired timer %p", t);
 
+                pthread_mutex_unlock(&ml->lock);
                 t->cb(t, t->user_data);
+                pthread_mutex_lock(&ml->lock);
 
                 if (!is_deleted(t))
                     rearm_timer(t);
@@ -2177,7 +2183,9 @@ static void dispatch_poll_events(mrp_mainloop_t *ml)
 
         if (!is_deleted(w)) {
             mrp_debug("dispatching I/O watch %p (fd %d)", w, fd);
+            pthread_mutex_unlock(&ml->lock);
             w->cb(w, w->fd, e->events, w->user_data);
+            pthread_mutex_lock(&ml->lock);
         }
         else
             mrp_debug("skipping deleted I/O watch %p (fd %d)", w, fd);