The SCHED_DEADLINE scheduling class provides an advanced and formal model to define tasks requirements that can translate into proper decisions for both task placements and frequencies selections. Other classes have a more simplified model based on the POSIX concept of priorities. Such a simple priority based model however does not allow to exploit most advanced features of the Linux scheduler like, for example, driving frequencies selection via the schedutil cpufreq governor. However, also for non SCHED_DEADLINE tasks, it's still interesting to define tasks properties to support scheduler decisions. Utilization clamping exposes to user-space a new set of per-task attributes the scheduler can use as hints about the expected/required utilization for a task. This allows to implement a "proactive" per-task frequency control policy, a more advanced policy than the current one based just on "passive" measured task utilization. For example, it's possible to boost interactive tasks (e.g. to get better performance) or cap background tasks (e.g. to be more energy/thermal efficient). Introduce a new API to set utilization clamping values for a specified task by extending sched_setattr(), a syscall which already allows to define task specific properties for different scheduling classes. A new pair of attributes allows to specify a minimum and maximum utilization the scheduler can consider for a task. Do that by validating the required clamp values before and then applying the required changes using _the_ same pattern already in use for __setscheduler(). This ensures that the task is re-enqueued with the new clamp values.
Showing the changes to include/linux (1 of 4 files). Show all
Unified · Split
| @@ -587,6 +587,7 @@ struct sched_dl_entity { · 586 unmodified lines | ||
| 587 | 587 | * @value: clamp value "assigned" to a se |
| 588 | 588 | * @bucket_id: bucket index corresponding to the "assigned" value |
| 589 | 589 | * @active: the se is currently refcounted in a rq's bucket |
| 590 | + * @user_defined: the requested clamp value comes from user-space | |
| 590 | 591 | * |
| 591 | 592 | * The bucket_id is the index of the clamp bucket matching the clamp value |
| 592 | 593 | * which is pre-computed and stored to avoid expensive integer divisions from |
| @@ -596,11 +597,19 @@ struct sched_dl_entity { · 3 unmodified lines | ||
| 596 | 597 | * which can be different from the clamp value "requested" from user-space. |
| 597 | 598 | * This allows to know a task is refcounted in the rq's bucket corresponding |
| 598 | 599 | * to the "effective" bucket_id. |
| 600 | + * | |
| 601 | + * The user_defined bit is set whenever a task has got a task-specific clamp | |
| 602 | + * value requested from userspace, i.e. the system defaults apply to this task | |
| 603 | + * just as a restriction. This allows to relax default clamps when a less | |
| 604 | + * restrictive task-specific value has been requested, thus allowing to | |
| 605 | + * implement a "nice" semantic. For example, a task running with a 20% | |
| 606 | + * default boost can still drop its own boosting to 0%. | |
| 599 | 607 | */ |
| 600 | 608 | struct uclamp_se { |
| 601 | 609 | unsigned int value : bits_per(SCHED_CAPACITY_SCALE); |
| 602 | 610 | unsigned int bucket_id : bits_per(UCLAMP_BUCKETS); |
| 603 | 611 | unsigned int active : 1; |
| 612 | + unsigned int user_defined : 1; | |
| 604 | 613 | }; |
| 605 | 614 | #endif /* CONFIG_UCLAMP_TASK */ |
| 606 | 615 | |