(_input)->client_input.flags = _flags; \
}
+#define CPU_BOOSTING_INFO_SET_TID (1 << 0)
+#define CPU_BOOSTING_INFO_SET_REF_CNT (1 << 1)
+#define CPU_BOOSTING_INFO_SET_CPU_BOOSTING_FLAGS (1 << 2)
+#define CPU_BOOSTING_INFO_SET_GSOURCE_ID (1 << 3)
+#define CPU_BOOSTING_INFO_SET_LEVEL (1 << 4)
+
static void cpu_boosting_handle_command(
struct syscommon_resourced_cpu_boosting_input *input);
+static int set_cpu_boosting_info(
+ uint32_t cpu_boosting_info_set_flag,
+ struct syscommon_resourced_cpu_boosting_info *cpu_boosting_info,
+ pid_t tid, int ref_cnt,
+ int cpu_boosting_flags, guint *timer_id,
+ cpu_boosting_level_e cpu_boosting_level)
+{
+ if (cpu_boosting_info == NULL) {
+ _E("Failed to set CPU boosting info structure due to null pointer");
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+
+ if (cpu_boosting_info_set_flag & CPU_BOOSTING_INFO_SET_TID)
+ cpu_boosting_info->tid = tid;
+
+ if (cpu_boosting_info_set_flag & CPU_BOOSTING_INFO_SET_REF_CNT)
+ cpu_boosting_info->ref_cnt = ref_cnt;
+
+ if (cpu_boosting_info_set_flag & CPU_BOOSTING_INFO_SET_CPU_BOOSTING_FLAGS)
+ cpu_boosting_info->cpu_boosting_flags = cpu_boosting_flags;
+
+ if (cpu_boosting_info_set_flag & CPU_BOOSTING_INFO_SET_GSOURCE_ID) {
+ if (timer_id)
+ cpu_boosting_info->gsource_id = *timer_id;
+ else
+ cpu_boosting_info->gsource_id = 0;
+ }
+
+ if (cpu_boosting_info_set_flag & CPU_BOOSTING_INFO_SET_LEVEL)
+ cpu_boosting_info->level = cpu_boosting_level;
+
+ return RESOURCED_ERROR_NONE;
+}
+
static void free_cpu_boosting_info(gpointer data)
{
struct syscommon_resourced_cpu_boosting_info *cpu_boosting_info =
(struct syscommon_resourced_cpu_boosting_info *)data;
+ uint32_t cpu_boosting_info_set_flag = 0;
assert(cpu_boosting_info);
- cpu_boosting_info->ref_cnt--;
+ cpu_boosting_info_set_flag = CPU_BOOSTING_INFO_SET_REF_CNT;
+ set_cpu_boosting_info(cpu_boosting_info_set_flag,
+ cpu_boosting_info, 0, cpu_boosting_info->ref_cnt - 1,
+ 0, NULL, CPU_BOOSTING_LEVEL_NONE);
+
if (cpu_boosting_info->ref_cnt == 0)
free(cpu_boosting_info);
}
return RESOURCED_ERROR_NONE;
}
+static bool is_valid_cpu_boosting_level(cpu_boosting_level_e cpu_boosting_level)
+{
+ switch (cpu_boosting_level) {
+ case CPU_BOOSTING_LEVEL_STRONG:
+ case CPU_BOOSTING_LEVEL_MEDIUM:
+ case CPU_BOOSTING_LEVEL_WEAK:
+ return true;
+ case CPU_BOOSTING_LEVEL_NONE:
+ default:
+ return false;
+ }
+}
+
static gboolean cpu_boosting_timeout(gpointer data)
{
int fail_cnt = 0;
|| cpu_boosting_info->gsource_id != *(input->gsource_id))
continue;
- switch (cpu_boosting_info->level) {
- case CPU_BOOSTING_LEVEL_STRONG:
- case CPU_BOOSTING_LEVEL_MEDIUM:
- case CPU_BOOSTING_LEVEL_WEAK:
- g_hash_table_remove(
- g_cpu_boosting_info_table[cpu_boosting_info->level],
- &tid_list[i]);
- break;
- case CPU_BOOSTING_LEVEL_NONE:
- default:
+ if (!is_valid_cpu_boosting_level(cpu_boosting_info->level)) {
_E("[CPU-BOOSTING] Unknown cpu boosting level (SIGABT)");
assert(0);
}
+ g_hash_table_remove(g_cpu_boosting_info_table[cpu_boosting_info->level],
+ &tid_list[i]);
+
if (sched_setattr(tid_list[i],
&cpu_boosting_attr[CPU_BOOSTING_LEVEL_NONE], 0) < 0) {
fail_cnt++;
cpu_boosting_level_e cpu_boosting_level)
{
struct syscommon_resourced_cpu_boosting_info *cpu_boosting_info = NULL;
+ uint32_t cpu_boosting_info_set_flag = 0;
- switch (cpu_boosting_level) {
- case CPU_BOOSTING_LEVEL_STRONG:
- case CPU_BOOSTING_LEVEL_MEDIUM:
- case CPU_BOOSTING_LEVEL_WEAK:
- break;
- case CPU_BOOSTING_LEVEL_NONE:
- default:
+ if (!is_valid_cpu_boosting_level(cpu_boosting_level)) {
_E("[CPU-BOOSTING] Cannot boosting unknown or none level");
return;
}
find_cpu_boosting_info_in_tables(&cpu_boosting_info, &tid);
+
+ cpu_boosting_info_set_flag =
+ CPU_BOOSTING_INFO_SET_TID | CPU_BOOSTING_INFO_SET_REF_CNT |
+ CPU_BOOSTING_INFO_SET_CPU_BOOSTING_FLAGS | CPU_BOOSTING_INFO_SET_GSOURCE_ID |
+ CPU_BOOSTING_INFO_SET_LEVEL;
+
+ /* Case1: No previous CPU boosting on the target thread */
if (cpu_boosting_info == NULL) {
cpu_boosting_info = (struct syscommon_resourced_cpu_boosting_info *)
calloc(1, sizeof (struct syscommon_resourced_cpu_boosting_info));
return;
}
- cpu_boosting_info->tid = tid;
- cpu_boosting_info->ref_cnt = 1;
+ set_cpu_boosting_info(cpu_boosting_info_set_flag, cpu_boosting_info,
+ tid, 1, cpu_boosting_flags, timer_id, cpu_boosting_level);
g_hash_table_insert(g_cpu_boosting_info_table[cpu_boosting_level],
&cpu_boosting_info->tid, cpu_boosting_info);
- } else if (cpu_boosting_info->level != cpu_boosting_level) {
+
+ return;
+ }
+
+ /* Case2: Previous CPU boosting on the target thread, but different CPU boosting level */
+ if (cpu_boosting_info->level != cpu_boosting_level) {
/**
* Do not free cpu_boosting_info in
* g_cpu_boosting_info_table[cpu_boosting_info->level].
* will be reused as a value in another table
* (g_cpu_boosting_info_table[cpu_boosting_level]
*/
- cpu_boosting_info->ref_cnt++;
- g_hash_table_remove(
- g_cpu_boosting_info_table[cpu_boosting_info->level],
+ set_cpu_boosting_info(cpu_boosting_info_set_flag, cpu_boosting_info,
+ tid, cpu_boosting_info->ref_cnt + 1, cpu_boosting_flags, timer_id, cpu_boosting_level);
+
+ g_hash_table_remove(g_cpu_boosting_info_table[cpu_boosting_info->level],
&cpu_boosting_info->tid);
g_hash_table_insert(g_cpu_boosting_info_table[cpu_boosting_level],
&cpu_boosting_info->tid, cpu_boosting_info);
- }
-
- cpu_boosting_info->level = cpu_boosting_level;
- /**
- * Register cpu_boosting_flags to handle cpu contention and
- * restore cpu boosting level after solving cpu contention.
- * For example, if resourced received CPU_BOOSTING_COMMAND_SET command
- * with CPU_BOOSTING_RESET_ON_FORK, then turn on
- * CPU_BOOSTING_RESET_ON_FORK flag
- * when decreasing and restoring cpu boosting level.
- */
- cpu_boosting_info->cpu_boosting_flags = cpu_boosting_flags;
+ return;
+ }
- if (timer_id)
- cpu_boosting_info->gsource_id = *timer_id;
- else
- cpu_boosting_info->gsource_id = 0;
+ /* Case3: Previous CPU boosting on the target thread with same CPU boosting level */
+ set_cpu_boosting_info(cpu_boosting_info_set_flag, cpu_boosting_info,
+ tid, cpu_boosting_info->ref_cnt, cpu_boosting_flags, timer_id, cpu_boosting_level);
}
-static void
-cpu_boosting_set(struct syscommon_resourced_cpu_boosting_input *input)
+static int update_cpu_sched_of_thread_list(int tid_count, int *tid_list,
+ cpu_boosting_flag_e cpu_boosting_flags, cpu_boosting_level_e cpu_boosting_level,
+ int *cpu_boosting_fail_cnt, int *cpu_boosting_success_cnt)
{
- guint id = 0;
+ struct sched_attr attr = cpu_boosting_attr[cpu_boosting_level];
int fail_cnt = 0;
int success_cnt = 0;
- struct sched_attr attr;
- int tid_count = input->client_input.pid.tid_count;
- int *tid_list = input->client_input.pid.tid;
- int timeout_msec = input->client_input.timeout_msec;
- cpu_boosting_level_e cpu_boosting_level = input->client_input.level;
- cpu_boosting_flag_e cpu_boosting_flags = input->client_input.flags;
- switch (cpu_boosting_level) {
- case CPU_BOOSTING_LEVEL_STRONG:
- case CPU_BOOSTING_LEVEL_MEDIUM:
- case CPU_BOOSTING_LEVEL_WEAK:
- break;
- case CPU_BOOSTING_LEVEL_NONE:
- return;
- default:
- _E("[CPU-BOOSTING] Unknown boosting level");
- return;
- }
-
- attr = cpu_boosting_attr[cpu_boosting_level];
if (cpu_boosting_flags & CPU_BOOSTING_RESET_ON_FORK) {
_I("[CPU-BOOSTING] Turn on SCHED_RESET_ON_FORK flag");
attr.sched_policy |= SCHED_RESET_ON_FORK;
fail_cnt++;
continue;
}
+
success_cnt++;
}
+ *cpu_boosting_fail_cnt = fail_cnt;
+ *cpu_boosting_success_cnt = success_cnt;
+
+ return RESOURCED_ERROR_NONE;
+}
+
+static void
+cpu_boosting_set(struct syscommon_resourced_cpu_boosting_input *input)
+{
+ guint id = 0;
+ int fail_cnt = 0;
+ int success_cnt = 0;
+ int tid_count = input->client_input.pid.tid_count;
+ int *tid_list = input->client_input.pid.tid;
+ int timeout_msec = input->client_input.timeout_msec;
+ cpu_boosting_level_e cpu_boosting_level = input->client_input.level;
+ cpu_boosting_flag_e cpu_boosting_flags = input->client_input.flags;
+
+ if (!is_valid_cpu_boosting_level(cpu_boosting_level)) {
+ _E("[CPU-BOOSTING] Unknown boosting level");
+ return;
+ }
+
+ update_cpu_sched_of_thread_list(tid_count, tid_list,
+ cpu_boosting_flags, cpu_boosting_level,
+ &fail_cnt, &success_cnt);
+
if (fail_cnt > 0)
_W("[CPU-BOOSTING] Boosting success ratio = %d/%d", success_cnt, fail_cnt + success_cnt);