hal-backend-service: Replace thread to tizen-core 79/320379/4
authorSangYoun Kwak <sy.kwak@samsung.com>
Thu, 27 Feb 2025 12:35:00 +0000 (21:35 +0900)
committerSangYoun Kwak <sy.kwak@samsung.com>
Fri, 28 Feb 2025 06:10:32 +0000 (15:10 +0900)
Previously, thread is used to run modules separately but the
comminucation was occured on gmainloop and there is only one gmainloop,
all comminucations were occured on one thread.

To fix this issue, tizen-core is used to run modules separately since it
supports separated gmainloop.

Change-Id: Ice506b1ad0bccf77b4790a6383f9f2e4ce554f90
Signed-off-by: SangYoun Kwak <sy.kwak@samsung.com>
hal-backend-service/CMakeLists.txt
hal-backend-service/hal-backend-service.c
hal-backend-service/thread.c [deleted file]
hal-backend-service/thread.h [deleted file]
packaging/hal-api-common.spec

index f2ca5594350862372e82037a8a04d7b62d687719..35868d39291959cabb4d34299fdc2efe8ca67033 100644 (file)
@@ -12,6 +12,7 @@ pkg_check_modules(gtest_pkgs REQUIRED
        glib-2.0
        rpc-port
        bundle
+       tizen-core
 )
 
 FOREACH(flag ${gtest_pkgs_CFLAGS})
@@ -27,7 +28,6 @@ SET(CMAKE_EXE_LINKER_FLAGS "-pie")
 SET(src
        ${CMAKE_SOURCE_DIR}/src/hal-api-conf.c
        ${CMAKE_SOURCE_DIR}/hal-backend-service/hal-backend-service.c
-       ${CMAKE_SOURCE_DIR}/hal-backend-service/thread.c
 )
 MESSAGE("${PROJECT_NAME}")
 ADD_EXECUTABLE(${PROJECT_NAME} ${src})
index f9fd2d9aa29c985b64a420c3cff327f8cb624544..d154db34714cb4709b9f8951e0986a02e2ef89c5 100644 (file)
 #include <glib-unix.h>
 #include <rpc-port-internal.h>
 #include <bundle_internal.h>
+#include <tizen_core.h>
 
 #include "hal-common.h"
 #include "hal-api-conf.h"
 #include "common.h"
 
