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.
Showing the changes to include/linux (3 of 6 files). Show all
Unified · Split
| @@ -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 | |||
| 224 | static inline __attribute__((const)) | ||
| 225 | int __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 */ |
| @@ -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 | */ | ||
| 292 | enum uclamp_id { | ||
| 293 | UCLAMP_MIN = 0, | ||
| 294 | UCLAMP_MAX, | ||
| 295 | UCLAMP_CNT | ||
| 296 | }; | ||
| 297 | |||
| 286 | struct sched_info { | 298 | struct sched_info { |
| 287 | #ifdef CONFIG_SCHED_INFO | 299 | #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 10 | 326 | # 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 | |||
| 317 | struct load_weight { | 333 | struct 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 | */ | ||
| 594 | struct 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 | |||
| 565 | union rcu_special { | 600 | union rcu_special { |
| 566 | struct { | 601 | struct { |
| 567 | u8 blocked; | 602 | u8 blocked; |
| @@ -642,6 +677,10 @@ struct task_struct { · 74 unmodified lines | |||
| 642 | #endif | 677 | #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_NOTIFIERS | 684 | #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; |
| @@ -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 | */ |