sched: ems: renewal global boost
authorPark Bumgyu <bumgyu.park@samsung.com>
Fri, 23 Mar 2018 05:07:09 +0000 (14:07 +0900)
committerChungwoo Park <cww.park@samsung.com>
Mon, 21 May 2018 08:35:29 +0000 (17:35 +0900)
Modify the structure of global boost to work with PCF. Accordingly,
the range of value is changed from 0~100 to 0/1.

Change-Id: I2a5d35cfeb69a9b9ca9d5e1d043f49ee4d3d4ff9
Signed-off-by: Park Bumgyu <bumgyu.park@samsung.com>
include/linux/ems.h
include/trace/events/ems.h
kernel/sched/ems/ehmp.c
kernel/sched/ems/ems.h
kernel/sched/ems/global_boost.c

index d019bbec826ace7d0d8df0443e1be6a51098b540..d35dba1f38f6515ebda1115d3af146a11733a9b3 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/plist.h>
 #include <linux/sched/idle.h>
+#include <linux/sched/topology.h>
 
 #ifdef CONFIG_SCHED_TUNE
 enum stune_group {
index e1831114520c2d9f24c087579d6136bbb252d6df..af380165f4501c2659e9762eac82120e24e4ce15 100644 (file)
@@ -69,6 +69,27 @@ TRACE_EVENT(ems_select_perf_cpu,
                  __entry->comm, __entry->pid, __entry->best_cpu, __entry->backup_cpu)
 );
 
+/*
+ * Tracepoint for global boost
+ */
+TRACE_EVENT(ems_global_boost,
+
+       TP_PROTO(char *name, int boost),
+
+       TP_ARGS(name, boost),
+
+       TP_STRUCT__entry(
+               __array(        char,   name,   64      )
+               __field(        int,    boost           )
+       ),
+
+       TP_fast_assign(
+               memcpy(__entry->name, name, 64);
+               __entry->boost          = boost;
+       ),
+
+       TP_printk("name=%s global_boost=%d", __entry->name, __entry->boost)
+);
 
 /*
  * Tracepoint for selection of boost cpu
index 52ad372016a6ea9d6c53c06062c10840fa41e41d..35068add52124de684fe4dbee3b373703980eeef 100644 (file)
@@ -15,7 +15,7 @@
 
 #include "../sched.h"
 #include "../tune.h"
-#include "./ems.h"
+#include "ems.h"
 
 /**********************************************************************
  * extern functions                                                   *
@@ -258,7 +258,6 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd)
                                (rq->cpu_capacity_orig * 100));
 }
 
-unsigned long global_boost(void);
 int exynos_need_active_balance(enum cpu_idle_type idle, struct sched_domain *sd,
                                        int src_cpu, int dst_cpu)
 {
@@ -278,7 +277,7 @@ int exynos_need_active_balance(enum cpu_idle_type idle, struct sched_domain *sd,
 
                /* This domain is top and dst_cpu is bigger than src_cpu*/
                if (!lb_sd_parent(sd) && src_cap < dst_cap)
-                       if (lbt_overutilized(src_cpu, level) || global_boost())
+                       if (lbt_overutilized(src_cpu, level) || global_boosted())
                                return 1;
        }
 
@@ -316,7 +315,7 @@ static int gb_qos_req_value(struct gb_qos_request *req)
        return req->node.prio;
 }
 
-void gb_qos_update_request(struct gb_qos_request *req, u32 new_value)
+void __weak gb_qos_update_request(struct gb_qos_request *req, u32 new_value)
 {
        unsigned long flags;
 
@@ -461,7 +460,7 @@ static int check_boost_trigger(struct task_struct *p, struct boost_trigger *bt)
        }
 #endif
 
