From 7332663441031588dbc3cbf6de9d4c75d90f02a5 Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Tue, 9 Aug 2022 14:45:55 +0900 Subject: [PATCH] resource: display: Add a display monitor thread to deal with multiple clients When multiple clients request to get fps concurrently, unacceptable delays (upto tens of seconds for hundred clients) are incurred. I guess that the dbus function g_dbus_connection_send_message_with_reply_sync() cannot deal with multiple concurrent calls. This patch added a monitor thread to read current fps value via dbus. The thread shares read fps value to clients. By doing so, multiple clients can get the fps value without delays. Change-Id: I726092658ef79af3610baa6fa356d8a54c6cf299 Signed-off-by: Sung-hun Kim --- src/resource/resource-display.c | 122 ++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 22 deletions(-) diff --git a/src/resource/resource-display.c b/src/resource/resource-display.c index 0f5a82a..724b5df 100644 --- a/src/resource/resource-display.c +++ b/src/resource/resource-display.c @@ -23,6 +23,7 @@ */ #include +#include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include @@ -38,6 +40,8 @@ #define DBUS_ENLIGHTENMENT_INTERFACE "org.enlightenment.wm.info" #define DBUS_ENLIGHTENMENT_FPS_FUNC "get_fps_info" +#define DISPLAY_SAMPLE_RATE_MSEC 1000 + struct display_context { char *device_name; int index; @@ -51,31 +55,24 @@ struct display_fps_data { double fps; }; -static int display_get_fps(struct resource *res, - const struct resource_attribute *attr, - void *data) +struct display_fps_monitor { + int holder; + int resource_count; + double *last_fps; + struct thread *thread; + GMutex display_lock; +}; + +static struct display_fps_monitor g_fps_monitor; + +static int display_read_fps(int resource_index) { - struct display_context *ctx; + int ret = 0; GDBusConnection *conn; GDBusMessage *msg, *reply; GVariant *result, *value; GError *err = NULL; struct display_fps_data fps_data; - double *fps = (double *)data; - int ret = 0; - - if (!res || !attr || !data) - return -EINVAL; - - ctx = get_resource_privdata(res); - if (!ctx) - return -EINVAL; - - if (!ctx->device_name) { - _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n", - get_resource_name(res)); - return -EINVAL; - } /* Connect dbus interface and receive message */ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); @@ -115,13 +112,14 @@ static int display_get_fps(struct resource *res, } /* Get the fps information according to the index of resource_device */ - value = g_variant_get_child_value(result, ctx->index); + value = g_variant_get_child_value(result, resource_index); g_variant_get(value, "(usiud)", &fps_data.type, fps_data.output, &fps_data.zpos, &fps_data.window, &fps_data.fps); out: - *fps = fps_data.fps; + __atomic_store((&g_fps_monitor.last_fps[resource_index]), + &fps_data.fps, __ATOMIC_RELEASE); err_reply: g_object_unref(reply); @@ -133,6 +131,31 @@ err_conn: return ret; } +static int display_get_fps(struct resource *res, + const struct resource_attribute *attr, + void *data) +{ + struct display_context *ctx; + double *fps = (double *)data; + + if (!res || !attr || !data) + return -EINVAL; + + ctx = get_resource_privdata(res); + if (!ctx) + return -EINVAL; + + if (!ctx->device_name) { + _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n", + get_resource_name(res)); + return -EINVAL; + } + + __atomic_load(&g_fps_monitor.last_fps[ctx->index], fps, __ATOMIC_ACQUIRE); + + return 0; +} + static int display_get_name(struct resource *res, const struct resource_attribute *attr, void *data) @@ -217,8 +240,49 @@ static const struct resource_control display_ctrls[] = { }, }; +static int display_monitor_func(void *data, void **result) +{ + int i; + + for (i = 0; i < g_fps_monitor.resource_count; i++) + display_read_fps(i); + + return THREAD_RETURN_CONTINUE; +} + +static int init_display_monitor_thread(struct resource *res) +{ + int ret; + + g_fps_monitor.resource_count = get_resource_device_count(get_resource_type(res)); + g_fps_monitor.last_fps = calloc(g_fps_monitor.resource_count, sizeof(double)); + if (!g_fps_monitor.last_fps) + return -ENOMEM; + + ret = create_timer_thread(&g_fps_monitor.thread, DISPLAY_SAMPLE_RATE_MSEC, + display_monitor_func, NULL); + + return ret; +} + +static void __DESTRUCTOR__ exit_display_monitor_thread(void) +{ + if (g_fps_monitor.thread != NULL) { + destroy_thread(g_fps_monitor.thread); + g_fps_monitor.thread = NULL; + } + + if (g_fps_monitor.last_fps) { + free(g_fps_monitor.last_fps); + g_fps_monitor.last_fps = NULL; + } + + g_fps_monitor.resource_count = 0; +} + static int display_init(struct resource *res) { + int ret = 0; struct display_context *ctx; ctx = calloc(1, sizeof(struct display_context)); @@ -229,7 +293,16 @@ static int display_init(struct resource *res) set_resource_privdata(res, ctx); - return 0; + g_mutex_lock(&g_fps_monitor.display_lock); + if (g_fps_monitor.holder++ == 0) { + if (!g_fps_monitor.thread) + ret = init_display_monitor_thread(res); + else + resume_thread(g_fps_monitor.thread); + } + g_mutex_unlock(&g_fps_monitor.display_lock); + + return ret; } static void display_exit(struct resource *res) @@ -248,6 +321,11 @@ static void display_exit(struct resource *res) free(ctx); set_resource_privdata(res, NULL); + + g_mutex_lock(&g_fps_monitor.display_lock); + if (--g_fps_monitor.holder == 0 && g_fps_monitor.thread != NULL) + suspend_thread(g_fps_monitor.thread); + g_mutex_unlock(&g_fps_monitor.display_lock); } static const struct resource_driver display_resource_driver = { -- 2.7.4