fix the too many logs when enabled
[platform/core/uifw/libtdm.git] / src / tdm_event_loop.c
index e0791ab..29a9763 100644 (file)
@@ -1,36 +1,36 @@
 /**************************************************************************
-
-libtdm
-
-Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
-
-Contact: Eunchul Kim <chulspro.kim@samsung.com>,
-         JinYoung Jeon <jy0.jeon@samsung.com>,
-         Taeheon Kim <th908.kim@samsung.com>,
-         YoungJun Cho <yj44.cho@samsung.com>,
-         SooChan Lim <sc1.lim@samsung.com>,
-         Boram Park <sc1.lim@samsung.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
+ *
+ * libtdm
+ *
+ * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
*          JinYoung Jeon <jy0.jeon@samsung.com>,
*          Taeheon Kim <th908.kim@samsung.com>,
*          YoungJun Cho <yj44.cho@samsung.com>,
*          SooChan Lim <sc1.lim@samsung.com>,
*          Boram Park <sc1.lim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
 **************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -43,21 +43,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <wayland-server-core.h>
 
-typedef struct _tdm_event_loop_source_base
-{
+typedef struct _tdm_event_loop_source_base {
        struct wl_event_source *wl_source;
 } tdm_event_loop_source_base;
 
-typedef struct _tdm_event_loop_source_fd
-{
+typedef struct _tdm_event_loop_source_fd {
        tdm_event_loop_source_base base;
        tdm_private_display *private_display;
        tdm_event_loop_fd_handler func;
        void *user_data;
 } tdm_event_loop_source_fd;
 
-typedef struct _tdm_event_loop_source_timer
-{
+typedef struct _tdm_event_loop_source_timer {
        tdm_event_loop_source_base base;
        tdm_private_display *private_display;
        tdm_event_loop_timer_handler func;
@@ -72,12 +69,13 @@ _tdm_event_loop_main_fd_handler(int fd, tdm_event_loop_mask mask, void *user_dat
        tdm_func_display *func_display;
        tdm_error ret;
 
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
        TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
        TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
 
        private_loop = private_display->private_loop;
 
-       if (tdm_debug_thread)
+       if (tdm_debug_module & TDM_DEBUG_THREAD)
                TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd);
 
        func_display = &private_display->func_display;
@@ -95,10 +93,12 @@ tdm_event_loop_init(tdm_private_display *private_display)
        tdm_private_loop *private_loop;
        tdm_error ret;
 
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
+
        if (private_display->private_loop)
                return TDM_ERROR_NONE;
 
-       private_loop = calloc(1, sizeof *private_loop);
+       private_loop = calloc(1, sizeof * private_loop);
        if (!private_loop) {
                TDM_ERR("alloc failed");
                return TDM_ERROR_OUT_OF_MEMORY;
@@ -142,9 +142,12 @@ tdm_event_loop_init(tdm_private_display *private_display)
 INTERN void
 tdm_event_loop_deinit(tdm_private_display *private_display)
 {
+       TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
        if (!private_display->private_loop)
                return;
 
+       /* after tdm_thread_deinit, we don't worry about thread things because it's finalized */
        tdm_thread_deinit(private_display->private_loop);
        tdm_server_deinit(private_display->private_loop);
 
@@ -166,6 +169,7 @@ tdm_event_loop_create_backend_source(tdm_private_display *private_display)
        tdm_error ret;
        int fd = -1;
 
+       TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
        TDM_RETURN_IF_FAIL(private_loop != NULL);
 
        func_display = &private_display->func_display;
@@ -176,7 +180,7 @@ tdm_event_loop_create_backend_source(tdm_private_display *private_display)
 
        ret = func_display->display_get_fd(private_display->bdata, &fd);
        if (fd < 0) {
-               TDM_WRN("TDM backend module returns fd(%d)", fd);
+               TDM_ERR("TDM backend module returns fd(%d)", fd);
                return;
        }
 