-       gb = global_boost();
+       gb = global_boosted();
        if (gb) {
                bt->trigger = BT_GLOBAL_BOOST;
                bt->boost_val = gb;
index 227e97067a59c80ae06e593e530a605e7e089098..000d9219776eac2eb3f94ccec2d87a4867acbe3a 100644 (file)
@@ -20,6 +20,7 @@ extern struct kobject *ems_kobj;
 extern int ontime_task_wakeup(struct task_struct *p);
 extern int select_perf_cpu(struct task_struct *p);
 extern int global_boosting(struct task_struct *p);
+extern int global_boosted(void);
 extern bool lbt_bring_overutilize(int cpu, struct task_struct *p);
 
 #ifdef CONFIG_SCHED_TUNE
index e6eb4ce924b43f67cb85ea66ece2675a5c66c586..c6df8d28144ef7ad5bd5e558cf10a50ac399b8fc 100644 (file)
@@ -6,8 +6,123 @@
  */
 
 #include <linux/sched.h>
+#include <linux/kobject.h>
+#include <linux/ems.h>
+
+#include <trace/events/ems.h>
+
+#include "ems.h"
+
+/*
+ * Global boost manages each boosting request as a list so that it can support
+ * boosting at the device driver level as well as user level. The list management
+ * algorithm uses the priority-list same as pm_qos.
+ */
+static struct plist_head gb_list = PLIST_HEAD_INIT(gb_list);
+
+static int gb_qos_value(void)
+{
+       return plist_last(&gb_list)->prio;
+}
+
+static DEFINE_SPINLOCK(gb_lock);
+
+void gb_qos_update_request(struct gb_qos_request *req, u32 new_value)
+{
+       unsigned long flags;
+
+       /* ignore if the value does not change */
+       if (req->node.prio == new_value)
+               return;
+
+       spin_lock_irqsave(&gb_lock, flags);
+
+       /*
+        * If the request already added to the list updates the value, remove
+        * the request from the list and add it again.
+        */
+       if (req->active)
+               plist_del(&req->node, &gb_list);
+       else
+               req->active = 1;
+
+       plist_node_init(&req->node, new_value);
+       plist_add(&req->node, &gb_list);
+
+       trace_ems_global_boost(req->name, new_value);
+
+       spin_unlock_irqrestore(&gb_lock, flags);
+}
+
+/* user level request, it is only set via sysfs */
+static struct gb_qos_request gb_req_user =
+{
+       .name = "gb_req_user",
+};
+
+static ssize_t show_global_boost(struct kobject *kobj,
+               struct kobj_attribute *attr, char *buf)
+{
+       struct gb_qos_request *req;
+       int ret = 0;
+
+       /* show all requests as well as user level */
+       plist_for_each_entry(req, &gb_list, node)
+               ret += snprintf(buf + ret, 30, "%s : %d\n",
+                               req->name, req->node.prio);
+
+       return ret;
+}
+
+static ssize_t store_global_boost(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf,
+               size_t count)
+{
+       unsigned int input;
+
+       if (!sscanf(buf, "%d", &input))
+               return -EINVAL;
+
+       gb_qos_update_request(&gb_req_user, input);
+
+       return count;
+}
+
+static struct kobj_attribute global_boost_attr =
+__ATTR(global_boost, 0644, show_global_boost, store_global_boost);
+
+static int __init init_gb_sysfs(void)
+{
+       int ret;
+
+       ret = sysfs_create_file(ems_kobj, &global_boost_attr.attr);
+       if (ret)
+               pr_err("%s: faile to create sysfs file\n", __func__);
+
+       return 0;
+}
+late_initcall(init_gb_sysfs);
+
+/*
+ * Returns the biggest value in the global boost list. In the current policy,
+ * a value greater than 0 is unconditionally boosting. The size of the value
+ * is meaningless.
+ */
+int global_boosted(void)
+{
+       u64 now = ktime_to_us(ktime_get());
+
+       /* booting boost duration = 40s */
+       if (now < 40 * USEC_PER_SEC)
+               return 1;
+
+       return gb_qos_value() > 0;
+}
 
 int global_boosting(struct task_struct *p)
 {
-       return -1;
+       if (!global_boosted())
+               return -1;
+
+       return select_perf_cpu(p);
 }