resource: display: Add a display monitor thread to deal with multiple clients 18/279418/9
authorSung-hun Kim <sfoon.kim@samsung.com>
Tue, 9 Aug 2022 05:45:55 +0000 (14:45 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 11 Aug 2022 08:54:34 +0000 (17:54 +0900)
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 <sfoon.kim@samsung.com>
src/resource/resource-display.c

index 0f5a82a..724b5df 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <glib.h>
+#include <unistd.h>
 
 #include <hal/hal-power.h>
 
@@ -30,6 +31,7 @@
 #include <util/log.h>
 #include <util/resource.h>
 #include <util/gdbus-util.h>
+#include <util/thread.h>
 
 #include <resource-monitor/resource-monitor.h>
 
@@ -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 = {