Delegate socket activation to a booster thread 19/277919/2 accepted/tizen/unified/20220719.131728 submit/tizen/20220718.101839
authorUnsung Lee <unsung.lee@samsung.com>
Fri, 15 Jul 2022 05:03:11 +0000 (14:03 +0900)
committerUnsung Lee <unsung.lee@samsung.com>
Fri, 15 Jul 2022 05:14:28 +0000 (14:14 +0900)
Change-Id: Ie9d2e928f60b8d1322f73697c459a8f74d80b22e
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
src/common/cpu-common.h
src/common/fd-handler.c
src/common/fd-handler.h
src/process/block/block-monitor.c
src/process/proc-usage-stats.c
src/resource-limiter/memory/lowmem-limit.c
src/resource-limiter/memory/vmpressure-lowmem-handler.c
src/resource-optimizer/cpu/cpu-boosting.c
src/resource-optimizer/cpu/cpu-hotplug.c

index 0f4e5f6..f4518ff 100644 (file)
@@ -41,14 +41,9 @@ enum cpu_sched_type {
        CPU_SCHED_DEADLINE,
 };
 
-struct cpu_boosting_worker {
-       pthread_t thread;
-       GAsyncQueue *queue;
-       int active;
-};
-
 struct cpu_boosting_info {
        pid_t tid;
+       int level;                     /* current boosting level */
        struct sched_attr origin_attr; /* cpu attribute before the first boosting */
        guint gsource_id;              /* timer id */
 };
index b950a21..30ae2a7 100644 (file)
@@ -105,7 +105,7 @@ static gboolean channel_changed(GIOChannel *source,
        return FALSE;
 }
 