-#include "thread.h"
-
 #define RPC_STUB_PROC_NAME     "d::HalBackendService"
 
 struct hal_backend_service_data {
        enum hal_module module;
-       struct thread *thread;
-       gboolean is_initialized;
+       tizen_core_task_h task;
+       bool is_initialized;
 };
 
 enum hal_backend_service_func {
@@ -51,7 +50,8 @@ enum hal_backend_service_func {
 
 extern char *program_invocation_name;
 
-static GMainLoop *g_g_main_loop;
+static tizen_core_task_h g_main_task = NULL;
+
 static GSList *g_hal_backend_service_data_list = NULL;
 G_LOCK_DEFINE_STATIC(hal_backend_service_lock);
 
@@ -405,7 +405,7 @@ int hal_common_exit_backend_service(enum hal_module module, void *user_data)
 
 static int add_hal_backend_service(enum hal_module module)
 {
-       struct hal_backend_service_data *hal_backend_service_data;
+       struct hal_backend_service_data *hal_backend_service_data = NULL;
 
        if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
                _E("Invalid parameter of HAL module (%d)\n", module);
@@ -419,8 +419,8 @@ static int add_hal_backend_service(enum hal_module module)
        }
 
        hal_backend_service_data->module = module;
-       hal_backend_service_data->thread = NULL;
-       hal_backend_service_data->is_initialized = FALSE;
+       hal_backend_service_data->task = NULL;
+       hal_backend_service_data->is_initialized = false;
 
        g_hal_backend_service_data_list = g_slist_prepend(g_hal_backend_service_data_list,
                                                (gpointer)hal_backend_service_data);
@@ -505,65 +505,73 @@ static int hal_backend_service_delete_and_close_plugin(void)
        return 0;
 }
 
-static int hal_backend_service_thread_func(void *data, void **user_data)
+static bool hal_backend_service_initialize_cb(tizen_core_source_h source, int *timeout, void *data)
 {
        struct hal_backend_service_data *service_data = NULL;
        int ret = 0;
 
+       /* FIXME: This is error situation, task should be terminated? */
        if (data == NULL) {
                _E("Invalid hal_backend_service(NULL)");
-               return THREAD_RETURN_ERROR;
+               return false;
        }
        service_data = (struct hal_backend_service_data *)data;
 
+       if (service_data->is_initialized)
+               return false;
+
        if (service_data->module <= HAL_MODULE_UNKNOWN || service_data->module >= HAL_MODULE_END) {
                _E("Invalid parameter of HAL module (%d)\n", service_data->module);
-               return THREAD_RETURN_ERROR;
+               return false;
        }
 
        ret = hal_common_init_backend_service(service_data->module, NULL);
        if (ret < 0) {
                _E("Failed to initialize hal backend service: ret(%d)", ret);
-               return THREAD_RETURN_ERROR;
+               return false;
        }
 
-       suspend_thread(service_data->thread);
+       service_data->is_initialized = true;
 
-       return THREAD_RETURN_CONTINUE;
+       return false;
 }
 
-static int hal_backend_thread_finalize_func(void *data)
+static void hal_backend_service_finalize_cb(tizen_core_source_h source, void *data)
 {
        struct hal_backend_service_data *service_data = NULL;
        int ret = 0;
 
        if (data == NULL) {
                _E("Invalid hal_backend_service(NULL)");
-               return THREAD_RETURN_ERROR;
+               return;
        }
        service_data = (struct hal_backend_service_data *)data;
 
        if (service_data->module <= HAL_MODULE_UNKNOWN || service_data->module >= HAL_MODULE_END) {
                _E("Invalid parameter of HAL module (%d)\n", service_data->module);
-               return THREAD_RETURN_ERROR;
+               return;
        }
 
        ret = hal_common_exit_backend_service(service_data->module, NULL);
        if (ret < 0) {
                _E("Failed to exit hal backend service: ret(%d)", ret);
-               return THREAD_RETURN_ERROR;
+               return;
        }
 
-       _D("Exit done.");
+       service_data->is_initialized = false;
 
-       return THREAD_RETURN_DONE;
+       _D("Exit done.");
 }
 
-static void create_hal_backend_service_thread(gpointer data, gpointer user_data)
+static void create_hal_backend_service_task(gpointer data, gpointer user_data)
 {
-       struct hal_backend_service_data *service_data;
-       size_t *failed_count;
-       struct thread *thread;
+       tizen_core_task_h task = NULL;
+       tizen_core_h core = NULL;
+       tizen_core_source_h source = NULL;
+
+       struct hal_backend_service_data *service_data = NULL;
+       struct __hal_module_info *module_info = NULL;
+       size_t *failed_count = NULL;
        int ret = 0;
 
        if (data == NULL || user_data == NULL) {
@@ -574,22 +582,71 @@ static void create_hal_backend_service_thread(gpointer data, gpointer user_data)
        service_data = (struct hal_backend_service_data *)data;
        failed_count = (size_t *)user_data;
 
-       ret = create_daemon_thread(&thread,
-                               hal_backend_service_thread_func, service_data,
-                               hal_backend_thread_finalize_func, service_data);
-       if (ret < 0) {
-               _E("Failed to create hal_backend_service thread: ret(%d)", ret);
-               (*failed_count)++;
-               return;
+       module_info = _hal_api_conf_get_module_info(service_data->module, NULL);
+       ret = tizen_core_task_create(module_info->backend_module_name, true, &task);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to create tizen_core task: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_source_create(&source);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to create tizen_core source: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_task_get_tizen_core(task, &core);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to get tizen_core core from task: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_source_set_prepare_cb(source, hal_backend_service_initialize_cb, service_data);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to set prepare callback: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_source_set_finalize_cb(source, hal_backend_service_finalize_cb, service_data);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to set finalize callback: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_add_source(core, source);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to add tizen_core source to core: ret(%d)", ret);
+               goto error;
+       }
+
+       ret = tizen_core_task_run(task);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to run tizen_core task: ret(%d)", ret);
+               goto error;
        }
-       service_data->thread = thread;
 
-       _D("Thread created for hal_module(%d)", service_data->module);
+       service_data->task = task;
+
+       _D("Task created for hal_module(%d)", service_data->module);
+
+       return;
+
+error:
+       if (source != NULL)
+               tizen_core_source_destroy(source);
+
+       if (task != NULL)
+               tizen_core_task_destroy(task);
+
+       (*failed_count)++;
+
+       return;
 }
 
-static void delete_hal_backend_service_thread(gpointer data, gpointer user_data)
+static void delete_hal_backend_service_task(gpointer data, gpointer user_data)
 {
-       struct hal_backend_service_data *service_data;
+       struct hal_backend_service_data *service_data = NULL;
+       int ret = 0;
 
        if (data == NULL) {
                _E("Invalid parameter: data(NULL)");
@@ -597,19 +654,35 @@ static void delete_hal_backend_service_thread(gpointer data, gpointer user_data)
        }
        service_data = (struct hal_backend_service_data *)data;
 
-       destroy_thread(service_data->thread);
-       service_data->thread = NULL;
+       if (service_data->task == NULL) {
+               _D("No task for hal_module(%d)", service_data->module);
+               return;
+       }
 
-       _D("Thread destroyed for hal_module(%d)", service_data->module);
+       ret = tizen_core_task_quit(service_data->task);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to quit task for hal_module(%d)", service_data->module);
+               return;
+       }
+
+       ret = tizen_core_task_destroy(service_data->task);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to destroy task for hal_module(%d)", service_data->module);
+               return;
+       }
+
+       service_data->task = NULL;
+
+       _D("Task destroyed for hal_module(%d)", service_data->module);
 }
 
 static void hal_backend_service_start(void)
 {
        size_t failed_count = 0;
 
-       /* Create threads for hal-backend-service and then tie them */
+       /* Create tasks for hal-backend-service and then tie them */
        g_slist_foreach(g_hal_backend_service_data_list,
-                       create_hal_backend_service_thread,
+                       (GFunc)create_hal_backend_service_task,
                        &failed_count);
        if (failed_count != 0)
                _W("Cannot register %zu service(s)", failed_count);
@@ -618,7 +691,7 @@ static void hal_backend_service_start(void)
 static void hal_backend_service_stop(void)
 {
        g_slist_foreach(g_hal_backend_service_data_list,
-                       delete_hal_backend_service_thread, NULL);
+                       delete_hal_backend_service_task, NULL);
 }
 
 /**
@@ -629,8 +702,8 @@ static gboolean handle_signal_glib(gpointer data)
        int signal_number = (int)data;
 
        _D("Received signal(%d)", signal_number);
-       if (g_g_main_loop != NULL)
-               g_main_loop_quit(g_g_main_loop);
+       if (g_main_task != NULL)
+               tizen_core_task_quit(g_main_task);
 
        return G_SOURCE_REMOVE;
 }
@@ -653,9 +726,18 @@ static void attach_signal_handlers(void)
 
 int main(int argc, char **argv)
 {
+       int ret = 0;
+
        _D("Initialize hal-backend-service");
 
-       g_g_main_loop = g_main_loop_new(NULL, FALSE);
+       tizen_core_init();
+
+       ret = tizen_core_task_create("main", false, &g_main_task);
+       if (ret != TIZEN_CORE_ERROR_NONE) {
+               _E("Failed to create tizen_core main task: ret(%d)", ret);
+               tizen_core_shutdown();
+               return 1;
+       }
 
        rpc_port_register_proc_info(RPC_STUB_PROC_NAME, NULL);
 
@@ -665,12 +747,16 @@ int main(int argc, char **argv)
 
        attach_signal_handlers();
 
-       g_main_loop_run(g_g_main_loop);
+       tizen_core_task_run(g_main_task);
 
        /* Un-load hal-backend-service plugin */
        hal_backend_service_stop();
        hal_backend_service_delete_and_close_plugin();
 