@@ -187,9 +191,9 @@ tdm_event_loop_create_backend_source(tdm_private_display *private_display)
 
        private_loop->backend_source =
                tdm_event_loop_add_fd_handler(private_display, fd,
-                                             TDM_EVENT_LOOP_READABLE,
-                                             _tdm_event_loop_main_fd_handler,
-                                             private_display, &ret);
+                                                                         TDM_EVENT_LOOP_READABLE,
+                                                                         _tdm_event_loop_main_fd_handler,
+                                                                         private_display, &ret);
        if (!private_loop->backend_source) {
                TDM_ERR("no backend fd(%d) source", fd);
                return;
@@ -205,6 +209,8 @@ tdm_event_loop_get_fd(tdm_private_display *private_display)
 {
        tdm_private_loop *private_loop = private_display->private_loop;
 
+       /* DON'T check TDM_MUTEX_IS_LOCKED here */
+
        TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, -1);
 
        return wl_event_loop_get_fd(private_loop->wl_loop);
@@ -215,11 +221,19 @@ tdm_event_loop_dispatch(tdm_private_display *private_display)
 {
        tdm_private_loop *private_loop = private_display->private_loop;
 
+       /* DON'T check TDM_MUTEX_IS_LOCKED here */
+
        TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, TDM_ERROR_OPERATION_FAILED);
 
-       if (tdm_debug_thread)
+       if (tdm_debug_module & TDM_DEBUG_THREAD)
                TDM_INFO("dispatch");
 
+       if (tdm_thread_is_running() &&
+               tdm_thread_in_display_thread(syscall(SYS_gettid))) {
+               TDM_NEVER_GET_HERE();
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
        /* Don't set timeout to -1. It can make deadblock by two mutex locks.
         * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
         * escaping polling.
@@ -227,6 +241,8 @@ tdm_event_loop_dispatch(tdm_private_display *private_display)
        if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
                TDM_ERR("dispatch failed");
 
+       wl_display_flush_clients(private_loop->wl_display);
+
        return TDM_ERROR_NONE;
 }
 
@@ -236,8 +252,16 @@ tdm_event_loop_flush(tdm_private_display *private_display)
 {
        tdm_private_loop *private_loop = private_display->private_loop;
 
+       /* DON'T check TDM_MUTEX_IS_LOCKED here */
+
        TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
 
+       if (tdm_thread_is_running() &&
+               tdm_thread_in_display_thread(syscall(SYS_gettid))) {
+               TDM_NEVER_GET_HERE();
+               return;
+       }
+
        wl_display_flush_clients(private_loop->wl_display);
 }
 
@@ -245,11 +269,16 @@ static int
 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
 {
        tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
+       tdm_private_display *private_display;
        tdm_event_loop_mask mask = 0;
 
+       /* DON'T check TDM_MUTEX_IS_LOCKED here */
+
        TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
        TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
 
+       private_display = fd_source->private_display;
+
        if (wl_mask & WL_EVENT_READABLE)
                mask |= TDM_EVENT_LOOP_READABLE;
        if (wl_mask & WL_EVENT_WRITABLE)
@@ -259,15 +288,17 @@ _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
        if (wl_mask & WL_EVENT_ERROR)
                mask |= TDM_EVENT_LOOP_ERROR;
 
+       _pthread_mutex_lock(&private_display->lock);
        fd_source->func(fd, mask, fd_source->user_data);
+       _pthread_mutex_unlock(&private_display->lock);
 
        return 1;
 }
 
-EXTERN tdm_event_loop_source*
+EXTERN tdm_event_loop_source *
 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
-                              tdm_event_loop_fd_handler func, void *user_data,
-                              tdm_error *error)
+                                                         tdm_event_loop_fd_handler func, void *user_data,
+                                                         tdm_error *error)
 {
        tdm_private_display *private_display;
        tdm_private_loop *private_loop;
@@ -275,6 +306,7 @@ tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask
        uint32_t wl_mask = 0;
        tdm_error ret;
 
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
        TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
        TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
        TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
@@ -294,7 +326,7 @@ tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask
 
        fd_source->base.wl_source =
                wl_event_loop_add_fd(private_loop->wl_loop,
-                                    fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
+                                                        fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
        if (!fd_source->base.wl_source) {
                if (error)
                        *error = TDM_ERROR_OUT_OF_MEMORY;
@@ -309,7 +341,7 @@ tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask
        if (error)
                *error = TDM_ERROR_NONE;
 
-       return (tdm_event_loop_source*)fd_source;
+       return (tdm_event_loop_source *)fd_source;
 }
 
 EXTERN tdm_error
@@ -318,6 +350,7 @@ tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_ma
        tdm_event_loop_source_fd *fd_source = source;
        uint32_t wl_mask = 0;
 
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
        TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
 
        if (mask & TDM_EVENT_LOOP_READABLE)
@@ -337,24 +370,36 @@ static int
 _tdm_event_loop_timer_func(void *data)
 {
        tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
+       tdm_private_display *private_display;
+
+       /* DON'T check TDM_MUTEX_IS_LOCKED here */
 
        TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
        TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
 
+       private_display = timer_source->private_display;
+
+       /* TDM event_loop function is actually for TDM backend module. When we call the
+        * backend's functions, we have to lock the mutex. TDM backend shouldn't consider
+        * mutex things.
+        */
+       _pthread_mutex_lock(&private_display->lock);
        timer_source->func(timer_source->user_data);
+       _pthread_mutex_unlock(&private_display->lock);
 
        return 1;
 }
 
-EXTERN tdm_event_loop_source*
+EXTERN tdm_event_loop_source *
 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
-                                 void *user_data, tdm_error *error)
+                                                                void *user_data, tdm_error *error)
 {
        tdm_private_display *private_display;
        tdm_private_loop *private_loop;
        tdm_event_loop_source_timer *timer_source;
        tdm_error ret;
 
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
        TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
        TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
 
@@ -368,7 +413,7 @@ tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler
 
        timer_source->base.wl_source =
                wl_event_loop_add_timer(private_loop->wl_loop,
-                                       _tdm_event_loop_timer_func, timer_source);
+                                                               _tdm_event_loop_timer_func, timer_source);
        if (!timer_source->base.wl_source) {
                if (error)
                        *error = TDM_ERROR_OUT_OF_MEMORY;
@@ -383,14 +428,15 @@ tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler
        if (error)
                *error = TDM_ERROR_NONE;
 
-       return (tdm_event_loop_source*)timer_source;
+       return (tdm_event_loop_source *)timer_source;
 }
 
 EXTERN tdm_error
-tdm_event_loop_source_timer_update(tdm_event_loop_source *source, int ms_delay)
+tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int ms_delay)
 {
        tdm_event_loop_source_timer *timer_source = source;
 
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
        TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
 
        if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
@@ -406,6 +452,8 @@ tdm_event_loop_source_remove(tdm_event_loop_source *source)
 {
        tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
 
+       TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
        if (!base)
                return;