From: Boram Park Date: Wed, 3 Jan 2018 11:16:25 +0000 (+0900) Subject: vblank: return TDM_ERROR_TIMEOUT when timeout occurs X-Git-Tag: accepted/tizen/4.0/unified/20180111.140807~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;ds=sidebyside;h=e11fa64c32cc9f5f22f2ce08647bed7dc549a8b3;p=platform%2Fcore%2Fuifw%2Flibtdm.git vblank: return TDM_ERROR_TIMEOUT when timeout occurs If a vblank callback isn't called in 2000ms, tdm vblank will return TDM_ERROR_TIMEOUT to client. Change-Id: Ib5cd14dddd8bef051e01664c52021f57c7099f48 --- diff --git a/include/tdm_common.h b/include/tdm_common.h index 054cb5e..ee86347 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -68,6 +68,7 @@ typedef enum { TDM_ERROR_NO_CAPABILITY = -9, /**< no capability */ TDM_ERROR_DPMS_OFF = -10, /**< dpms off */ TDM_ERROR_OUTPUT_DISCONNECTED = -11, /**< output disconnected */ + TDM_ERROR_TIMEOUT = -12, /**< timeout */ } tdm_error; /** diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 4816411..b272a2d 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -125,6 +125,9 @@ typedef struct _tdm_private_vblank { /* for SW */ tdm_event_loop_source *SW_timer; struct list_head SW_wait_list; + + /* for timeout */ + tdm_event_loop_source *timeout_timer; } tdm_private_vblank; struct _tdm_vblank_wait_info { @@ -161,6 +164,9 @@ static tdm_error _tdm_vblank_wait_SW(tdm_vblank_wait_info *wait_info); static void _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); +static void _tdm_vblank_timeout_timer_update(tdm_private_vblank *private_vblank, int ms_delay); +static void _tdm_vblank_get_client_information(tdm_private_vblank *private_vblank, + pid_t *pid, const char **name); #if 0 static void @@ -302,6 +308,13 @@ _tdm_vblank_free_HW_wait(tdm_private_vblank *private_vblank, tdm_error error, un { tdm_vblank_wait_info *w = NULL, *ww = NULL; + if (!LIST_IS_EMPTY(&private_vblank->SW_wait_list)) + TDM_NEVER_GET_HERE(); + + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + tdm_display_unlock(private_vblank->dpy); + LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->HW_wait_list, link) { LIST_DEL(&w->link); _tdm_vblank_valid_list_del(&w->valid_link); @@ -535,14 +548,20 @@ tdm_vblank_destroy(tdm_vblank *vblank) tdm_output_remove_change_handler(private_vblank->output, _tdm_vblank_cb_output_change, private_vblank); - _tdm_vblank_free_HW_wait(private_vblank, 0, 0); - LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->SW_wait_list, link) { LIST_DEL(&w->link); _tdm_vblank_valid_list_del(&w->valid_link); free(w); } + _tdm_vblank_free_HW_wait(private_vblank, 0, 0); + + if (private_vblank->timeout_timer) { + tdm_display_lock(private_vblank->dpy); + tdm_event_loop_source_remove(private_vblank->timeout_timer); + tdm_display_unlock(private_vblank->dpy); + } + VIN("destroyed"); free(private_vblank); @@ -694,6 +713,84 @@ tdm_vblank_get_enable_fake(tdm_vblank *vblank, unsigned int *enable_fake) } static tdm_error +_tdm_vblank_timeout_timer_cb(void *user_data) +{ + tdm_private_vblank *private_vblank = user_data; + tdm_vblank_wait_info *w = NULL, *ww = NULL; + tdm_error error = TDM_ERROR_TIMEOUT; + pid_t pid; + const char *proc_name; + + TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_OPERATION_FAILED); + + _tdm_vblank_get_client_information(private_vblank, &pid, &proc_name); + + if (!LIST_IS_EMPTY(&private_vblank->HW_wait_list)) { + + VER("HW vblank TIMEOUT!! (pid: %u, name: %s)", pid, proc_name); + + LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->HW_wait_list, link) { + LIST_DEL(&w->link); + _tdm_vblank_valid_list_del(&w->valid_link); + + tdm_output_remove_vblank_handler_internal(private_vblank->output, _tdm_vblank_cb_vblank_HW, w); + + if (w->func) + w->func(private_vblank, error, 0, 0, 0, w->user_data); + + free(w); + } + } + + if (!LIST_IS_EMPTY(&private_vblank->SW_wait_list)) { + + VER("SW vblank TIMEOUT!! (pid: %u, name: %s)", pid, proc_name); + + LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->SW_wait_list, link) { + LIST_DEL(&w->link); + _tdm_vblank_valid_list_del(&w->valid_link); + + if (w->func) + w->func(private_vblank, error, 0, 0, 0, w->user_data); + + free(w); + } + } + + return TDM_ERROR_NONE; +} + +static void +_tdm_vblank_timeout_timer_update(tdm_private_vblank *private_vblank, int ms_delay) +{ + tdm_error ret; + + if (!private_vblank->timeout_timer) { + private_vblank->timeout_timer = + tdm_event_loop_add_timer_handler(private_vblank->dpy, + _tdm_vblank_timeout_timer_cb, + private_vblank, + &ret); + if (!private_vblank->timeout_timer) { + VER("couldn't add timer"); + return; + } + VIN("Create Timeout timer"); + } + + ret = tdm_event_loop_source_timer_update(private_vblank->timeout_timer, ms_delay); + if (ret != TDM_ERROR_NONE) { + VER("couldn't update timer"); + return; + } + + if (ms_delay != 0) + VDB("timeout timer updated"); + else + VDB("timeout timer disabled"); +} + +static tdm_error _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) { tdm_vblank_wait_info *first_wait_info = NULL; @@ -797,6 +894,13 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, VWR("couldn't update sw timer"); } + if (!LIST_IS_EMPTY(&private_vblank->SW_wait_list)) + TDM_NEVER_GET_HERE(); + + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + tdm_display_unlock(private_vblank->dpy); + LIST_DEL(&wait_info->link); _tdm_vblank_valid_list_del(&wait_info->valid_link); @@ -948,6 +1052,11 @@ tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) return TDM_ERROR_OPERATION_FAILED; } + if (!LIST_IS_EMPTY(&private_vblank->HW_wait_list)) + TDM_NEVER_GET_HERE(); + + _tdm_vblank_timeout_timer_update(private_vblank, 0); + first_wait_info = container_of(private_vblank->SW_wait_list.next, first_wait_info, link); TDM_RETURN_VAL_IF_FAIL(first_wait_info != NULL, TDM_ERROR_OPERATION_FAILED); @@ -1148,6 +1257,10 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, return ret; } + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 2000); + tdm_display_unlock(private_vblank->dpy); + return TDM_ERROR_NONE; } @@ -1242,6 +1355,29 @@ tdm_vblank_get_stamp(tdm_vblank *vblank) return private_vblank->stamp; } +static void +_tdm_vblank_get_client_information(tdm_private_vblank *private_vblank, pid_t *pid, const char **name) +{ + struct wl_client *client; + + if (!private_vblank->resource) + goto no_client; + + client = wl_resource_get_client(private_vblank->resource); + if (!client) + goto no_client; + + wl_client_get_credentials(client, pid, NULL, NULL); + *name = tdm_server_get_client_name(*pid); + + return; + +no_client: + *pid = 0; + *name = NULL; + return; +} + INTERN void tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) { @@ -1258,13 +1394,7 @@ tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) const char *proc_name = NULL; pid_t pid = 0; - if (v->resource) { - struct wl_client *client = wl_resource_get_client(v->resource); - if (client) { - wl_client_get_credentials(client, &pid, NULL, NULL); - proc_name = tdm_server_get_client_name(pid); - } - } + _tdm_vblank_get_client_information(v, &pid, &proc_name); TDM_SNPRINTF(reply, len, "%-12s %u %u %d %u %s (pid: %u)\n", v->name, v->fps, v->ignore_global_fps, v->offset, v->enable_fake,