+       tizen_core_task_destroy(g_main_task);
+
+       tizen_core_shutdown();
+
        _D("Exit hal-backend-service");
 
        return 0;
diff --git a/hal-backend-service/thread.c b/hal-backend-service/thread.c
deleted file mode 100644 (file)
index 8bd49b4..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2025 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 <stdlib.h>
-#include <errno.h>
-
-#include "thread.h"
-
-static void __thread_loop_main(void *_ctx)
-{
-       enum thread_return ret = THREAD_RETURN_DONE;
-       enum thread_return finalize_ret = THREAD_RETURN_DONE;
-       struct thread_context *ctx = _ctx;
-       void *result = NULL;
-
-       mtx_lock(&ctx->lock);
-       while (ctx->state != THREAD_STATE_TERMINATED) {
-               if (ctx->timer.tv_sec || ctx->timer.tv_nsec) {
-                       mtx_unlock(&ctx->lock);
-                       thrd_sleep(&ctx->timer, NULL);
-                       mtx_lock(&ctx->lock);
-               }
-
-               while (ctx->state == THREAD_STATE_STOPPED)
-                       cnd_wait(&ctx->wait, &ctx->lock);
-               if (ctx->state == THREAD_STATE_TERMINATED)
-                       break;
-
-               mtx_unlock(&ctx->lock);
-               ret = ctx->func(ctx->func_arg, &result);
-               mtx_lock(&ctx->lock);
-
-               if (ret != THREAD_RETURN_CONTINUE) {
-                       ctx->state = THREAD_STATE_TERMINATED;
-                       ctx->result = result;
-               }
-       }
-       mtx_unlock(&ctx->lock);
-
-       if (ctx->finalize != NULL)
-               finalize_ret = ctx->finalize(ctx->finalize_arg);
-
-       if (finalize_ret != THREAD_RETURN_DONE)
-               ret = finalize_ret;
-
-       thrd_exit(ret);
-}
-
-static void do_destroy_thread(struct thread *thread)
-{
-       struct thread_context *ctx = thread->ctx;
-
-       mtx_lock(&ctx->lock);
-       ctx->state = THREAD_STATE_TERMINATED;
-       mtx_unlock(&ctx->lock);
-
-       /* try to wake up thread whether it is sleeping or not */
-       cnd_signal(&ctx->wait);
-
-       thrd_join(thread->id, NULL);
-
-       cnd_destroy(&ctx->wait);
-       mtx_destroy(&ctx->lock);
-}
-
-void destroy_thread(struct thread *thread)
-{
-       do_destroy_thread(thread);
-       free(thread->ctx);
-       thread->ctx = NULL;
-
-       free(thread);
-}
-
-static int do_create_thread(struct thread **thread, enum thread_type type,
-                       u_int32_t timer_expire_msec,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg)
-{
-       struct thread *new_thread;
-       struct thread_context *ctx;
-       thrd_t tid;
-       int ret;
-
-       if (!thread || !func)
-               return -EINVAL;
-
-       new_thread = malloc(sizeof(struct thread));
-       if (!new_thread)
-               return -ENOMEM;
-
-       ctx = calloc(1, sizeof(struct thread_context));
-       if (!ctx) {
-               ret = -ENOMEM;
-               goto err_malloc;
-       }
-
-       mtx_init(&ctx->lock, mtx_plain);
-       cnd_init(&ctx->wait);
-
-       ctx->func = func;
-       ctx->func_arg = func_arg;
-       ctx->finalize = finalize;
-       ctx->finalize_arg = finalize_arg;
-
-       mtx_lock(&ctx->lock);
-       switch (type) {
-       case THREAD_TYPE_WORKER:
-               ctx->state = THREAD_STATE_STOPPED;
-               break;
-       case THREAD_TYPE_DAEMON:
-               ctx->state = THREAD_STATE_RUNNING;
-               break;
-       case THREAD_TYPE_TIMER:
-               ctx->state = THREAD_STATE_RUNNING;
-               ctx->timer = (struct timespec) {
-                       .tv_sec = timer_expire_msec / 1000,
-                       .tv_nsec = (timer_expire_msec % 1000) * 1000000,
-               };
-               break;
-       default:
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = thrd_create(&tid, (thrd_start_t) __thread_loop_main, (void *)ctx);
-       if (ret == thrd_error) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       new_thread->id = tid;
-       new_thread->ctx = ctx;
-
-       *thread = new_thread;
-       mtx_unlock(&ctx->lock);
-
-       return 0;
-
-err:
-       mtx_unlock(&ctx->lock);
-       cnd_destroy(&ctx->wait);
-       mtx_destroy(&ctx->lock);
-       free(ctx);
-err_malloc:
-       free(new_thread);
-
-       return ret;
-}
-
-int create_daemon_thread(struct thread **thread,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg)
-{
-       return do_create_thread(thread, THREAD_TYPE_DAEMON, 0, func, func_arg,
-                               finalize, finalize_arg);
-}
-
-int create_timer_thread(struct thread **thread, u_int32_t timer_expire_msec,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg)
-{
-       return do_create_thread(thread, THREAD_TYPE_TIMER, timer_expire_msec,
-                       func, func_arg, finalize, finalize_arg);
-}
-
-int create_worker_thread(struct thread **thread,
-                       int (*func)(void *, void **), void *arg,
-                       int (*finalize)(void *), void *finalize_arg)
-{
-       return do_create_thread(thread, THREAD_TYPE_WORKER, 0, func, arg,
-                               finalize, finalize_arg);
-}
-
-void suspend_thread(struct thread *thread)
-{
-       struct thread_context *ctx = thread->ctx;
-
-       mtx_lock(&ctx->lock);
-       ctx->state = THREAD_STATE_STOPPED;
-       mtx_unlock(&ctx->lock);
-}
-
-void resume_thread(struct thread *thread)
-{
-       struct thread_context *ctx = thread->ctx;
-
-       mtx_lock(&ctx->lock);
-       ctx->state = THREAD_STATE_RUNNING;
-       mtx_unlock(&ctx->lock);
-       cnd_signal(&ctx->wait);
-}
-
-int wait_for_completion(struct thread *thread, void **result)
-{
-       struct thread_context *ctx = thread->ctx;
-       int ret;
-
-       thrd_join(thread->id, &ret);
-       if (ret == THREAD_RETURN_ERROR)
-               return ret;
-
-       if (result)
-               *result = ctx->result;
-
-       cnd_destroy(&ctx->wait);
-       mtx_destroy(&ctx->lock);
-
-       free(thread->ctx);
-       thread->ctx = NULL;
-
-       free(thread);
-
-       return 0;
-}
diff --git a/hal-backend-service/thread.h b/hal-backend-service/thread.h
deleted file mode 100644 (file)
index bac0970..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2025 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.
- */
-
-#pragma once
-
-#include <stdlib.h>
-#include <threads.h>
-#include <time.h>
-
-enum thread_type {
-       THREAD_TYPE_WORKER,
-       THREAD_TYPE_DAEMON,
-       THREAD_TYPE_TIMER,
-};
-
-enum thread_state {
-       THREAD_STATE_RUNNING,
-       THREAD_STATE_STOPPED,
-       THREAD_STATE_TERMINATED,
-};
-
-enum thread_return {
-       THREAD_RETURN_ERROR = -EXIT_FAILURE,
-       THREAD_RETURN_DONE = EXIT_SUCCESS,
-       THREAD_RETURN_CONTINUE,
-};
-
-struct thread_context {
-       enum thread_state state;
-       struct timespec timer;
-       int (*func)(void *func_arg, void **result);
-       int (*finalize)(void *finalize_arg);
-       void *func_arg;
-       void *result;
-       void *finalize_arg;
-       mtx_t lock;
-       cnd_t wait;
-};
-
-struct thread {
-       thrd_t id;
-       struct thread_context *ctx;
-};
-
-int create_daemon_thread(struct thread **thread,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg);
-int create_timer_thread(struct thread **thread, u_int32_t timer_expire_msec,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg);
-int create_worker_thread(struct thread **thread,
-                       int (*func)(void *, void **), void *func_arg,
-                       int (*finalize)(void *), void *finalize_arg);
-
-void destroy_thread(struct thread *thread);
-void suspend_thread(struct thread *thread);
-void resume_thread(struct thread *thread);
-
-int wait_for_completion(struct thread *thread, void **result);
index 534a843583edee6d26009cc08a629eb1076fe52f..50b9a10e25e8f2157c03b5414395c5c05675808d 100644 (file)
@@ -42,6 +42,7 @@ BuildRequires: pkgconfig(systemd)
 BuildRequires: pkgconfig(capi-base-common)
 BuildRequires: pkgconfig(rpc-port)
 BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(tizen-core)
 
 %description
 %{name} interface