[PATCH v3 07/12] sched/fair: Generalize the load/util averages resolution definition
From: Yuyang Du
Date: Tue May 03 2016  23:46:30 EST
Integer metric needs fixed point arithmetic. In sched/fair, a few
metrics, including weight, load, load_avg, util_avg, freq, and capacity,
may have different fixed point ranges.
In order to avoid errors relating to the fixed point range of these
metrics, we define a basic fixed point range, and then formalize all
metrics to base on the basic range.
The basic range is 1024. Further, one can recursively apply this basic
range to have larger range.
Pointed out by Ben Segall, weight (visible to user, e.g., NICE0 has
1024) and load (e.g., NICE_0_LOAD) have independent ranges, but they
must be well calibrated.
Signedoffby: Yuyang Du <yuyang.du@xxxxxxxxx>

include/linux/sched.h  16 +++++++++++++
kernel/sched/fair.c  4 
kernel/sched/sched.h  15 ++++++++++
3 files changed, 23 insertions(+), 12 deletions()
diff git a/include/linux/sched.h b/include/linux/sched.h
index ad9454d..33e7929 100644
 a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ 937,9 +937,19 @@ enum cpu_idle_type {
};
/*
+ * Integer metrics need fixed point arithmetic, e.g., sched/fair
+ * has a few: load, load_avg, util_avg, freq, and capacity.
+ *
+ * We define a basic fixed point arithmetic range, and then formalize
+ * all these metrics based on that basic range.
+ */
+# define SCHED_FIXEDPOINT_SHIFT 10
+# define SCHED_FIXEDPOINT_SCALE (1L << SCHED_FIXEDPOINT_SHIFT)
+
+/*
* Increase resolution of cpu_capacity calculations
*/
#define SCHED_CAPACITY_SHIFT 10
+#define SCHED_CAPACITY_SHIFT SCHED_FIXEDPOINT_SHIFT
#define SCHED_CAPACITY_SCALE (1L << SCHED_CAPACITY_SHIFT)
/*
@@ 1205,8 +1215,8 @@ struct load_weight {
* 1) load_avg factors frequency scaling into the amount of time that a
* sched_entity is runnable on a rq into its weight. For cfs_rq, it is the
* aggregated such weights of all runnable and blocked sched_entities.
 * 2) util_avg factors frequency and cpu scaling into the amount of time
 * that a sched_entity is running on a CPU, in the range [0..SCHED_LOAD_SCALE].
+ * 2) util_avg factors frequency and cpu capacity scaling into the amount of time
+ * that a sched_entity is running on a CPU, in the range [0..SCHED_CAPACITY_SCALE].
* For cfs_rq, it is the aggregated such times of all runnable and
* blocked sched_entities.
* The 64 bit load_sum can:
diff git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 495e5f0..1a61137 100644
 a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ 2678,10 +2678,6 @@ __accumulate_sum(u32 periods, u32 period_contrib, u32 remainder)
return contrib + remainder;
}
#if (SCHED_LOAD_SHIFT  SCHED_LOAD_RESOLUTION) != 10  SCHED_CAPACITY_SHIFT != 10
#error "load tracking assumes 2^10 as unit"
#endif

#define cap_scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT)
static __always_inline u32 accumulate_sum(u64 delta, struct sched_avg *sa,
diff git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 69da6fc..996a137 100644
 a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ 54,18 +54,23 @@ static inline void cpu_load_update_active(struct rq *this_rq) { }
* increased costs.
*/
#if 0 /* BITS_PER_LONG > 32  currently broken: it increases power usage under light load */
# define SCHED_LOAD_RESOLUTION 10
# define scale_load(w) ((w) << SCHED_LOAD_RESOLUTION)
# define scale_load_down(w) ((w) >> SCHED_LOAD_RESOLUTION)
+# define SCHED_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
+# define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
+# define scale_load_down(w) ((w) >> SCHED_FIXEDPOINT_SHIFT)
#else
# define SCHED_LOAD_RESOLUTION 0
+# define SCHED_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
# define scale_load(w) (w)
# define scale_load_down(w) (w)
#endif
#define SCHED_LOAD_SHIFT (10 + SCHED_LOAD_RESOLUTION)
#define SCHED_LOAD_SCALE (1L << SCHED_LOAD_SHIFT)
+/*
+ * NICE_0's weight (visible to user) and its load (invisible to user) have
+ * independent ranges, but they should be well calibrated. We use scale_load()
+ * and scale_load_down(w) to convert between them, the following must be true:
+ * scale_load(sched_prio_to_weight[20]) == NICE_0_LOAD
+ */
#define NICE_0_LOAD SCHED_LOAD_SCALE
#define NICE_0_SHIFT SCHED_LOAD_SHIFT

1.7.9.5