X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftdm_event_loop.c;h=29a97636fafd5cf7734b53754b0f4fd5036efaed;hb=02d2100670785551b95cde50a3cf0f0ee395031a;hp=e0791ab9eecf6ac5dba7d23086f6b5e3526525bc;hpb=61d122abfd323a39d4ed597ab625aa2cb2c913f6;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index e0791ab..29a9763 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -1,36 +1,36 @@ /************************************************************************** - -libtdm - -Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Eunchul Kim , - JinYoung Jeon , - Taeheon Kim , - YoungJun Cho , - SooChan Lim , - Boram Park - -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 , + * JinYoung Jeon , + * Taeheon Kim , + * YoungJun Cho , + * SooChan Lim , + * Boram Park + * + * 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 -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;