History

sched/uclamp: Add CPU's clamp buckets refcounting

Utilization clamping allows to clamp the CPU's utilization within a [util_min, util_max] range, depending on the set of RUNNABLE tasks on that CPU. Each task references two "clamp buckets" defining its minimum and maximum (util_{min,max}) utilization "clamp values". A CPU's clamp bucket is active if there is at least one RUNNABLE tasks enqueued on that CPU and refcounting that bucket. When a task is {en,de}queued {on,from} a rq, the set of active clamp buckets on that CPU can change. If the set of active clamp buckets changes for a CPU a new "aggregated" clamp value is computed for that CPU. This is because each clamp bucket enforces a different utilization clamp value. Clamp values are always MAX aggregated for both util_min and util_max. This ensures that no task can affect the performance of other co-scheduled tasks which are more boosted (i.e. with higher util_min clamp) or less capped (i.e. with higher util_max clamp). A task has: task_struct::uclamp[clamp_id]::bucket_id to track the "bucket index" of the CPU's clamp bucket it refcounts while enqueued, for each clamp index (clamp_id). A runqueue has: rq::uclamp[clamp_id]::bucket[bucket_id].tasks to track how many RUNNABLE tasks on that CPU refcount each clamp bucket (bucket_id) of a clamp index (clamp_id). It also has a: rq::uclamp[clamp_id]::bucket[bucket_id].value to track the clamp value of each clamp bucket (bucket_id) of a clamp index (clamp_id). The rq::uclamp::bucket[clamp_id][] array is scanned every time it's needed to find a new MAX aggregated clamp value for a clamp_id. This operation is required only when it's dequeued the last task of a clamp bucket tracking the current MAX aggregated clamp value. In this case, the CPU is either entering IDLE or going to schedule a less boosted or more clamped task. The expected number of different clamp values configured at build time is small enough to fit the full unordered array into a single cache line, for configurations of up to 7 buckets. Add to struct rq the basic data structures required to refcount the number of RUNNABLE tasks for each clamp bucket. Add also the max aggregation required to update the rq's clamp value at each enqueue/dequeue event. Use a simple linear mapping of clamp values into clamp buckets. Pre-compute and cache bucket_id to avoid integer divisions at enqueue/dequeue time.

Patrick Bellasi committed 7 years ago

Commit 69842cb1 parent a3df0676 files · +343 −6Browse files

Showing the changes to include/linux (3 of 6 files). Show all

Unified · Split

3 files
  1. include/linux/log2.h +34 −0
  2. include/linux/sched.h +39 −0
  3. include/linux/sched/topology.h +0 −6
