From c14e6187bd2683333d78671364d8a30392f29d45 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 20 Apr 2016 18:52:46 +0900 Subject: [PATCH 01/16] fix segfault when the vblank resource is gone Change-Id: I4acfe93a46d85dcdcc4db81d79d78b8165b88a9e --- src/tdm_server.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tdm_server.c b/src/tdm_server.c index a8d0498..c824905 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -57,6 +57,8 @@ typedef struct _tdm_server_vblank_info { tdm_private_server *private_server; } tdm_server_vblank_info; +static tdm_private_loop *keep_private_loop; + static void _tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, @@ -65,7 +67,10 @@ _tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence, tdm_server_vblank_info *vblank_info = (tdm_server_vblank_info*)user_data; tdm_server_vblank_info *found; - LIST_FIND_ITEM(vblank_info, &vblank_info->private_server->vblank_list, + if (!keep_private_loop || !keep_private_loop->private_server) + return; + + LIST_FIND_ITEM(vblank_info, &keep_private_loop->private_server->vblank_list, tdm_server_vblank_info, link, found); if (!found) { TDM_DBG("vblank_info(%p) is destroyed", vblank_info); @@ -222,6 +227,7 @@ tdm_server_init(tdm_private_loop *private_loop) } private_loop->private_server = private_server; + keep_private_loop = private_loop; return TDM_ERROR_NONE; } @@ -243,4 +249,5 @@ tdm_server_deinit(tdm_private_loop *private_loop) free(private_server); private_loop->private_server = NULL; + keep_private_loop = NULL; } -- 2.7.4 From facfa524ba5d1e21ee25e71596bd62237bc60457 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 11:01:35 +0900 Subject: [PATCH 02/16] print log with color red - error yellow - warning green - info white - debug Change-Id: I9861b058efefc40c5d04677d5c1f952c959ffe60 --- include/tdm_log.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/tdm_log.h b/include/tdm_log.h index cddf0e6..841cde2 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -109,6 +109,11 @@ extern int tdm_debug; #include +#define COLOR_RED "\x1b[31m" /* for error */ +#define COLOR_YELLOW "\x1b[33m" /* for warning */ +#define COLOR_GREEN "\x1b[32m" /* for info */ +#define COLOR_RESET "\x1b[0m" + #define TDM_DBG(fmt, args...) \ if (tdm_debug) \ do { \ @@ -122,7 +127,7 @@ extern int tdm_debug; do { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - printf("[TDM_INF][%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ + printf(COLOR_GREEN"[TDM_INF]"COLOR_RESET"[%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ (int)ts.tv_nsec / 1000, (int)syscall(SYS_gettid), __func__, __LINE__, ##args); \ } while (0); @@ -130,7 +135,7 @@ extern int tdm_debug; do { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - printf("[TDM_WRN][%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ + printf(COLOR_YELLOW"[TDM_WRN]"COLOR_RESET"[%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ (int)ts.tv_nsec / 1000, (int)syscall(SYS_gettid), __func__, __LINE__, ##args); \ } while (0); @@ -138,7 +143,7 @@ extern int tdm_debug; do { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - printf("[TDM_ERR][%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ + printf(COLOR_RED"[TDM_ERR]"COLOR_RESET"[%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ (int)ts.tv_nsec / 1000, (int)syscall(SYS_gettid), __func__, __LINE__, ##args); \ } while (0); -- 2.7.4 From acab1c4c70fb532947a941c3514249346a07e338 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 15:35:13 +0900 Subject: [PATCH 03/16] assertion if there is error or warning Change-Id: Ie2a0586b28fd54bf6712603b2c316c3845d23869 --- include/tdm_log.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/tdm_log.h b/include/tdm_log.h index 841cde2..ebfa1d7 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -43,6 +43,7 @@ extern "C" { #include #include +#include #include @@ -59,6 +60,15 @@ extern "C" { extern int tdm_debug; //#define TDM_CONFIG_DLOG +//#define TDM_CONFIG_ASSERT + +#undef TDM_ASSERT +#ifdef TDM_CONFIG_ASSERT +#define TDM_ASSERT(o) assert(o) +#else +#define TDM_ASSERT(o) +#endif + #ifdef TDM_CONFIG_DLOG #include @@ -137,6 +147,7 @@ extern int tdm_debug; clock_gettime(CLOCK_MONOTONIC, &ts); \ printf(COLOR_YELLOW"[TDM_WRN]"COLOR_RESET"[%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ (int)ts.tv_nsec / 1000, (int)syscall(SYS_gettid), __func__, __LINE__, ##args); \ + TDM_ASSERT(0); \ } while (0); #define TDM_ERR(fmt, args...) \ @@ -145,6 +156,7 @@ extern int tdm_debug; clock_gettime(CLOCK_MONOTONIC, &ts); \ printf(COLOR_RED"[TDM_ERR]"COLOR_RESET"[%d.%06d][%d][%s %d] "fmt"\n", (int)ts.tv_sec, \ (int)ts.tv_nsec / 1000, (int)syscall(SYS_gettid), __func__, __LINE__, ##args); \ + TDM_ASSERT(0); \ } while (0); #endif /* TDM_CONFIG_DLOG */ -- 2.7.4 From 079e504c8b39826dbc840df05a3a41bef876ae72 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 15:43:47 +0900 Subject: [PATCH 04/16] fix deadlock and enhance lock/unlock to protect the backend module's data Change-Id: I4e057d3238779702af5e878be96ecb9c33573d10 --- src/tdm.c | 9 +++++++ src/tdm_backend.c | 20 +++++++------- src/tdm_buffer.c | 3 +++ src/tdm_capture.c | 29 ++++++++++---------- src/tdm_display.c | 75 ++++++++++++---------------------------------------- src/tdm_event_loop.c | 32 ++++++++++++++++++++++ src/tdm_helper.c | 25 ------------------ src/tdm_pp.c | 31 ++++++++++------------ src/tdm_private.h | 50 ++++++++++++++++++++++++++--------- src/tdm_server.c | 12 ++++----- src/tdm_thread.c | 36 ++++++++++++++++++++----- 11 files changed, 172 insertions(+), 150 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index 24ee038..cc21a1f 100755 --- a/src/tdm.c +++ b/src/tdm.c @@ -42,6 +42,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdm_private.h" #include "tdm_helper.h" +pthread_mutex_t tdm_mutex_check_lock = PTHREAD_MUTEX_INITIALIZER; +int tdm_mutex_locked; + static tdm_private_layer * _tdm_display_find_private_layer(tdm_private_output *private_output, tdm_layer *layer_backend) @@ -784,6 +787,8 @@ tdm_display_init(tdm_error *error) goto failed_mutex_init; } + _pthread_mutex_lock(&private_display->lock); + ret = tdm_event_loop_init(private_display); if (ret != TDM_ERROR_NONE) goto failed_event; @@ -821,6 +826,7 @@ tdm_display_init(tdm_error *error) if (error) *error = TDM_ERROR_NONE; + _pthread_mutex_unlock(&private_display->lock); _pthread_mutex_unlock(&gLock); return (tdm_display *)private_display; @@ -830,6 +836,7 @@ failed_update: failed_load: tdm_event_loop_deinit(private_display); failed_event: + _pthread_mutex_unlock(&private_display->lock); pthread_mutex_destroy(&private_display->lock); failed_mutex_init: free(private_display); @@ -881,5 +888,7 @@ tdm_display_deinit(tdm_display *dpy) tdm_debug_buffer = 0; _pthread_mutex_unlock(&gLock); + + TDM_INFO("done"); } diff --git a/src/tdm_backend.c b/src/tdm_backend.c index 9dfa2d1..d7cfc8d 100644 --- a/src/tdm_backend.c +++ b/src/tdm_backend.c @@ -69,6 +69,8 @@ tdm_backend_register_func_display(tdm_display *dpy, { tdm_backend_module *module; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + BACKEND_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -78,9 +80,7 @@ tdm_backend_register_func_display(tdm_display *dpy, if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - _pthread_mutex_lock(&private_display->lock); private_display->func_display = *func_display; - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } @@ -90,6 +90,8 @@ tdm_backend_register_func_output(tdm_display *dpy, tdm_func_output *func_output) { tdm_backend_module *module; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + BACKEND_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(func_output != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -99,9 +101,7 @@ tdm_backend_register_func_output(tdm_display *dpy, tdm_func_output *func_output) if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - _pthread_mutex_lock(&private_display->lock); private_display->func_output = *func_output; - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } @@ -111,6 +111,8 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer) { tdm_backend_module *module; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + BACKEND_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(func_layer != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -120,9 +122,7 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer) if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - _pthread_mutex_lock(&private_display->lock); private_display->func_layer = *func_layer; - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } @@ -130,15 +130,15 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer) EXTERN tdm_error tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp) { + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + BACKEND_FUNC_ENTRY(); if (!func_pp) return TDM_ERROR_NONE; - _pthread_mutex_lock(&private_display->lock); private_display->capabilities |= TDM_DISPLAY_CAPABILITY_PP; private_display->func_pp = *func_pp; - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } @@ -147,15 +147,15 @@ EXTERN tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture) { + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + BACKEND_FUNC_ENTRY(); if (!func_capture) return TDM_ERROR_NONE; - _pthread_mutex_lock(&private_display->lock); private_display->capabilities |= TDM_DISPLAY_CAPABILITY_CAPTURE; private_display->func_capture = *func_capture; - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index 50a94be..a394fe7 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -196,6 +196,9 @@ tdm_buffer_unref_backend(tbm_surface_h buffer) return; } + if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) + TDM_NEVER_GET_HERE(); + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { tbm_surface_internal_ref(buffer); func_info->release_func(buffer, func_info->user_data); diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 411d209..1a73db4 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -82,8 +82,8 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, tdm_private_display *private_display = private_capture->private_display; tdm_buffer_info *buf_info; tbm_surface_h first_entry; - int lock_after_cb_done = 0; - int ret; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); if (private_capture->owner_tid != syscall(SYS_gettid)) { tdm_thread_cb_capture_done capture_done; @@ -114,18 +114,9 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, if ((buf_info = tdm_buffer_get_info(buffer))) LIST_DEL(&buf_info->link); - ret = pthread_mutex_trylock(&private_display->lock); - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - lock_after_cb_done = 1; - } - + _pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(buffer); - - if (lock_after_cb_done) - _pthread_mutex_lock(&private_display->lock); + _pthread_mutex_lock(&private_display->lock); } INTERN tdm_private_capture * @@ -133,6 +124,8 @@ tdm_capture_find_stamp(tdm_private_display *private_display, unsigned long stamp { tdm_private_capture *private_capture = NULL; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) { if (private_capture->stamp == stamp) return private_capture; @@ -152,6 +145,8 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, tdm_capture *capture_backend = NULL; tdm_error ret = TDM_ERROR_NONE; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { TDM_ERR("no capture capability"); if (error) @@ -221,6 +216,8 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, tdm_capture *capture_backend = NULL; tdm_error ret = TDM_ERROR_NONE; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { TDM_ERR("no capture capability"); if (error) @@ -272,6 +269,8 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) tdm_func_capture *func_capture; tdm_buffer_info *b = NULL, *bb = NULL; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + if (!private_capture) return; @@ -282,7 +281,7 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) func_capture->capture_destroy(private_capture->capture_backend); if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) { - TDM_ERR("capture(%p) not finished:", private_capture); + TDM_WRN("capture(%p) not finished:", private_capture); tdm_buffer_list_dump(&private_capture->pending_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) { @@ -294,7 +293,7 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) } if (!LIST_IS_EMPTY(&private_capture->buffer_list)) { - TDM_ERR("capture(%p) not finished:", private_capture); + TDM_WRN("capture(%p) not finished:", private_capture); tdm_buffer_list_dump(&private_capture->buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) { diff --git a/src/tdm_display.c b/src/tdm_display.c index a7a1327..4a2d25e 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -341,11 +341,8 @@ tdm_display_get_fd(tdm_display *dpy, int *fd) _pthread_mutex_lock(&private_display->lock); - if (private_display->private_loop->private_thread) { - _pthread_mutex_unlock(&private_display->lock); + if (tdm_thread_is_running()) *fd = tdm_thread_get_fd(private_display->private_loop); - _pthread_mutex_lock(&private_display->lock); - } else *fd = tdm_event_loop_get_fd(private_display); @@ -384,18 +381,11 @@ tdm_display_handle_events(tdm_display *dpy) if (tdm_debug_thread) TDM_INFO("fd(%d) polling out", fd); - _pthread_mutex_lock(&private_display->lock); - - if (private_display->private_loop->private_thread) { - _pthread_mutex_unlock(&private_display->lock); + if (tdm_thread_is_running()) ret = tdm_thread_handle_cb(private_display->private_loop); - _pthread_mutex_lock(&private_display->lock); - } else ret = tdm_event_loop_dispatch(private_display); - _pthread_mutex_unlock(&private_display->lock); - return ret; } @@ -458,15 +448,13 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, tdm_private_display *private_display; tdm_private_output *private_output = user_data; tdm_value value; - int lock_after_cb_done = 0; - int ret; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(private_output); private_display = private_output->private_display; - if (!tdm_thread_in_display_thread(private_display->private_loop, - syscall(SYS_gettid))) { + if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { tdm_thread_cb_output_status output_status; tdm_error ret; @@ -488,22 +476,11 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, return; } - ret = pthread_mutex_trylock(&private_display->lock); - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - lock_after_cb_done = 1; - } - value.u32 = status; tdm_output_call_change_handler_internal(private_output, &private_output->change_handler_list_main, TDM_OUTPUT_CHANGE_CONNECTION, value); - - if (lock_after_cb_done) - _pthread_mutex_lock(&private_display->lock); } EXTERN tdm_error @@ -536,8 +513,7 @@ tdm_output_add_change_handler(tdm_output *output, change_handler->user_data = user_data; change_handler->owner_tid = syscall(SYS_gettid); - if (!tdm_thread_in_display_thread(private_display->private_loop, - change_handler->owner_tid)) + if (!tdm_thread_in_display_thread(change_handler->owner_tid)) LIST_ADD(&change_handler->link, &private_output->change_handler_list_sub); else LIST_ADD(&change_handler->link, &private_output->change_handler_list_main); @@ -826,6 +802,7 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, tdm_private_vblank_handler *vblank_handler = user_data; tdm_private_display *private_display; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(vblank_handler); private_display = vblank_handler->private_output->private_display; @@ -852,22 +829,10 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, TDM_NEVER_GET_HERE(); if (vblank_handler->func) { - int lock_after_cb_done = 0; - int ret; - - ret = pthread_mutex_trylock(&private_display->lock); - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - lock_after_cb_done = 1; - } - + _pthread_mutex_unlock(&private_display->lock); vblank_handler->func(vblank_handler->private_output, sequence, tv_sec, tv_usec, vblank_handler->user_data); - - if (lock_after_cb_done) - _pthread_mutex_lock(&private_display->lock); + _pthread_mutex_lock(&private_display->lock); } LIST_DEL(&vblank_handler->link); @@ -882,9 +847,8 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, tdm_private_display *private_display; tdm_private_output *private_output; tdm_private_layer *private_layer = NULL; - int lock_after_cb_done = 0; - int ret; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(commit_handler); private_output = commit_handler->private_output; @@ -908,20 +872,14 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, return; } - ret = pthread_mutex_trylock(&private_display->lock); - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - lock_after_cb_done = 1; - } - LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { if (!private_layer->waiting_buffer) continue; if (private_layer->showing_buffer) { + _pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(private_layer->showing_buffer); + _pthread_mutex_lock(&private_display->lock); if (private_layer->buffer_queue) { tbm_surface_queue_release(private_layer->buffer_queue, @@ -939,12 +897,11 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, } if (commit_handler->func) { + _pthread_mutex_unlock(&private_display->lock); commit_handler->func(private_output, sequence, tv_sec, tv_usec, commit_handler->user_data); - } - - if (lock_after_cb_done) _pthread_mutex_lock(&private_display->lock); + } LIST_DEL(&commit_handler->link); free(commit_handler); @@ -1213,11 +1170,11 @@ tdm_output_call_change_handler_internal(tdm_private_output *private_output, tdm_private_display *private_display; tdm_private_change_handler *change_handler; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(private_output); private_display = private_output->private_display; - if (!tdm_thread_in_display_thread(private_display->private_loop, - syscall(SYS_gettid))) { + if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { if (type & TDM_OUTPUT_CHANGE_CONNECTION) TDM_INFO("output(%d) changed: %s (%d)", private_output->pipe, status_str(value.u32), value.u32); @@ -1233,8 +1190,10 @@ tdm_output_call_change_handler_internal(tdm_private_output *private_output, if (change_handler->owner_tid != syscall(SYS_gettid)) TDM_NEVER_GET_HERE(); + _pthread_mutex_unlock(&private_display->lock); change_handler->func(private_output, type, value, change_handler->user_data); + _pthread_mutex_lock(&private_display->lock); } } diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index e0791ab..a9da07c 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -72,6 +72,7 @@ _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); @@ -95,6 +96,8 @@ 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; @@ -142,6 +145,8 @@ 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; @@ -166,6 +171,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; @@ -205,6 +211,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,6 +223,8 @@ 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) @@ -236,6 +246,8 @@ 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); wl_display_flush_clients(private_loop->wl_display); @@ -245,11 +257,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,7 +276,9 @@ _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; } @@ -275,6 +294,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); @@ -318,6 +338,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,11 +358,18 @@ 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; + + _pthread_mutex_lock(&private_display->lock); timer_source->func(timer_source->user_data); + _pthread_mutex_unlock(&private_display->lock); return 1; } @@ -355,6 +383,7 @@ tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler 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); @@ -391,6 +420,7 @@ tdm_event_loop_source_timer_update(tdm_event_loop_source *source, 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 +436,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; diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 03d13cb..4e6c910 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -19,31 +19,6 @@ static const char *dump_prefix[2] = {"png", "yuv"}; static int *tdm_helper_dump_count; static char *tdm_helper_dump_path; -INTERN int -tdm_helper_unlock_in_cb(tdm_private_display *private_display) -{ - int ret = pthread_mutex_trylock(&private_display->lock); - int need_lock = 0; - - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - need_lock = 1; - } - - return need_lock; -} - -INTERN void -tdm_helper_lock_in_cb(tdm_private_display *private_display, int need_lock) -{ - if (!need_lock) - return; - - _pthread_mutex_lock(&private_display->lock); -} - INTERN unsigned long tdm_helper_get_time_in_millis(void) { diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 603911e..0b56073 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -96,8 +96,8 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, tdm_private_display *private_display = private_pp->private_display; tdm_buffer_info *buf_info; tbm_surface_h first_entry; - int lock_after_cb_done = 0; - int ret; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); if (private_pp->owner_tid != syscall(SYS_gettid)) { tdm_thread_cb_pp_done pp_done; @@ -136,19 +136,10 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, if ((buf_info = tdm_buffer_get_info(dst))) LIST_DEL(&buf_info->link); - ret = pthread_mutex_trylock(&private_display->lock); - if (ret == 0) - _pthread_mutex_unlock(&private_display->lock); - else if (ret == EBUSY) { - _pthread_mutex_unlock(&private_display->lock); - lock_after_cb_done = 1; - } - + _pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(src); tdm_buffer_unref_backend(dst); - - if (lock_after_cb_done) - _pthread_mutex_lock(&private_display->lock); + _pthread_mutex_lock(&private_display->lock); } INTERN tdm_private_pp * @@ -156,6 +147,8 @@ tdm_pp_find_stamp(tdm_private_display *private_display, unsigned long stamp) { tdm_private_pp *private_pp = NULL; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + LIST_FOR_EACH_ENTRY(private_pp, &private_display->pp_list, link) { if (private_pp->stamp == stamp) return private_pp; @@ -173,6 +166,8 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) tdm_pp *pp_backend = NULL; tdm_error ret = TDM_ERROR_NONE; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + func_display = &private_display->func_display; func_pp = &private_display->func_pp; @@ -235,6 +230,8 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) tdm_func_pp *func_pp; tdm_buffer_info *b = NULL, *bb = NULL; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + if (!private_pp) return; @@ -246,7 +243,7 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) func_pp->pp_destroy(private_pp->pp_backend); if (!LIST_IS_EMPTY(&private_pp->src_pending_buffer_list)) { - TDM_ERR("pp(%p) not finished:", private_pp); + TDM_WRN("pp(%p) not finished:", private_pp); tdm_buffer_list_dump(&private_pp->src_pending_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) { @@ -258,7 +255,7 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) } if (!LIST_IS_EMPTY(&private_pp->dst_pending_buffer_list)) { - TDM_ERR("pp(%p) not finished:", private_pp); + TDM_WRN("pp(%p) not finished:", private_pp); tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) { @@ -270,7 +267,7 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) } if (!LIST_IS_EMPTY(&private_pp->src_buffer_list)) { - TDM_ERR("pp(%p) not finished:", private_pp); + TDM_WRN("pp(%p) not finished:", private_pp); tdm_buffer_list_dump(&private_pp->src_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_buffer_list, link) { @@ -282,7 +279,7 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) } if (!LIST_IS_EMPTY(&private_pp->dst_buffer_list)) { - TDM_ERR("pp(%p) not finished:", private_pp); + TDM_WRN("pp(%p) not finished:", private_pp); tdm_buffer_list_dump(&private_pp->dst_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_buffer_list, link) { diff --git a/src/tdm_private.h b/src/tdm_private.h index aa19633..7bc3acb 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -229,10 +229,10 @@ struct _tdm_private_capture { }; /* CAUTION: - * Note that this structure is not thread-safe. If there is no TDM thread, all - * TDM resources are protected by private_display's lock. If there is a TDM - * thread, this struct will be used only in a TDM thread. So, we don't need to - * protect this structure. + * Note that we don't need to (un)lock mutex to use this structure. If there is + * no TDM thread, all TDM resources are protected by private_display's mutex. + * If there is a TDM thread, this struct will be used only in a TDM thread. + * So, we don't need to protect this structure by mutex. Not thread-safe. */ struct _tdm_private_loop { /* TDM uses wl_event_loop to handle various event sources including the TDM @@ -247,7 +247,7 @@ struct _tdm_private_loop { /* In event loop, all resources are accessed by this dpy. * CAUTION: * - DO NOT include other private structure in this structure because this - * struct is not thread-safe. + * struct is not protected by mutex. */ tdm_display *dpy; @@ -432,7 +432,9 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base); tdm_error tdm_thread_handle_cb(tdm_private_loop *private_loop); int -tdm_thread_in_display_thread(tdm_private_loop *private_loop, pid_t tid); +tdm_thread_in_display_thread(pid_t tid); +int +tdm_thread_is_running(void); tdm_error tdm_server_init(tdm_private_loop *private_loop); @@ -441,10 +443,9 @@ tdm_server_deinit(tdm_private_loop *private_loop); unsigned long tdm_helper_get_time_in_millis(void); -int -tdm_helper_unlock_in_cb(tdm_private_display *private_display); -void -tdm_helper_lock_in_cb(tdm_private_display *private_display, int need_lock); + +extern pthread_mutex_t tdm_mutex_check_lock; +extern int tdm_mutex_locked; int tdm_helper_get_dump_count(void); @@ -452,9 +453,34 @@ char * tdm_helper_get_dump_path(void); #define _pthread_mutex_lock(l) \ - do {if (tdm_debug_mutex) TDM_INFO("mutex lock"); pthread_mutex_lock(l);} while (0) + do { \ + if (tdm_debug_mutex) \ + TDM_INFO("mutex lock"); \ + pthread_mutex_lock(l); \ + pthread_mutex_lock(&tdm_mutex_check_lock); \ + tdm_mutex_locked = 1; \ + pthread_mutex_unlock(&tdm_mutex_check_lock); \ + } while (0) + #define _pthread_mutex_unlock(l) \ - do {if (tdm_debug_mutex) TDM_INFO("mutex unlock"); pthread_mutex_unlock(l);} while (0) + do { \ + if (tdm_debug_mutex) \ + TDM_INFO("mutex unlock"); \ + pthread_mutex_lock(&tdm_mutex_check_lock); \ + tdm_mutex_locked = 0; \ + pthread_mutex_unlock(&tdm_mutex_check_lock); \ + pthread_mutex_unlock(l); \ + } while (0) + +//#define TDM_MUTEX_IS_LOCKED() (tdm_mutex_locked == 1) +static inline int TDM_MUTEX_IS_LOCKED(void) +{ + int ret; + pthread_mutex_lock(&tdm_mutex_check_lock); + ret = (tdm_mutex_locked == 1); + pthread_mutex_unlock(&tdm_mutex_check_lock); + return ret; +} #ifdef __cplusplus } diff --git a/src/tdm_server.c b/src/tdm_server.c index c824905..142c1a3 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -43,7 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdm-server-protocol.h" /* CAUTION: - * - tdm server doesn't care about multi-thread. + * - tdm server doesn't care about thread things. * - DO NOT use the TDM internal functions here. */ @@ -57,7 +57,7 @@ typedef struct _tdm_server_vblank_info { tdm_private_server *private_server; } tdm_server_vblank_info; -static tdm_private_loop *keep_private_loop; +static tdm_private_server *keep_private_server; static void _tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence, @@ -67,10 +67,10 @@ _tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence, tdm_server_vblank_info *vblank_info = (tdm_server_vblank_info*)user_data; tdm_server_vblank_info *found; - if (!keep_private_loop || !keep_private_loop->private_server) + if (!keep_private_server) return; - LIST_FIND_ITEM(vblank_info, &keep_private_loop->private_server->vblank_list, + LIST_FIND_ITEM(vblank_info, &keep_private_server->vblank_list, tdm_server_vblank_info, link, found); if (!found) { TDM_DBG("vblank_info(%p) is destroyed", vblank_info); @@ -227,7 +227,7 @@ tdm_server_init(tdm_private_loop *private_loop) } private_loop->private_server = private_server; - keep_private_loop = private_loop; + keep_private_server = private_server; return TDM_ERROR_NONE; } @@ -249,5 +249,5 @@ tdm_server_deinit(tdm_private_loop *private_loop) free(private_server); private_loop->private_server = NULL; - keep_private_loop = NULL; + keep_private_server = NULL; } diff --git a/src/tdm_thread.c b/src/tdm_thread.c index fd9a5ad..53ab893 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -43,6 +43,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdm_private.h" #include "tdm_list.h" +static tdm_private_thread *keep_private_thread; + struct _tdm_private_thread { tdm_private_loop *private_loop; @@ -124,6 +126,7 @@ tdm_thread_init(tdm_private_loop *private_loop) tdm_private_thread *private_thread; const char *thread; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(private_loop->dpy, TDM_ERROR_OPERATION_FAILED); private_display = private_loop->dpy; @@ -159,6 +162,8 @@ tdm_thread_init(tdm_private_loop *private_loop) pthread_create(&private_thread->event_thread, NULL, _tdm_thread_main, private_thread); + keep_private_thread = private_thread; + TDM_INFO("using a TDM event thread. pipe(%d,%d)", private_thread->pipe[0], private_thread->pipe[1]); @@ -168,6 +173,8 @@ tdm_thread_init(tdm_private_loop *private_loop) INTERN void tdm_thread_deinit(tdm_private_loop *private_loop) { + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + if (!private_loop->private_thread) return; @@ -181,6 +188,7 @@ tdm_thread_deinit(tdm_private_loop *private_loop) free(private_loop->private_thread); private_loop->private_thread = NULL; + keep_private_thread = NULL; TDM_INFO("Finish a TDM event thread"); } @@ -190,6 +198,7 @@ tdm_thread_get_fd(tdm_private_loop *private_loop) { tdm_private_thread *private_thread; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(private_loop, -1); TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, -1); @@ -204,6 +213,7 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base) tdm_private_thread *private_thread; ssize_t len; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(base, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, TDM_ERROR_INVALID_PARAMETER); @@ -226,15 +236,19 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base) INTERN tdm_error tdm_thread_handle_cb(tdm_private_loop *private_loop) { + tdm_private_display *private_display; tdm_private_thread *private_thread; tdm_thread_cb_base *base; char buffer[1024]; int len, i; + /* DON'T check TDM_MUTEX_IS_LOCKED here */ + TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, TDM_ERROR_INVALID_PARAMETER); private_thread = private_loop->private_thread; + private_display = private_loop->dpy; len = read(private_thread->pipe[0], buffer, sizeof buffer); @@ -249,6 +263,8 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) return TDM_ERROR_OPERATION_FAILED; } + _pthread_mutex_lock(&private_display->lock); + i = 0; while (i < len) { base = (tdm_thread_cb_base*)&buffer[i]; @@ -326,22 +342,28 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) i += base->length; } + _pthread_mutex_unlock(&private_display->lock); + tdm_event_loop_flush(private_loop->dpy); return TDM_ERROR_NONE; } INTERN int -tdm_thread_in_display_thread(tdm_private_loop *private_loop, pid_t tid) +tdm_thread_in_display_thread(pid_t tid) { - tdm_private_thread *private_thread; + if (!keep_private_thread) + return 1; - TDM_RETURN_VAL_IF_FAIL(private_loop, 1); + /* DON'T check TDM_MUTEX_IS_LOCKED here */ - if (!private_loop->private_thread) - return 1; + return (keep_private_thread->display_tid == tid) ? 1 : 0; +} - private_thread = private_loop->private_thread; +INTERN int +tdm_thread_is_running(void) +{ + /* DON'T check TDM_MUTEX_IS_LOCKED here */ - return (private_thread->display_tid == tid) ? 1 : 0; + return (keep_private_thread) ? 1 : 0; } -- 2.7.4 From 94b9ff427d146300129b1432dd0ceac9afd744a3 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 16:20:32 +0900 Subject: [PATCH 05/16] remove unuseful error log Change-Id: Id215f5bf40d6f8b2563560f2683bc57b71062469 --- src/tdm_display.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 4a2d25e..e586665 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1386,20 +1386,21 @@ _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer) int count; unsigned int pipe; int zpos; + char fullpath[PATH_MAX]; tbm_surface_info_s info; tbm_surface_error_e err; path = tdm_helper_get_dump_path(); - TDM_RETURN_IF_FAIL(path != NULL); + if (!path) + return; count = tdm_helper_get_dump_count(); - TDM_RETURN_IF_FAIL(count != 0); + if (count <= 0) + return; err = tbm_surface_map(buffer, TBM_SURF_OPTION_READ, &info); TDM_RETURN_IF_FAIL(err == TBM_SURFACE_ERROR_NONE); - char fullpath[PATH_MAX] = {0, }; - pipe = private_output->pipe; zpos = private_layer->caps.zpos; -- 2.7.4 From e188e70285f8fa09c831291f1145c8d39323bc83 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 16:29:48 +0900 Subject: [PATCH 06/16] use tdm_dump_enable variable to check if dump needed Change-Id: I8287bc0eca5198ade708b26a585cd6c88bc2bd66 --- src/tdm_display.c | 3 ++- src/tdm_helper.c | 5 +++++ src/tdm_private.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index e586665..1d6618e 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1444,7 +1444,8 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); /* dump buffer */ - _tdm_layer_dump_buffer(layer, buffer); + if (tdm_dump_enable) + _tdm_layer_dump_buffer(layer, buffer); if (ret == TDM_ERROR_NONE) { /* FIXME: should save to pending_buffer first. And after committing diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 4e6c910..5887986 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -16,6 +16,7 @@ static const char *dump_prefix[2] = {"png", "yuv"}; +int tdm_dump_enable; static int *tdm_helper_dump_count; static char *tdm_helper_dump_path; @@ -258,6 +259,8 @@ tdm_helper_dump_start(char *dumppath, int *count) tdm_helper_dump_count = count; tdm_helper_dump_path = dumppath; + tdm_dump_enable = 1; + TDM_DBG("tdm_helper_dump start.(path : %s)", tdm_helper_dump_path); } @@ -267,6 +270,8 @@ tdm_helper_dump_stop(void) tdm_helper_dump_path = NULL; tdm_helper_dump_count = NULL; + tdm_dump_enable = 0; + TDM_DBG("tdm_helper_dump stop."); } diff --git a/src/tdm_private.h b/src/tdm_private.h index 7bc3acb..50417f9 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -446,6 +446,7 @@ tdm_helper_get_time_in_millis(void); extern pthread_mutex_t tdm_mutex_check_lock; extern int tdm_mutex_locked; +extern int tdm_dump_enable; int tdm_helper_get_dump_count(void); -- 2.7.4 From 05e6bec3fd72144f03cb34310f2be066a6e80ac0 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 21 Apr 2016 16:30:10 +0900 Subject: [PATCH 07/16] check if input param is valid Change-Id: Ic1cd413a0205c05226c9b955011e82ac5dbbaf2b --- src/tdm_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 5887986..25bb885 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -251,8 +251,8 @@ tdm_helper_dump_start(char *dumppath, int *count) return; } - if (dumppath == NULL) { - TDM_DBG("tdm_helper_dump dumppath is null."); + if (dumppath == NULL || count == NULL) { + TDM_DBG("tdm_helper_dump dumppath or count is null."); return; } -- 2.7.4 From fceb1931559fd583620befb3aab730b0ebb76273 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 22 Apr 2016 14:36:41 +0900 Subject: [PATCH 08/16] enhance log Change-Id: I05970c643cebda9d9cc3313bf3b26ffeba95469e --- client/tdm_client.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 5e2b750..45dd757 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -47,7 +47,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdm_list.h" #include "tdm-client-protocol.h" -extern int tdm_debug; +int tdm_debug; typedef struct _tdm_private_client { struct wl_display *display; @@ -95,6 +95,11 @@ tdm_client* tdm_client_create(tdm_client_error *error) { tdm_private_client *private_client; + const char *debug; + + debug = getenv("TDM_DEBUG"); + if (debug && (strstr(debug, "1"))) + tdm_debug = 1; private_client = calloc(1, sizeof *private_client); if (!private_client) { @@ -194,6 +199,11 @@ _tdm_client_cb_vblank_done(void *data, struct wl_tdm_vblank *vblank, TDM_RETURN_IF_FAIL(vblank_info != NULL); + if (vblank_info->vblank != vblank) + TDM_NEVER_GET_HERE(); + + TDM_DBG("vblank_info(%p) wl_tbm_vblank@%d", vblank_info, wl_proxy_get_id((struct wl_proxy *)vblank)); + if (vblank_info->func) { vblank_info->func(sequence, tv_sec, tv_usec, vblank_info->user_data); } @@ -232,6 +242,8 @@ tdm_client_wait_vblank(tdm_client *client, char *name, int interval, int sync, return TDM_CLIENT_ERROR_OUT_OF_MEMORY; } + TDM_DBG("vblank_info(%p) wl_tbm_vblank@%d", vblank_info, wl_proxy_get_id((struct wl_proxy *)vblank_info->vblank)); + wl_tdm_vblank_add_listener(vblank_info->vblank, &tdm_client_vblank_listener, vblank_info); -- 2.7.4 From affc2eacfe963b2cca8617aa8ebf735facaa424a Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 22 Apr 2016 18:25:27 +0900 Subject: [PATCH 09/16] backend can have no output_set_dpms Change-Id: Ifc34ff143f52182a1bd1e418b49d82458a4b2188 --- src/tdm_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 1d6618e..a0c3171 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1097,8 +1097,9 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) if (!func_output->output_set_dpms) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); - return TDM_ERROR_NOT_IMPLEMENTED; + private_output->current_dpms_value = dpms_value; + TDM_DBG("not implemented!!"); + return TDM_ERROR_NONE; } ret = func_output->output_set_dpms(private_output->output_backend, dpms_value); @@ -1132,9 +1133,10 @@ tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value) func_output = &private_display->func_output; if (!func_output->output_get_dpms) { + *dpms_value = private_output->current_dpms_value; _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); - return TDM_ERROR_NOT_IMPLEMENTED; + TDM_DBG("not implemented!!"); + return TDM_ERROR_NONE; } ret = func_output->output_get_dpms(private_output->output_backend, dpms_value); -- 2.7.4 From f70d6e1e8c43a47e72c195d171abe893d6629836 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 22 Apr 2016 18:26:12 +0900 Subject: [PATCH 10/16] enhance log Change-Id: I05e236e01c32d5873192a9ff913484a574adfc1f --- src/tdm_buffer.c | 4 ++-- src/tdm_capture.c | 2 +- src/tdm_display.c | 40 ++++++++++++++++++++-------------------- src/tdm_event_loop.c | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index a394fe7..9f17dd8 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -99,11 +99,11 @@ tdm_buffer_get_info(tbm_surface_h buffer) LIST_INITHEAD(&buf_info->link); if (!tbm_surface_internal_add_user_data(buffer, TDM_BUFFER_KEY, _tdm_buffer_destroy_info)) { - TDM_WRN("FAIL to create user_data for surface %p", buffer); + TDM_ERR("FAIL to create user_data for surface %p", buffer); return NULL; } if (!tbm_surface_internal_set_user_data(buffer, TDM_BUFFER_KEY, buf_info)) { - TDM_WRN("FAIL to set user_data for surface %p", buffer); + TDM_ERR("FAIL to set user_data for surface %p", buffer); return NULL; } diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 1a73db4..85432d3 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -400,7 +400,7 @@ tdm_capture_commit(tdm_capture *capture) private_output = private_capture->private_output; if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { - TDM_WRN("output(%d) dpms: %s", private_output->pipe, + TDM_ERR("output(%d) dpms: %s", private_output->pipe, dpms_str(private_output->current_dpms_value)); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_BAD_REQUEST; diff --git a/src/tdm_display.c b/src/tdm_display.c index a0c3171..0d6e274 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -497,7 +497,7 @@ tdm_output_add_change_handler(tdm_output *output, if (!private_output->regist_change_cb) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -757,7 +757,7 @@ tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value) if (!func_output->output_set_property) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -783,7 +783,7 @@ tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) if (!func_output->output_get_property) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -918,7 +918,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, _pthread_mutex_lock(&private_display->lock); if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { - TDM_WRN("output(%d) dpms: %s", private_output->pipe, + TDM_ERR("output(%d) dpms: %s", private_output->pipe, dpms_str(private_output->current_dpms_value)); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_BAD_REQUEST; @@ -928,7 +928,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, if (!func_output->output_wait_vblank) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -974,7 +974,7 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, func_output = &private_display->func_output; if (!func_output->output_commit) { - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1012,7 +1012,7 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, _pthread_mutex_lock(&private_display->lock); if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { - TDM_WRN("output(%d) dpms: %s", private_output->pipe, + TDM_ERR("output(%d) dpms: %s", private_output->pipe, dpms_str(private_output->current_dpms_value)); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_BAD_REQUEST; @@ -1039,7 +1039,7 @@ tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) if (!func_output->output_set_mode) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1064,7 +1064,7 @@ tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode) if (!func_output->output_get_mode) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1098,7 +1098,7 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) if (!func_output->output_set_dpms) { _pthread_mutex_unlock(&private_display->lock); private_output->current_dpms_value = dpms_value; - TDM_DBG("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NONE; } @@ -1135,7 +1135,7 @@ tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value) if (!func_output->output_get_dpms) { *dpms_value = private_output->current_dpms_value; _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NONE; } @@ -1281,7 +1281,7 @@ tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value) if (!func_layer->layer_set_property) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1306,7 +1306,7 @@ tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value) if (!func_layer->layer_get_property) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1333,7 +1333,7 @@ tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info) if (!func_layer->layer_set_info) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1368,7 +1368,7 @@ tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info) if (!func_layer->layer_get_info) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1438,7 +1438,7 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) if (!func_layer->layer_set_buffer) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1506,7 +1506,7 @@ tdm_layer_unset_buffer(tdm_layer *layer) if (!func_layer->layer_unset_buffer) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1609,7 +1609,7 @@ tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) if (!func_layer->layer_set_buffer) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1686,7 +1686,7 @@ tdm_layer_unset_buffer_queue(tdm_layer *layer) if (!func_layer->layer_unset_buffer) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1731,7 +1731,7 @@ tdm_layer_set_video_pos(tdm_layer *layer, int zpos) if (!func_layer->layer_set_video_pos) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: not implemented!!"); + TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index a9da07c..1cfaad2 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -182,7 +182,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; } -- 2.7.4 From a130103063054273484248fd913f478e899d9ea9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 25 Apr 2016 10:58:49 +0900 Subject: [PATCH 11/16] add TDM_LAYER_CAPABILITY_NO_CROP Change-Id: I78bbf9b71353426beb3aa69f675b0167be52fc97 --- include/tdm.h | 4 +++- include/tdm_types.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/tdm.h b/include/tdm.h index 04cbcb5..1c38b52 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -539,7 +539,9 @@ tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); /** * @brief Set the geometry information to a layer object * @details The geometry information will be applied when the output object - * of a layer object is committed. + * of a layer object is committed. If a layer has TDM_LAYER_CAPABILITY_NO_CROP + * capability, a layer will ignore the pos(crop) information of #tdm_info_layer's + * src_config. * @param[in] layer A layer object * @param[in] info The geometry information * @return #TDM_ERROR_NONE if success. Otherwise, error value. diff --git a/include/tdm_types.h b/include/tdm_types.h index 6ca3c83..f6fc5c4 100755 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -167,6 +167,7 @@ typedef enum { TDM_LAYER_CAPABILITY_TRANSFORM = (1 << 9), /**< if a layer has transform capability */ TDM_LAYER_CAPABILITY_SCANOUT = (1 << 10), /**< if a layer allows a scanout buffer only */ TDM_LAYER_CAPABILITY_RESEVED_MEMORY = (1 << 11), /**< if a layer allows a reserved buffer only */ + TDM_LAYER_CAPABILITY_NO_CROP = (1 << 12), /**< if a layer has no cropping capability */ } tdm_layer_capability; /** -- 2.7.4 From e5ddde496b91d24cc2be17ec59c2e00536aaad20 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 25 Apr 2016 11:05:22 +0900 Subject: [PATCH 12/16] set tdm output list's first element to main Change-Id: I6208106cf1023c007a2b519258dc7907cad4b5b9 Signed-off-by: Junkyeong Kim --- src/tdm.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 132 insertions(+), 5 deletions(-) mode change 100755 => 100644 src/tdm.c diff --git a/src/tdm.c b/src/tdm.c old mode 100755 new mode 100644 index cc21a1f..1d52152 --- a/src/tdm.c +++ b/src/tdm.c @@ -410,7 +410,7 @@ _tdm_display_update_output(tdm_private_display *private_display, while (tdm_display_find_output_stamp(private_display, private_output->stamp)) private_output->stamp++; - LIST_ADD(&private_output->link, &private_display->output_list); + LIST_ADDTAIL(&private_output->link, &private_display->output_list); private_output->private_display = private_display; private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF; @@ -456,11 +456,139 @@ failed_update: return ret; } +static tdm_output ** +_tdm_display_set_main_first(tdm_output **outputs, int index) +{ + tdm_output *output_tmp = NULL; + + if (index == 0) + return outputs; + + output_tmp = outputs[0]; + outputs[0] = outputs[index]; + outputs[index] = output_tmp; + + return outputs; +} + +static tdm_output ** +_tdm_display_get_ordered_outputs(tdm_private_display *private_display, + int *count, int init) +{ + tdm_func_display *func_display = &private_display->func_display; + tdm_output **outputs = NULL; + tdm_output **new_outputs = NULL; + tdm_output *output_dsi = NULL; + tdm_output *output_lvds = NULL; + tdm_output *output_hdmia = NULL; + tdm_output *output_hdmib = NULL; + int i, output_count = 0, output_connected_count = 0; + int index_dsi, index_lvds, index_hdmia, index_hdmib; + tdm_error ret; + + outputs = func_display->display_get_outputs(private_display->bdata, + &output_count, &ret); + if (ret != TDM_ERROR_NONE) + goto failed_get_outputs; + + *count = output_count; + + if (output_count == 0) + goto failed_get_outputs; + else if (output_count == 1) + return outputs; + + /* don't change list order if not init time */ + if (init != 0) + return outputs; + + /* count connected outputs */ + for (i = 0; i < output_count; i++) { + tdm_func_output *func_output = &private_display->func_output; + tdm_caps_output caps; + memset(&caps, 0, sizeof(tdm_caps_output)); + + if (!func_output->output_get_capability) { + TDM_ERR("no output_get_capability()"); + return outputs; + } + + ret = func_output->output_get_capability(outputs[i], &caps); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("output_get_capability() failed"); + return outputs; + } + + if (caps.status == TDM_OUTPUT_CONN_STATUS_CONNECTED) { + output_connected_count++; + + switch (caps.type) { + case TDM_OUTPUT_TYPE_DSI: + output_dsi = outputs[i]; + index_dsi = i; + break; + case TDM_OUTPUT_TYPE_LVDS: + output_lvds = outputs[i]; + index_lvds = i; + break; + case TDM_OUTPUT_TYPE_HDMIA: + output_hdmia = outputs[i]; + index_hdmia = i; + break; + case TDM_OUTPUT_TYPE_HDMIB: + output_hdmib = outputs[i]; + index_hdmib = i; + break; + default : + break; + } + } + } + + /* ordering : main output is first */ + /* If there is no connected output, lvds or dsi cannot be main display. (cannot connect after booting) + * But hdmi is possible, so set hdmi to main display. + * If connected only one output, it is main output. + * If connected outputs over 2, has priority like below. + * (dsi > lvds > hdmi > else) + */ + if (output_connected_count == 0) { + /* hdmi > dsi > lvds > else */ + if (output_hdmia != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_hdmia); + else if (output_hdmib != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_hdmib); + else if (output_dsi != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_dsi); + else if (output_lvds != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_lvds); + else + new_outputs = outputs; + } else { /* (output_connected_count > 1) */ + /* dsi > lvds > hdmi > else */ + if (output_dsi != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_dsi); + else if (output_lvds != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_lvds); + else if (output_hdmia != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_hdmia); + else if (output_hdmib != NULL) + new_outputs = _tdm_display_set_main_first(outputs, index_hdmib); + else + new_outputs = outputs; + } + + return new_outputs; + +failed_get_outputs: + *count = 0; + return NULL; +} + static tdm_error _tdm_display_update_internal(tdm_private_display *private_display, int only_display) { - tdm_func_display *func_display = &private_display->func_display; tdm_output **outputs = NULL; int output_count = 0, i; tdm_error ret; @@ -480,9 +608,8 @@ _tdm_display_update_internal(tdm_private_display *private_display, goto failed_update; } - outputs = func_display->display_get_outputs(private_display->bdata, - &output_count, &ret); - if (ret != TDM_ERROR_NONE) + outputs = _tdm_display_get_ordered_outputs(private_display, &output_count, only_display); + if (!outputs) goto failed_update; for (i = 0; i < output_count; i++) { -- 2.7.4 From c92ad1ac99a8f96b29706453a7097c5a15c308ab Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 25 Apr 2016 19:42:53 +0900 Subject: [PATCH 13/16] init variable Change-Id: I73691449738ad137cac39c6573afd2881ada2b6e --- src/tdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tdm.c b/src/tdm.c index 1d52152..acc9c05 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -483,7 +483,7 @@ _tdm_display_get_ordered_outputs(tdm_private_display *private_display, tdm_output *output_hdmia = NULL; tdm_output *output_hdmib = NULL; int i, output_count = 0, output_connected_count = 0; - int index_dsi, index_lvds, index_hdmia, index_hdmib; + int index_dsi = 0, index_lvds = 0, index_hdmia = 0, index_hdmib = 0; tdm_error ret; outputs = func_display->display_get_outputs(private_display->bdata, -- 2.7.4 From eb1168718b4770457b2ff7e3b0b30c5ff52bea05 Mon Sep 17 00:00:00 2001 From: Andrii Sokolenko Date: Mon, 25 Apr 2016 10:45:16 +0300 Subject: [PATCH 14/16] Implement deadlock checker. To enable this function, compile with TDM_CONFIG_MUTEX_TIMEOUT Change-Id: I20e04366aaefa7dd1369a482028cb3c2b4e7c47f Signed-off-by: Andrii Sokolenko --- src/tdm_private.h | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/tdm_private.h b/src/tdm_private.h index 50417f9..6cd2185 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -453,26 +453,45 @@ tdm_helper_get_dump_count(void); char * tdm_helper_get_dump_path(void); -#define _pthread_mutex_lock(l) \ +#define _pthread_mutex_unlock(l) \ do { \ if (tdm_debug_mutex) \ - TDM_INFO("mutex lock"); \ - pthread_mutex_lock(l); \ + TDM_INFO("mutex unlock"); \ pthread_mutex_lock(&tdm_mutex_check_lock); \ - tdm_mutex_locked = 1; \ + tdm_mutex_locked = 0; \ pthread_mutex_unlock(&tdm_mutex_check_lock); \ + pthread_mutex_unlock(l); \ } while (0) - -#define _pthread_mutex_unlock(l) \ +#ifdef TDM_CONFIG_MUTEX_TIMEOUT +#define MUTEX_TIMEOUT_SEC 5 +#define _pthread_mutex_lock(l) \ do { \ if (tdm_debug_mutex) \ - TDM_INFO("mutex unlock"); \ + TDM_INFO("mutex lock"); \ + struct timespec rtime; \ + clock_gettime(CLOCK_REALTIME, &rtime); \ + rtime.tv_sec += MUTEX_TIMEOUT_SEC; \ + if (pthread_mutex_timedlock(l, &rtime)) { \ + TDM_ERR("Mutex lock failed PID %d", getpid()); \ + _pthread_mutex_unlock(l); \ + } \ + else { \ + pthread_mutex_lock(&tdm_mutex_check_lock); \ + tdm_mutex_locked = 1; \ + pthread_mutex_unlock(&tdm_mutex_check_lock); \ + } \ + } while (0) +#else //TDM_CONFIG_MUTEX_TIMEOUT +#define _pthread_mutex_lock(l) \ + do { \ + if (tdm_debug_mutex) \ + TDM_INFO("mutex lock"); \ + pthread_mutex_lock(l); \ pthread_mutex_lock(&tdm_mutex_check_lock); \ - tdm_mutex_locked = 0; \ + tdm_mutex_locked = 1; \ pthread_mutex_unlock(&tdm_mutex_check_lock); \ - pthread_mutex_unlock(l); \ } while (0) - +#endif //TDM_CONFIG_MUTEX_TIMEOUT //#define TDM_MUTEX_IS_LOCKED() (tdm_mutex_locked == 1) static inline int TDM_MUTEX_IS_LOCKED(void) { -- 2.7.4 From 353af27ec5477a66779c8f3c685203a8245a01de Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 25 Apr 2016 23:05:49 +0900 Subject: [PATCH 15/16] don't call tdm_event_loop_flush in a main thread. All requests and events of a wayland display are handled in a TDM thread. Change-Id: I9469304a631c45a5d71dfcd27c8cc8d78d7be253 --- src/tdm_event_loop.c | 14 ++++++++++++++ src/tdm_thread.c | 2 -- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index 1cfaad2..c6d3486 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -230,6 +230,12 @@ tdm_event_loop_dispatch(tdm_private_display *private_display) if (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. @@ -237,6 +243,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; } @@ -250,6 +258,12 @@ tdm_event_loop_flush(tdm_private_display *private_display) 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); } diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 53ab893..4dd33e4 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -344,8 +344,6 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) _pthread_mutex_unlock(&private_display->lock); - tdm_event_loop_flush(private_loop->dpy); - return TDM_ERROR_NONE; } -- 2.7.4 From 2e7a781e22ab7a6d267eabe994e928c5cf397ed8 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 25 Apr 2016 23:30:58 +0900 Subject: [PATCH 16/16] changing test log Change-Id: Ia09d2f5af48af1e1eb6351f5acbed8e202ebf3ea --- tools/tdm_test_client.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index 817ca3e..bc29283 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -38,12 +38,12 @@ DEALINGS IN THE SOFTWARE. #include static int -get_time_in_millis(void) +get_time_in_micros(void) { struct timespec tp; if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) - return (int)(tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); + return (int)(tp.tv_sec * 1000000) + (tp.tv_nsec / 1000L); return 0; } @@ -52,12 +52,19 @@ static void _client_vblank_handler(unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { - int temp1, temp2; + int client, vblank; + static int prev = 0; - temp1 = (intptr_t)user_data; - temp2 = get_time_in_millis(); + client = get_time_in_micros(); + vblank = tv_sec * 1000000 + tv_usec; - printf("%d ms\n", temp2 - temp1); + if (vblank - prev > 16966 || vblank - prev < 16366) /* +0.3 ~ -0.3 ms */ + printf("vblank : %d us\n", vblank - prev); + + if (client - vblank > 3000) /* 3ms */ + printf("kernel -> tdm-client: %d us\n", client - vblank); + + prev = vblank; } @@ -89,8 +96,7 @@ main(int argc, char *argv[]) int ret; error = tdm_client_wait_vblank(client, "unknown-0", 1, 0, - _client_vblank_handler, - (void*)(intptr_t)get_time_in_millis()); + _client_vblank_handler, NULL); if (error != TDM_CLIENT_ERROR_NONE) { printf("tdm_client_wait_vblank failed\n"); goto done; -- 2.7.4