-int add_fd_read_handler(int fd,
+int add_fd_read_handler(GMainContext *context, int fd,
                fd_changed_cb callback, void *data,
                release_cb free_func, fd_handler_h *handler)
 {
@@ -127,8 +127,18 @@ int add_fd_read_handler(int fd,
                return -ENOMEM;
        }
 
-       id = g_io_add_watch(ch, G_IO_IN | G_IO_ERR | G_IO_HUP,
-                       channel_changed, h);
+       if (context == NULL) {
+               id = g_io_add_watch(ch, G_IO_IN | G_IO_ERR | G_IO_HUP,
+                               channel_changed, h);
+       }
+       else {
+               GSource *source = g_io_create_watch(ch, G_IO_IN | G_IO_ERR | G_IO_HUP);
+               g_source_set_callback(source, (GSourceFunc)channel_changed, h, NULL);
+
+               id = g_source_attach(source, context);
+               g_source_unref(source);
+       }
+
        if (id == 0) {
                _E("Failed to add watch for GIOChannel");
                free(h);
index d4f4592..3c8405f 100644 (file)
@@ -48,6 +48,7 @@ typedef void (*release_cb)(void *data);
 /**
  * @brief   Register file descriptor callback function
  * @since_tizen 4.0
+ * @param[in]  context The context of the event.
  * @param[in]  fd    The file descriptor to notify the changes.
  * @param[in]  callback The callback function which will be called when the fd is changed.
  * @param[in]  data  The user data which is delivered to the callback function.
@@ -57,7 +58,7 @@ typedef void (*release_cb)(void *data);
  *          otherwise a negative error value
  * @remarks If the callback function returns false, the fd handler is removed automatically and the callback will not be called again.
  */
-int add_fd_read_handler(int fd, fd_changed_cb callback,
+int add_fd_read_handler(GMainContext *context, int fd, fd_changed_cb callback,
                void *data, release_cb free_func,
                fd_handler_h *handler);
 
index ec84551..d058dac 100644 (file)
@@ -278,7 +278,7 @@ int register_fanotify(struct block_monitor_info *bmi)
                _E("Failed to mark fanotify for %s", bmi->path);
                goto error;
        }
-       add_fd_read_handler(bmi->mfd, block_monitor_cb, bmi, NULL, &(bmi->fd_handler));
+       add_fd_read_handler(NULL, bmi->mfd, block_monitor_cb, bmi, NULL, &(bmi->fd_handler));
        block_logging_init(bmi);
        return RESOURCED_ERROR_NONE;
 error:
index 49c6799..8bdcd7a 100644 (file)
@@ -283,7 +283,7 @@ void proc_runtime_info_request_handler(GDBusMethodInvocation *invocation,
                ret = -EIO;
                goto error;
        }
-       ret = add_fd_read_handler(rt_task->pipe_fds[0], proc_runtime_info_task_cb,
+       ret = add_fd_read_handler(NULL, rt_task->pipe_fds[0], proc_runtime_info_task_cb,
                        (void *)rt_task, NULL, &fd_handler);
        if (ret) {
                _E("task %s: error creating glib file handler", rt_task->task_name);
index e9e5722..ee7a11c 100644 (file)
@@ -338,7 +338,7 @@ int lowmem_reassign_limit(const char *dir,
                }
                mle->action = action;
                mle->threshold_bytes = limit_bytes;
-               add_fd_read_handler(fd, memory_action_cb, mle->path, NULL, NULL);
+               add_fd_read_handler(NULL, fd, memory_action_cb, mle->path, NULL, NULL);
                g_hash_table_insert(memory_limit_hash, (gpointer)mle->path,
                                (gpointer)mle);
 
index 89cb30c..25d46e4 100644 (file)
@@ -1534,7 +1534,7 @@ static int lowmem_press_register_eventfd(struct memcg_info *mi)
 
        mi->evfd = evfd;
 
-       add_fd_read_handler(evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
+       add_fd_read_handler(NULL, evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
        return 0;
 }
 
index 7426fe8..28673ba 100644 (file)
 #include "proc-common.h"
 
 static GHashTable *tid_table;  /* cpu_boosting info per thread (tid, attr, gsource_id) hash table */
-static pthread_mutex_t  mutex;
-static struct cpu_boosting_worker worker;
+pthread_t cpu_boosting_thread;
 static struct sched_attr cpu_boosting_attr[CPU_BOOSTING_LEVEL_END];
 static bool cpu_boosting_success[CPU_BOOSTING_LEVEL_END] = {false, };
 
+GMainLoop *cpu_boosting_loop;
+GMainContext *cpu_boosting_context;
+
 static void cpu_boosting_destroy_request(struct cpu_boosting_input *input);
 
 #define SOCK_PATH "/run/.resourced.socket"
 
-#define CPU_BOOSTING_WORKER_IS_ACTIVE  g_atomic_int_get(&worker.active)
-#define CPU_BOOSTING_WORKER_ACTIVATE   g_atomic_int_set(&worker.active, 1)
-#define CPU_BOOSTING_WORKER_DEACTIVATE g_atomic_int_set(&worker.active, 0)
-
 #define CPU_BOOSTING_SET_REQUEST(_input, _command, _level, _timeout_msec, _pid) \
 {                                                                               \
        (_input)->client_input.command = _command;                                  \
@@ -43,16 +41,6 @@ static void cpu_boosting_destroy_request(struct cpu_boosting_input *input);
        (_input)->client_input.pid = _pid;                                          \
 }
 
-#define CPU_BOOSTING_ENQUEUE_REQUEST(_input)                                \
-       do {                                                                    \
-               if (CPU_BOOSTING_WORKER_IS_ACTIVE)                                  \
-                       g_async_queue_push(worker.queue, _input);                       \
-               else {                                                              \
-                       _W("[CPU-BOOSTING] Cpu boosting is not active");                \
-                       cpu_boosting_destroy_request(_input);                           \
-               }                                                                   \
-       } while (0)
-
 static cpu_boosting_level_e cpu_boosting_level_search(struct sched_attr attr)
 {
        for (int level = CPU_BOOSTING_LEVEL_STRONG; level < CPU_BOOSTING_LEVEL_END; level++) {
@@ -236,7 +224,7 @@ static void load_cpu_boosting_configs(void)
        }
 }
 
-static void cpu_boosting_send_reply(int sock, cpu_boosting_output_t *output)
+static void cpu_boosting_send_reply(int sock, cpu_boosting_output_t output)
 {
        int byte;
 
@@ -247,65 +235,84 @@ static void cpu_boosting_send_reply(int sock, cpu_boosting_output_t *output)
                return;
        }
 
-       if (output->level.tid_level && output->level.tid_count > 0) {
+       if (output.level.tid_level && output.level.tid_count > 0) {
                /* Send a header first */
-               byte = send(sock, (const void *)output, sizeof(*output), 0);
-               if (byte != sizeof(*output)) {
+               byte = send(sock, (const void *)&output, sizeof(output), 0);
+               if (byte != sizeof(output)) {
                        _E("[CPU-BOOSTING] Server output size is %u, but sent size is %d",
-                                       (unsigned int)sizeof(*output), byte);
+                                       (unsigned int)sizeof(output), byte);
                        return;
                }
 
                /* Check body size */
-               byte = send(sock, (const void *)output->level.tid_level,
-                               output->level.tid_count * sizeof(int), 0);
-               if (byte != output->level.tid_count * sizeof(int)) {
+               byte = send(sock, (const void *)output.level.tid_level,
+                               output.level.tid_count * sizeof(int), 0);
+               if (byte != output.level.tid_count * sizeof(int)) {
                        _E("[CPU-BOOSTING] Server output size is %u, but sent size is %d",
-                                       output->level.tid_count * (unsigned int)sizeof(int), byte);
+                                       output.level.tid_count * (unsigned int)sizeof(int), byte);
                        return;
                }
 
-               if (output->level.tid_level)
-                       free(output->level.tid_level);
+               if (output.level.tid_level)
+                       free(output.level.tid_level);
        }
        else {
                /* Send a header */
-               byte = send(sock, (const void *)&output->success, sizeof(output->success), 0);
-               if (byte != sizeof(output->success)) {
+               byte = send(sock, (const void *)&output.success, sizeof(output.success), 0);
+               if (byte != sizeof(output.success)) {
                        _E("[CPU-BOOSTING] Server output size is %u, but sent size is %d",
-                                       (unsigned int)sizeof(output->success), byte);
+                                       (unsigned int)sizeof(output.success), byte);
                        return;
                }
        }
 }
 
-static int cpu_boosting_enqueue_by_socket(int sock)
+static int cpu_boosting_enqueue_by_socket(int sock, struct cpu_boosting_input **input_p)
 {
        int ret = RESOURCED_ERROR_NONE;
        int byte;
-       struct cpu_boosting_input *input;
-//     cpu_boosting_output_t output;
 
-       input = cpu_boosting_new_request();
+       struct cpu_boosting_input *input = cpu_boosting_new_request();
        if (input == NULL) {
                ret = RESOURCED_ERROR_OUT_OF_MEMORY;
                goto destroy_input;
        }
+       else
+               *input_p = input;
 
        /* Get a header from the client */
        byte = recv(sock, (void *)&input->client_input, sizeof(input->client_input), 0);
        if (byte != sizeof(input->client_input)) {
                ret = RESOURCED_ERROR_FAIL;
-               if (byte == 0)
-                       goto destroy_input; /* connection is closed */
+               if (byte < 0)
+                       _E("[CPU-BOOSTING] error is based on %s", strerror(errno));
+               else if (byte > 0) {
+                       _E("[CPU-BOOSTING] client input size is %u, but received size is %d",
+                                       (unsigned int)sizeof(input->client_input), byte);
+                       input->client_input.pid.tid = NULL;
+               }
 
-               _E("[CPU-BOOSTING] error is based on %s", strerror(errno));
-               _E("[CPU-BOOSTING] client input size is %u, but received size is %d",
-                               (unsigned int)sizeof(input->client_input), byte);
-               input->client_input.pid.tid = NULL;
                goto destroy_input;
        }
 
+       if (input->client_input.command == CPU_BOOSTING_COMMAND_CLEAR ||
+               input->client_input.command == CPU_BOOSTING_COMMAND_SET) {
+               if (input->client_input.level < CPU_BOOSTING_LEVEL_NONE ||
+                       input->client_input.level > CPU_BOOSTING_LEVEL_WEAK) {
+                       ret = RESOURCED_ERROR_FAIL;
+                       _E("[CPU-BOOSTING] cpu boosting (level = %d) is out of scope",
+                                       input->client_input.level);
+                       goto destroy_input;
+               }
+
+               if (!cpu_boosting_success[input->client_input.level]) {
+                       ret = RESOURCED_ERROR_FAIL;
+                       _I("[CPU-BOOSTING] cpu boosting (level = %d) is not supported",
+                                       input->client_input.level);
+                       goto destroy_input;
+               }
+       }
+
        /* Check body size */
        input->client_input.pid.tid = NULL;
        if (input->client_input.body_size > 0 &&
@@ -335,6 +342,14 @@ static int cpu_boosting_enqueue_by_socket(int sock)
 
                        goto destroy_input;
                }
+
+               /*
+                *  TODO: Checking whether Thread ID is valid or  not
+                *
+                *  for (int i = 0; i < tid_count; i++) {
+                *      if (tid_list[i] <= 0)
+                *              goto destroy_input;
+               }*/
        }
        else if (input->client_input.body_size == 0 &&
              input->client_input.pid.pid > 0) {
@@ -349,7 +364,7 @@ static int cpu_boosting_enqueue_by_socket(int sock)
 
        if (input->client_input.command == CPU_BOOSTING_COMMAND_GET)
                input->sock = sock;     /* For a reply */
-       CPU_BOOSTING_ENQUEUE_REQUEST(input);
+
        return RESOURCED_ERROR_NONE;
 
 destroy_input:
@@ -359,13 +374,12 @@ destroy_input:
 }
 
 /* Called by resourced main thread */
-static int cpu_boosting_enqueue_by_conf(void *data)
+static int cpu_boosting_enqueue_by_conf(void *data, struct cpu_boosting_input **input)
 {
        assert(data);
 
        int ret;
        struct proc_status *ps = (struct proc_status *)data;
-       struct cpu_boosting_input *input;
        cpu_boosting_level_e cpu_boosting_level;
        resource_pid_t pid;
 
@@ -389,24 +403,15 @@ static int cpu_boosting_enqueue_by_conf(void *data)
        if (ret != RESOURCED_ERROR_NONE)
                return ret;
 
-       input = cpu_boosting_new_request();
-       if (input == NULL)
+       *input = cpu_boosting_new_request();
+       if (*input == NULL)
                return RESOURCED_ERROR_FAIL;
 
-       CPU_BOOSTING_SET_REQUEST(input, CPU_BOOSTING_COMMAND_SET, cpu_boosting_level, -1, pid);
-       CPU_BOOSTING_ENQUEUE_REQUEST(input);
+       CPU_BOOSTING_SET_REQUEST(*input, CPU_BOOSTING_COMMAND_SET, cpu_boosting_level, -1, pid);
 
        return RESOURCED_ERROR_NONE;
 }
 
-/* Called by the last calling thread which calls unref */
-static void cpu_boosting_input_destroy(gpointer data)
-{
-       struct cpu_boosting_input *input = (struct cpu_boosting_input *)data;
-
-       cpu_boosting_destroy_request(input);
-}
-
 static gboolean cpu_boosting_timeout(gpointer data)
 {
        int ret;
@@ -422,23 +427,18 @@ static gboolean cpu_boosting_timeout(gpointer data)
 
        for (int i = 0; i < tid_count; i++) {
                if (tid_list[i] > 0) {
-                       pthread_mutex_lock(&mutex);
-
                        struct cpu_boosting_info *info = g_hash_table_lookup(tid_table, &tid_list[i]);
                        /*
                         * info is NULL when clearing boosting before timeout
                         * info->gsource_id != *(input->gsource_id) when setting boosting again before timeout
                         */
                        if (info == NULL || info->gsource_id != *(input->gsource_id)) {
-                               pthread_mutex_unlock(&mutex);
                                continue;
                        }
 
                        ret = sched_setattr(tid_list[i], &info->origin_attr, 0);
                        g_hash_table_remove(tid_table, &tid_list[i]);
 
-                       pthread_mutex_unlock(&mutex);
-
                        if (ret != RESOURCED_ERROR_NONE)
                                _E("[CPU-BOOSTING] Failed to clear boost cpu of (tid = %d)", tid_list[i]);
                }
@@ -452,16 +452,12 @@ timer_out:
        return G_SOURCE_REMOVE;
 }
 
-static struct cpu_boosting_info *cpu_boosting_find_and_insert_attr(pid_t tid)
+static struct cpu_boosting_info *cpu_boosting_find_and_insert_attr(pid_t tid, cpu_boosting_level_e level)
 {
        int ret;
 
-       pthread_mutex_lock(&mutex);
-
        struct cpu_boosting_info *info = g_hash_table_lookup(tid_table, &tid);
        if (info == NULL) {
-               pthread_mutex_unlock(&mutex);
-
                info = (struct cpu_boosting_info *)calloc(1, sizeof (struct cpu_boosting_info));
                if (info == NULL) {
                        _E("[CPU-BOOSTING] Failed to allocate memory");
@@ -474,13 +470,11 @@ static struct cpu_boosting_info *cpu_boosting_find_and_insert_attr(pid_t tid)
                        return NULL;
                }
                info->tid = tid;
-
-               pthread_mutex_lock(&mutex);
                g_hash_table_insert(tid_table, &info->tid, info);
        }
 
+       info->level = level;
        info->gsource_id = 0;
-       pthread_mutex_unlock(&mutex);
        return info;
 }
 
@@ -507,12 +501,14 @@ static void cpu_boosting_set(struct cpu_boosting_input *input)
 
        for (int i = 0; i < tid_count; i++) {
                if (tid_list[i] > 0) {
-                       if ((info = cpu_boosting_find_and_insert_attr(tid_list[i])) == NULL) {
+                       if ((info = cpu_boosting_find_and_insert_attr(tid_list[i], cpu_boosting_level)) == NULL) {
                                fail_cnt++;
                                continue;
                        }
 
                        if (sched_setattr(tid_list[i], &cpu_boosting_attr[cpu_boosting_level], 0) < 0) {
+                               g_hash_table_remove(tid_table, &tid_list[i]);
+
                                _E("[CPU-BOOSTING] Failed to boost cpu of (tid = %d) with (level = %d)",
                                                tid_list[i], cpu_boosting_level);
                                fail_cnt++;
@@ -520,9 +516,8 @@ static void cpu_boosting_set(struct cpu_boosting_input *input)
                        }
                        success_cnt++;
                }
-               else {
+               else
                        _E("[CPU-BOOSTING] Thread (id = %d) should be larger than 0", tid_list[i]);
-               }
        }
 
        if (fail_cnt > 0)
@@ -535,8 +530,13 @@ static void cpu_boosting_set(struct cpu_boosting_input *input)
         * then set the timer to restore
         */
        if (timeout_msec > 0 && success_cnt > 0) {
+               GSource *source;
                input->gsource_id = g_new(guint, 1);
-               *(input->gsource_id) = g_timeout_add(timeout_msec, cpu_boosting_timeout, input);
+
+               source = g_timeout_source_new(timeout_msec);
+               g_source_set_callback(source, cpu_boosting_timeout, input, NULL);
+               *(input->gsource_id) = g_source_attach(source, cpu_boosting_context);
+               g_source_unref(source);
 
                for (int i = 0; i < tid_count; i++) {
                        if (tid_list[i] > 0)
@@ -557,12 +557,8 @@ static void cpu_boosting_clear(struct cpu_boosting_input *input)
 
        for (int i = 0; i < tid_count; i++) {
                if (tid_list[i] > 0) {
-                       pthread_mutex_lock(&mutex);
-
                        struct cpu_boosting_info *info = g_hash_table_lookup(tid_table, &tid_list[i]);
                        if (info == NULL) {
-                               pthread_mutex_unlock(&mutex);
-
                                struct sched_attr attr;
                                if (sched_getattr(tid_list[i], &attr, 0) < 0) {
                                        _E("[CPU-BOOSTING] Failed to get boost cpu of (tid = %d)", tid_list[i]);
@@ -581,7 +577,7 @@ static void cpu_boosting_clear(struct cpu_boosting_input *input)
                                        }
                                }
                                else {
-                                       _E("[CPU-BOOSTING] Try to clear non-boosted process (policy = %d, priority = %d, nice = %d", attr.sched_policy, attr.sched_priority, attr.sched_nice);
+                                       _W("[CPU-BOOSTING] Try to clear non-boosted process (policy = %d, priority = %d, nice = %d", attr.sched_policy, attr.sched_priority, attr.sched_nice);
                                        fail_cnt++;
                                        continue;
                                }
@@ -589,9 +585,6 @@ static void cpu_boosting_clear(struct cpu_boosting_input *input)
                        else {
                                ret = sched_setattr(tid_list[i], &info->origin_attr, 0);
                                g_hash_table_remove(tid_table, &tid_list[i]);
-
-                               pthread_mutex_unlock(&mutex);
-
                                if (ret != RESOURCED_ERROR_NONE) {
                                        _E("[CPU-BOOSTING] Failed to clear boost cpu of (tid = %d)", tid_list[i]);
                                        fail_cnt++;
@@ -601,9 +594,8 @@ static void cpu_boosting_clear(struct cpu_boosting_input *input)
 
                        success_cnt++;
                }
-               else {
+               else
                        _E("[CPU-BOOSTING] Thread (id = %d) should be larger than 0", tid_list[i]);
-               }
        }
 
        if (fail_cnt > 0)
@@ -614,18 +606,18 @@ static void cpu_boosting_clear(struct cpu_boosting_input *input)
        cpu_boosting_destroy_request(input);
 }
 
-
-static void cpu_boosting_get(struct cpu_boosting_input *input,
-               cpu_boosting_output_t *output)
+static void cpu_boosting_get(struct cpu_boosting_input *input)
 {
        int fail_cnt = 0;
        int success_cnt = 0;
        struct sched_attr attr;
+       cpu_boosting_output_t output;
        int tid_count = input->client_input.pid.tid_count;
        int *tid_list = input->client_input.pid.tid;
 
-       output->level.tid_level = (int *)calloc(tid_count, sizeof (int));
-       if (output->level.tid_level == NULL) {
+       memset(&output, 0, sizeof (output));
+       output.level.tid_level = (int *)calloc(tid_count, sizeof (int));
+       if (output.level.tid_level == NULL) {
                _E("[CPU-BOOSTING] Failed to allocate memory");
                fail_cnt = 1;
                goto output_update;
@@ -633,96 +625,41 @@ static void cpu_boosting_get(struct cpu_boosting_input *input,
 
        for (int i = 0; i < tid_count; i++) {
                if (tid_list[i] > 0) {
-                       if (sched_getattr(tid_list[i], &attr, 0) < 0) {
-                               _E("[CPU-BOOSTING] Failed to get boost cpu of (tid = %d)", tid_list[i]);
-                               fail_cnt++;
-                               continue;
+                       struct cpu_boosting_info *info = g_hash_table_lookup(tid_table, &tid_list[i]);
+                       if (info == NULL) {
+                               if (sched_getattr(tid_list[i], &attr, 0) < 0) {
+                                       _E("[CPU-BOOSTING] Failed to get boost cpu of (tid = %d)", tid_list[i]);
+                                       fail_cnt++;
+                                       continue;
+                               }
+                               output.level.tid_level[success_cnt++] = cpu_boosting_level_search(attr);
                        }
-                       output->level.tid_level[success_cnt++] = cpu_boosting_level_search(attr);
+                       else
+                               output.level.tid_level[success_cnt++] = info->level;
                }
                else {
                        fail_cnt++;
                        _E("[CPU-BOOSTING] Thread (id = %d) should be larger than 0", tid_list[i]);
                }
        }
-       output->level.tid_count = success_cnt;
+       output.level.tid_count = success_cnt;
+       if (success_cnt == 0)
+               free(output.level.tid_level);
 
 output_update:
        if (fail_cnt > 0) {
                _E("[CPU-BOOSTING] Get boosting success ratio = %d/%d", success_cnt, fail_cnt + success_cnt);
-               output->success = false;
+               output.success = false;
        }
        else {
                _D("[CPU-BOOSTING] Success CPU boosting get");
-               output->success = true;
+               output.success = true;
        }
 
        cpu_boosting_send_reply(input->sock, output);
        cpu_boosting_destroy_request(input);
 }
 
-/* Cpu boosting thread's main code */
-static void *cpu_boosting_func(void *data)
-{
-       CPU_BOOSTING_WORKER_ACTIVATE;
-
-       setpriority(PRIO_PROCESS, 0, CPU_MIN_NICE);
-
-       g_async_queue_ref(worker.queue);
-
-       while (1) {
-               struct cpu_boosting_input *input;
-               cpu_boosting_output_t output;
-
-               if (!CPU_BOOSTING_WORKER_IS_ACTIVE)
-                       break;
-
-               input = g_async_queue_pop(worker.queue);
-               if (!input) {
-                       _E("[CPU-BOOSTING] Cpu boosting input data structure should not be NULL");
-                       continue;
-               }
-
-               /*
-                * Whether current boosting level is supported or not should be checked before
-                * calling CPU_BOOSTING_ENQUEUE_REQUEST. That is the cpu boosting thread ignores it
-                */
-               switch (input->client_input.command) {
-                       case CPU_BOOSTING_COMMAND_SET:
-                               cpu_boosting_set(input);
-                               break;
-                       case CPU_BOOSTING_COMMAND_CLEAR:
-                               cpu_boosting_clear(input);
-                               break;
-                       case CPU_BOOSTING_COMMAND_GET:
-                               output.level.tid_level = NULL;
-                               output.level.tid_count = 0;
-                               cpu_boosting_get(input, &output);
-                               break;
-                       case CPU_BOOSTING_COMMAND_NONE:
-                       default:
-                               _E("[CPU-BOOSTING] Unknwon cpu boosting command");
-                               cpu_boosting_destroy_request(input);
-               }
-       }
-
-       g_async_queue_unref(worker.queue);
-
-       pthread_exit(NULL);
-}
-
-/* Called by resourced main thread */
-static void cpu_boosting_drain_queue(void)
-{
-       struct cpu_boosting_input *input;
-
-       g_async_queue_lock(worker.queue);
-       while ((input = g_async_queue_try_pop_unlocked(worker.queue))) {
-               cpu_boosting_destroy_request(input);
-       }
-       g_async_queue_unlock(worker.queue);
-}
-
 static int cpu_boosting_init_socket(void)
 {
        /* Create a server socket */
@@ -773,23 +710,85 @@ close_sock:
        return 0;
 }
 
+static void cpu_boosting_handle_command(struct cpu_boosting_input *input)
+{
+       if (!input) {
+               _E("[CPU-BOOSTING] Cpu boosting input data structure should not be NULL");
+               return;
+       }
+
+       /*
+        * Whether current boosting level is supported or not should be checked before
+        * calling CPU_BOOSTING_ENQUEUE_REQUEST. That is the cpu boosting thread ignores it
+        */
+       switch (input->client_input.command) {
+               case CPU_BOOSTING_COMMAND_SET:
+                       cpu_boosting_set(input);
+                       break;
+               case CPU_BOOSTING_COMMAND_CLEAR:
+                       cpu_boosting_clear(input);
+                       break;
+               case CPU_BOOSTING_COMMAND_GET:
+
+                       cpu_boosting_get(input);
+                       break;
+               case CPU_BOOSTING_COMMAND_NONE:
+               default:
+                       _E("[CPU-BOOSTING] Unknown cpu boosting (command = %d)", input->client_input.command);
+                       cpu_boosting_destroy_request(input);
+       }
+}
+
+static int cpu_boosting_recv_from_conf(void *data)
+{
+       int ret;
+       struct cpu_boosting_input *input = NULL;
+
+       if ((ret = cpu_boosting_enqueue_by_conf(data, &input)) < 0 ||
+                       input == NULL)
+               return ret;
+
+       if (input->client_input.pid.tid_count == 0) {
+               _E("[CPU-BOOSTING] The number of tids should be larger than 0");
+               cpu_boosting_destroy_request(input);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       cpu_boosting_handle_command(input);
+
+       return RESOURCED_ERROR_NONE;
+}
+
 /* Client asks send() to the resourced, so call recv() */
 static bool cpu_boosting_recv_from_client(int fd, void *data)
 {
        int client_sock = fd;
+       struct cpu_boosting_input *input = NULL;
 
        if (client_sock <= 0) {
                _E("[CPU-BOOSTING] client socket should be larger than 0");
                goto remove_handler;
        }
 
-       if (cpu_boosting_enqueue_by_socket(client_sock) < 0) {
+       if (cpu_boosting_enqueue_by_socket(client_sock, &input) < 0 ||
+                       input == NULL) {
+               goto remove_handler;
+       }
+
+       if (input->client_input.pid.tid_count == 0) {
+               _E("[CPU-BOOSTING] The number of tids should be larger than 0");
+               cpu_boosting_destroy_request(input);
                goto remove_handler;
        }
 
+       cpu_boosting_handle_command(input);
+
        return G_SOURCE_CONTINUE;
 
 remove_handler:
+       if (client_sock > 0)
+               close(client_sock);
+
        return G_SOURCE_REMOVE;
 }
 
@@ -807,21 +806,23 @@ static bool cpu_boosting_connect_from_client(int fd, void *data)
        int new_sock = accept(master_sock, NULL, NULL);
        if (new_sock < 0) {
                _E("[CPU-BOOSTING] Failed to allocate a new socket for the client (%s)", strerror(errno));
-               goto continue_handler;
+               goto remove_handler;
        }
 
-       /* Add event handler to receive data from the client */
-       ret = add_fd_read_handler(new_sock, cpu_boosting_recv_from_client,
+       /* Add an event handler to receive data from the client */
+       ret = add_fd_read_handler(cpu_boosting_context, new_sock, cpu_boosting_recv_from_client,
                        NULL, NULL, NULL);
        if (ret < 0) {
                _E("[CPU-BOOSTING] Failed to add event handler of (sock = %d)", new_sock);
                close(new_sock);
        }
 
-continue_handler:
        return G_SOURCE_CONTINUE;
 
 remove_handler:
+       if (master_sock > 0)
+               close(master_sock);
+
        return G_SOURCE_REMOVE;
 }
 
@@ -831,8 +832,8 @@ static int cpu_boosting_init_server(void)
        static fd_handler_h handler;
        int sock = cpu_boosting_init_socket();
        if (sock > 0) {
-               ret = add_fd_read_handler(sock, cpu_boosting_connect_from_client,
-                               NULL, NULL, &handler);
+               ret = add_fd_read_handler(cpu_boosting_context, sock,
+                               cpu_boosting_connect_from_client, NULL, NULL, &handler);
                if (ret < 0) {
                        _E("[CPU-BOOSTING] Failed to add event handler of (sock = %d)", sock);
                        close(sock);
@@ -845,52 +846,51 @@ static int cpu_boosting_init_server(void)
        return RESOURCED_ERROR_NONE;
 }
 
-static int cpu_boosting_thread_activate(void)
+/* Cpu boosting thread's main code */
+static void *cpu_boosting_func(void *data)
 {
-       int ret;
+       /* Boost cpu boosting thread itself */
+       setpriority(PRIO_PROCESS, 0, CPU_MIN_NICE);
 
-       if (CPU_BOOSTING_WORKER_IS_ACTIVE)
-               return RESOURCED_ERROR_NONE;
+       cpu_boosting_context = g_main_context_new();
+       g_main_context_push_thread_default(cpu_boosting_context);
+       cpu_boosting_loop = g_main_loop_new(cpu_boosting_context, FALSE);
 
-       worker.queue = g_async_queue_new_full(cpu_boosting_input_destroy);
-       if (!worker.queue) {
-               _E("[CPU-BOOSTING] Failed to create request queue");
-               return RESOURCED_ERROR_FAIL;
+       /* For the socket-based client */
+       if (cpu_boosting_init_server() < 0) {
+               _E("[CPU-BOOSTING] Failed to initialize server environment");
+               goto thread_exit;
        }
+       else
+               _D("[CPU-BOOSTING] Success to initialize server environment");
 
-       /* g_hash_table is not thread safe, so use a lock between threads */
-       if (pthread_mutex_init(&mutex, NULL) != 0) {
-               _E("[CPU-BOOSTING] Failed to initialize mutex");
-               g_async_queue_unref(worker.queue);
-               return RESOURCED_ERROR_FAIL;
-       }
+       g_main_loop_run(cpu_boosting_loop);
 
-       ret = pthread_create(&worker.thread, NULL,
+thread_exit:
+       g_main_loop_unref(cpu_boosting_loop);
+       g_main_context_unref(cpu_boosting_context);
+       pthread_exit(NULL);
+}
+
+static int cpu_boosting_thread_activate(void)
+{
+       int ret = pthread_create(&cpu_boosting_thread, NULL,
                        cpu_boosting_func, NULL);
        if (ret == 0) {
-               pthread_detach(worker.thread);
+               pthread_detach(cpu_boosting_thread);
                ret = RESOURCED_ERROR_NONE;
        }
        else {
                _E("[CPU-BOOSTING] Failed to create cpu boosting thread");
-               g_async_queue_unref(worker.queue);
-               pthread_mutex_destroy(&mutex);
                ret = RESOURCED_ERROR_FAIL;
        }
 
        return ret;
 }
 
-/* Called by resourced main thread */
 static void cpu_boosting_thread_deactivate(void)
 {
-       if (!CPU_BOOSTING_WORKER_IS_ACTIVE)
-               return;
-
-       CPU_BOOSTING_WORKER_DEACTIVATE;
-       cpu_boosting_drain_queue();
-       g_async_queue_unref(worker.queue);
-       pthread_mutex_destroy(&mutex);
+       g_main_loop_quit(cpu_boosting_loop);
 }
 
 /* Called by resourced main thread */
@@ -907,14 +907,8 @@ static int cpu_boosting_init(void *data)
        tid_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free);
        g_assert(tid_table);
 
-       /* For the socket-based client */
-       if (cpu_boosting_init_server() < 0)
-               _E("[CPU-BOOSTING] Failed to initialize server environment");
-       else
-               _D("[CPU-BOOSTING] Success to initialize server environment");
-
        /* For the conf-based client */
-       register_notifier(RESOURCED_NOTIFIER_BOOSTING_RESOURCE, cpu_boosting_enqueue_by_conf);
+       register_notifier(RESOURCED_NOTIFIER_BOOSTING_RESOURCE, cpu_boosting_recv_from_conf);
 
        return RESOURCED_ERROR_NONE;
 }
@@ -925,7 +919,7 @@ static int cpu_boosting_finalize(void *data)
        cpu_boosting_thread_deactivate();
        g_hash_table_destroy(tid_table);
 
-       unregister_notifier(RESOURCED_NOTIFIER_BOOSTING_RESOURCE, cpu_boosting_enqueue_by_conf);
+       unregister_notifier(RESOURCED_NOTIFIER_BOOSTING_RESOURCE, cpu_boosting_recv_from_conf);
        return RESOURCED_ERROR_NONE;
 }
 
index cf344cc..c90cc78 100644 (file)
@@ -115,7 +115,7 @@ static int monitor_cpus()
                goto monitor_failed;
        }
 
-       if (add_fd_read_handler(ch.fd, udev_io_handler, ch.mon, NULL, &(ch.io_handler)) < 0) {
+       if (add_fd_read_handler(NULL, ch.fd, udev_io_handler, ch.mon, NULL, &(ch.io_handler)) < 0) {
                _E("cpu-hotplug: could not add fd read handler");
                ret = -1;
                goto monitor_failed;