include/linux/log2.h+34−0
@@ -220,4 +220,38 @@ int __order_base_2(unsigned long n) · 219 unmodified lines
220 ilog2((n) - 1) + 1) : \220 ilog2((n) - 1) + 1) : \
221 __order_base_2(n) \221 __order_base_2(n) \
222)222)
223
224static inline __attribute__((const))
225int __bits_per(unsigned long n)
226{
227 if (n < 2)
228 return 1;
229 if (is_power_of_2(n))
230 return order_base_2(n) + 1;
231 return order_base_2(n);
232}
233
234/**
235 * bits_per - calculate the number of bits required for the argument
236 * @n: parameter
237 *
238 * This is constant-capable and can be used for compile time
239 * initializations, e.g bitfields.
240 *
241 * The first few values calculated by this routine:
242 * bf(0) = 1
243 * bf(1) = 1
244 * bf(2) = 2
245 * bf(3) = 2
246 * bf(4) = 3
247 * ... and so on.
248 */
249#define bits_per(n) \
250( \
251 __builtin_constant_p(n) ? ( \
252 ((n) == 0 || (n) == 1) \
253 ? 1 : ilog2(n) + 1 \
254 ) : \
255 __bits_per(n) \
256)
223#endif /* _LINUX_LOG2_H */257#endif /* _LINUX_LOG2_H */
include/linux/sched.h+39−0
@@ -283,6 +283,18 @@ struct vtime { · 282 unmodified lines
283 u64 gtime;283 u64 gtime;
284};284};
285 285
286/*
287 * Utilization clamp constraints.
288 * @UCLAMP_MIN: Minimum utilization
289 * @UCLAMP_MAX: Maximum utilization
290 * @UCLAMP_CNT: Utilization clamp constraints count
291 */
292enum uclamp_id {
293 UCLAMP_MIN = 0,
294 UCLAMP_MAX,
295 UCLAMP_CNT
296};
297
286struct sched_info {298struct sched_info {
287#ifdef CONFIG_SCHED_INFO299#ifdef CONFIG_SCHED_INFO
288 /* Cumulative counters: */300 /* Cumulative counters: */
@@ -314,6 +326,10 @@ struct sched_info { · 25 unmodified lines
314# define SCHED_FIXEDPOINT_SHIFT 10326# define SCHED_FIXEDPOINT_SHIFT 10
315# define SCHED_FIXEDPOINT_SCALE (1L << SCHED_FIXEDPOINT_SHIFT)327# define SCHED_FIXEDPOINT_SCALE (1L << SCHED_FIXEDPOINT_SHIFT)
316 328
329/* Increase resolution of cpu_capacity calculations */
330# define SCHED_CAPACITY_SHIFT SCHED_FIXEDPOINT_SHIFT
331# define SCHED_CAPACITY_SCALE (1L << SCHED_CAPACITY_SHIFT)
332
317struct load_weight {333struct load_weight {
318 unsigned long weight;334 unsigned long weight;
319 u32 inv_weight;335 u32 inv_weight;
@@ -562,6 +578,25 @@ struct sched_dl_entity { · 242 unmodified lines
562 struct hrtimer inactive_timer;578 struct hrtimer inactive_timer;
563};579};
564 580
581#ifdef CONFIG_UCLAMP_TASK
582/* Number of utilization clamp buckets (shorter alias) */
583#define UCLAMP_BUCKETS CONFIG_UCLAMP_BUCKETS_COUNT
584
585/*
586 * Utilization clamp for a scheduling entity
587 * @value: clamp value "assigned" to a se
588 * @bucket_id: bucket index corresponding to the "assigned" value
589 *
590 * The bucket_id is the index of the clamp bucket matching the clamp value
591 * which is pre-computed and stored to avoid expensive integer divisions from
592 * the fast path.
593 */
594struct uclamp_se {
595 unsigned int value : bits_per(SCHED_CAPACITY_SCALE);
596 unsigned int bucket_id : bits_per(UCLAMP_BUCKETS);
597};
598#endif /* CONFIG_UCLAMP_TASK */
599
565union rcu_special {600union rcu_special {
566 struct {601 struct {
567 u8 blocked;602 u8 blocked;
@@ -642,6 +677,10 @@ struct task_struct { · 74 unmodified lines
642#endif677#endif
643 struct sched_dl_entity dl;678 struct sched_dl_entity dl;
644 679
680#ifdef CONFIG_UCLAMP_TASK
681 struct uclamp_se uclamp[UCLAMP_CNT];
682#endif
683
645#ifdef CONFIG_PREEMPT_NOTIFIERS684#ifdef CONFIG_PREEMPT_NOTIFIERS
646 /* List of struct preempt_notifier: */685 /* List of struct preempt_notifier: */
647 struct hlist_head preempt_notifiers;686 struct hlist_head preempt_notifiers;
include/linux/sched/topology.h+0−6
@@ -6,12 +6,6 @@ · 5 unmodified lines
6 6
7#include <linux/sched/idle.h>7#include <linux/sched/idle.h>
8 8
9/*
10 * Increase resolution of cpu_capacity calculations
11 */
12#define SCHED_CAPACITY_SHIFT SCHED_FIXEDPOINT_SHIFT
13#define SCHED_CAPACITY_SCALE (1L << SCHED_CAPACITY_SHIFT)
14
15/*9/*
16 * sched-domains (multiprocessor balancing) declarations:10 * sched-domains (multiprocessor balancing) declarations:
17 */11 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t