monitor: Add monitor module 24/270624/5
authorDongwoo Lee <dwoo08.lee@samsung.com>
Mon, 7 Feb 2022 05:24:56 +0000 (14:24 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 8 Feb 2022 05:06:43 +0000 (14:06 +0900)
This introduce the new pass module monitor which provides methods for
accessing or controlling resources in a common way. By just creating
and queuing a request, resource attributes are updated, and we can
exploit it easily. And attributes also can be filtered in order not
to take unnecessary attributes by set interest mask.

How to request resource update:
 1) create resource
 2) set interest attributes for resource
 3) create monitor command
 4) bind resource with command
 5) submit command (sync or async)
 6) if async) wait for done
 7) get attributes values by 'get' function as following the
    corresponding type
 8) PTR_TYPE, STRING_TYPE, ARRAY_TYPE attributes should be call 'put'
    function to release memory

Change-Id: I110e46b96691381629b8da619d3519c50e409693
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
CMakeLists.txt
include/monitor/monitor.h [new file with mode: 0644]
src/monitor/monitor-command.c [new file with mode: 0644]
src/monitor/monitor-thread.c [new file with mode: 0644]
src/monitor/monitor.c [new file with mode: 0644]

index 568afd4..6b0d426 100644 (file)
@@ -43,6 +43,9 @@ SET(SRCS
        src/resource/resource-bus.c
        src/resource/resource-gpu.c
        src/resource/resource-memory.c
+       src/monitor/monitor.c
+       src/monitor/monitor-thread.c
+       src/monitor/monitor-command.c
 )
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
new file mode 100644 (file)
index 0000000..08e9e21
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * PASS (Power Aware System Service)
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MONITOR_H__
+#define __MONITOR_H__
+
+#include <util/resource.h>
+#include <util/thread.h>
+#include <util/queue.h>
+
+#define MONITOR_POLLING_DURATION 100
+
+struct monitor_command {
+       struct resource *resource;
+       volatile bool done;
+       mtx_t lock;
+       cnd_t signal;
+};
+
+struct monitor {
+       struct thread *thread;
+       struct queue *q;
+       void *priv;
+       mtx_t lock;
+       cnd_t signal;
+};
+
+struct monitor *monitor_get(void);
+int monitor_thread_init(struct monitor *monitor);
+void monitor_thread_exit(struct monitor *monitor);
+
+void monitor_command_wait_done(struct monitor_command *cmd);
+void monitor_command_submit(struct monitor_command *cmd);
+void monitor_command_submit_sync(struct monitor_command *cmd);
+void monitor_command_bind_resource(struct monitor_command *cmd, struct resource *res);
+void monitor_command_unbind_resource(struct monitor_command *cmd);
+int monitor_command_init(struct monitor_command **cmd);
+void monitor_command_exit(struct monitor_command *cmd);
+
+#endif
diff --git a/src/monitor/monitor-command.c b/src/monitor/monitor-command.c
new file mode 100644 (file)
index 0000000..6009ee3
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * PASS (Power Aware System Service)
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <util/log.h>
+#include <util/resource.h>
+#include <monitor/monitor.h>
+
+static void _monitor_command_wait_done(struct monitor_command *cmd, int polling)
+{
+       while (!cmd->done) {
+               smp_rmb();
+               if (polling-- <= 0) {
+                       mtx_lock(&cmd->lock);
+                       cnd_wait(&cmd->signal, &cmd->lock);
+                       mtx_unlock(&cmd->lock);
+                       /* done at this time */
+                       break;
+               }
+       }
+}
+
+void monitor_command_wait_done(struct monitor_command *cmd)
+{
+       _monitor_command_wait_done(cmd, 0);
+}
+
+void monitor_command_submit(struct monitor_command *cmd)
+{
+       struct monitor *monitor = monitor_get();
+
+       cmd->done = false;
+       enqueue(monitor->q, (void *)cmd);
+
+       cnd_signal(&monitor->signal);
+}
+
+void monitor_command_submit_sync(struct monitor_command *cmd)
+{
+       monitor_command_submit(cmd);
+       _monitor_command_wait_done(cmd, MONITOR_POLLING_DURATION);
+}
+
+void monitor_command_bind_resource(struct monitor_command *cmd, struct resource *res)
+{
+       if (cmd->resource) {
+               _E("resource is already bound\n");
+               return;
+       }
+
+       cmd->resource = res;
+}
+
+void monitor_command_unbind_resource(struct monitor_command *cmd)
+{
+       if (!cmd->resource) {
+               _E("resource is not bound yet\n");
+               return;
+       }
+
+       cmd->resource = NULL;
+}
+
+int monitor_command_init(struct monitor_command **cmd)
+{
+       struct monitor_command *new_cmd;
+
+       new_cmd = calloc(1, sizeof(struct monitor_command));
+       if (!new_cmd)
+               return -ENOMEM;
+
+       mtx_init(&new_cmd->lock, mtx_plain);
+       cnd_init(&new_cmd->signal);
+       new_cmd->done = false;
+
+       *cmd = new_cmd;
+
+       return 0;
+}
+
+void monitor_command_exit(struct monitor_command *cmd)
+{
+       cnd_destroy(&cmd->signal);
+       mtx_destroy(&cmd->lock);
+
+       if (cmd->resource)
+               _W("resource is not unbound before destroying request\n");
+
+       free(cmd);
+}
diff --git a/src/monitor/monitor-thread.c b/src/monitor/monitor-thread.c
new file mode 100644 (file)
index 0000000..e8a3b12
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * PASS (Power Aware System Service)
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <util/log.h>
+#include <monitor/monitor.h>
+
+thread_local int empty_counter = 0;
+
+static int monitor_func(void *data, void **result)
+{
+       struct monitor *monitor = data;
+       struct monitor_command *cmd;
+
+new_command:
+       if (dequeue(monitor->q, (void *)&cmd) < 0) {
+               if (empty_counter++ > MONITOR_POLLING_DURATION) {
+                       empty_counter = 0;
+                       mtx_lock(&monitor->lock);
+                       cnd_wait(&monitor->signal, &monitor->lock);
+                       mtx_unlock(&monitor->lock);
+                       goto new_command;
+               }
+               return THREAD_RETURN_CONTINUE;
+       }
+
+       update_resource_attrs(cmd->resource);
+
+       cmd->done = true;
+       smp_wmb();
+
+       cnd_signal(&cmd->signal);
+
+       return THREAD_RETURN_CONTINUE;
+}
+
+int monitor_thread_init(struct monitor *monitor)
+{
+       struct thread *thread;
+       struct queue *queue;
+       int ret;
+
+       ret = create_queue(&queue);
+       if (ret < 0) {
+               _E("failed to create command queue\n");
+               return ret;
+       }
+
+       /* q should be assigned before create daemon thread */
+       monitor->q = queue;
+       monitor->priv = NULL;
+       mtx_init(&monitor->lock, mtx_plain);
+       cnd_init(&monitor->signal);
+
+       ret = create_daemon_thread(&thread, monitor_func, monitor);
+       if (ret < 0) {
+               _E("failed to create monitor thread\n");
+               cnd_destroy(&monitor->signal);
+               mtx_destroy(&monitor->lock);
+               destroy_queue(queue);
+               monitor->q = NULL;
+               return ret;
+       }
+
+       monitor->thread = thread;
+
+       return 0;
+}
+
+void monitor_thread_exit(struct monitor *monitor)
+{
+       if (monitor->thread) {
+               cnd_signal(&monitor->signal);
+               destroy_thread(monitor->thread);
+               monitor->thread = NULL;
+       }
+
+       cnd_destroy(&monitor->signal);
+       mtx_destroy(&monitor->lock);
+
+       if (monitor->q) {
+               destroy_queue(monitor->q);
+               monitor->q = NULL;
+       }
+}
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
new file mode 100644 (file)
index 0000000..50f602c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * PASS (Power Aware System Service)
+ *
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib.h>
+
+#include <util/device-notifier.h>
+#include <util/log.h>
+#include <util/devices.h>
+#include <monitor/monitor.h>
+
+static struct monitor g_monitor;
+
+struct monitor *monitor_get(void)
+{
+       return &g_monitor;
+}
+
+static int monitor_setup(void *data, void *user_data)
+{
+       int ret;
+
+       ret = monitor_thread_init(&g_monitor);
+       if (ret < 0) {
+               _E("failed to initialize monitor thread\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void monitor_init(void *data)
+{
+       /* This is the case of daemon creation: DO NOTHING */
+}
+
+static void monitor_exit(void *data)
+{
+       monitor_thread_exit(&g_monitor);
+       unregister_notifier(DEVICE_NOTIFIER_INIT_DONE, monitor_setup, NULL);
+}
+
+static int monitor_probe(void *data)
+{
+       int ret = 0;
+
+       /*
+        * Register a notifier for the booting-done event. The actual
+        * initialization of the daemon is performed by this notifier after
+        * booting is completely done.
+        */
+       ret = register_notifier(DEVICE_NOTIFIER_INIT_DONE,
+                       monitor_setup, NULL);
+       if (ret < 0) {
+               _E("cannot register a callback function \
+                               for the booting-done event (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct device_ops monitor_device_ops = {
+       .name   = "monitor",
+       .probe  = monitor_probe,
+       .init   = monitor_init,
+       .exit   = monitor_exit,
+};
+
+DEVICE_OPS_REGISTER(&monitor_device_ops)