static void load_stats_device_free(void) { hotplug_info("%s\n", __func__); if (load_stats_state == DISABLED) { load_stats_state = IDLE; load_stats_work_func(NULL); } }
static void load_stats_device_busy(void) { hotplug_info("%s\n", __func__); if (load_stats_state != DISABLED) { load_stats_state = DISABLED; cancel_delayed_work_sync(&load_stats_work); } }
static inline void show_status(const char* extra, cputime64_t on_time, int cpu) { if(on_time) hotplug_info("%s Mask=[%d.%d%d%d%d]|lp_on_time=%llu\n", extra, is_lp_cluster(), ((is_lp_cluster() == 1) ? 0 : cpu_online(0)), cpu_online(1), cpu_online(2), cpu_online(3), on_time); else if(cpu>0) hotplug_info("%s %d Mask=[%d.%d%d%d%d]\n", extra, cpu, is_lp_cluster(), ((is_lp_cluster() == 1) ? 0 : cpu_online(0)), cpu_online(1), cpu_online(2), cpu_online(3)); else hotplug_info("%s Mask=[%d.%d%d%d%d]\n", extra, is_lp_cluster(), ((is_lp_cluster() == 1) ? 0 : cpu_online(0)), cpu_online(1), cpu_online(2), cpu_online(3)); }
static int load_stats_boost_task(void *data) { unsigned int nr_cpu_online; int i; while (1) { set_current_state(TASK_INTERRUPTIBLE); schedule(); if (kthread_should_stop()) break; set_current_state(TASK_RUNNING); if (input_boost_running) continue; mutex_lock(&load_stats_work_lock); input_boost_running = true; /* do boost work */ nr_cpu_online = num_online_cpus(); if (nr_cpu_online < input_boost_cpus){ for (i = nr_cpu_online; i < input_boost_cpus; i++){ load_stats_state = UP; hotplug_info("UP because of input boost\n"); __load_stats_work_func(); } } input_boost_end_time = ktime_to_ms(ktime_get()) + input_boost_duration; mutex_unlock(&load_stats_work_lock); } hotplug_info("%s: input_boost_thread stopped\n", __func__); return 0; }
static int load_stats_start(void) { int err; struct sched_param param = { .sched_priority = 1 }; err = load_stats_sysfs(); if (err) return err; load_stats_wq = alloc_workqueue("cpuquiet-load_stats", WQ_HIGHPRI, 0); if (!load_stats_wq) return -ENOMEM; INIT_DELAYED_WORK(&load_stats_work, load_stats_work_func); input_boost_task = kthread_create ( load_stats_boost_task, NULL, "cpuquiet_input_boost_task" ); if (IS_ERR(input_boost_task)) pr_err("%s: failed to create input boost task\n", __func__); else { sched_setscheduler_nocheck(input_boost_task, SCHED_RR, ¶m); get_task_struct(input_boost_task); input_boost_task_alive = true; hotplug_info("%s: input boost task created\n", __func__); } first_call = true; total_time = 0; last_time = 0; load_stats_state = IDLE; load_stats_work_func(NULL); return 0; } struct cpuquiet_governor load_stats_governor = { .name = "load_stats", .start = load_stats_start, .device_free_notification = load_stats_device_free, .device_busy_notification = load_stats_device_busy, .stop = load_stats_stop, .touch_event_notification = load_stats_touch_event, .owner = THIS_MODULE, }; static int __init init_load_stats(void) { return cpuquiet_register_governor(&load_stats_governor); } static void __exit exit_load_stats(void) { cpuquiet_unregister_governor(&load_stats_governor); } MODULE_LICENSE("GPL"); module_init(init_load_stats); module_exit(exit_load_stats);
static void update_load_stats_state(void) { unsigned int load; unsigned int nr_cpu_online; unsigned int max_cpus = cpq_max_cpus(); unsigned int min_cpus = cpq_min_cpus(); u64 current_time; u64 this_time = 0; int index; if (load_stats_state == DISABLED) return; current_time = ktime_to_ms(ktime_get()); if (current_time <= start_delay){ load_stats_state = IDLE; return; } if (first_call) { first_call = false; } else { this_time = current_time - last_time; } total_time += this_time; load = report_load(); nr_cpu_online = num_online_cpus(); load_stats_state = IDLE; if (nr_cpu_online) { index = (nr_cpu_online - 1) * 2; if ((nr_cpu_online < CONFIG_NR_CPUS) && (load >= load_threshold[index])) { if (total_time >= twts_threshold[index]) { if (nr_cpu_online < max_cpus){ hotplug_info("UP load=%d total_time=%lld load_threshold[index]=%d twts_threshold[index]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", load, total_time, load_threshold[index], twts_threshold[index], nr_cpu_online, min_cpus, max_cpus); load_stats_state = UP; } } } else if (load <= load_threshold[index+1]) { if (total_time >= twts_threshold[index+1] ) { if ((nr_cpu_online > 1) && (nr_cpu_online > min_cpus)){ hotplug_info("DOWN load=%d total_time=%lld load_threshold[index+1]=%d twts_threshold[index+1]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", load, total_time, load_threshold[index+1], twts_threshold[index+1], nr_cpu_online, min_cpus, max_cpus); load_stats_state = DOWN; } } } else { load_stats_state = IDLE; total_time = 0; } } else { total_time = 0; } if (input_boost_running && current_time > input_boost_end_time) input_boost_running = false; if (input_boost_running){ if (load_stats_state != UP){ load_stats_state = IDLE; hotplug_info("IDLE because of input boost\n"); } } if (load_stats_state != IDLE) total_time = 0; last_time = ktime_to_ms(ktime_get()); }