Latency Tracking

The kernel has a built-in notion of what it considers a good scheduling latency, that is, the interval during which every runnable task should run at least once.29 It is given in sysctl_sched_latency, which can be controlled via /proc/sys/kernel/sched_latency_ns and defaults to, respectively, 20,000,000 ns (nanoseconds) and 20 ms (milliseconds). A second control parameter, sched_nr_latency, controls the number of active processes that are at most handled in one latency period. If the number of active processes grows larger than this bound, the latency period is extended linearly. sched_nr_latency can be indirectly controlled via sysctl_sched_min_granularity, which can be set via /proc/sys/kernel/ sched_min_granularity_ns. The default value is 4,000,000 ns, that is, 4 ms, and sched_nr_latency is

28This is slightly different for short sleepers, but I consider this situation when I discuss the exact mechanism.

29Caution: This has nothing to do with time slices, which were used by the old scheduler!

computed as sysctl_sched_latency/sysctl_sched_min_granularity each time one of the values is changed.

_sched_period determines the length of the latency period, which is usually just sysctl_sched_latency, but is extended linearly if more processes are running. In this case, the period length is nr_running sysctl_sched_latency x -.

sched_nr_latency

Distribution of the time among active processes in one latency period is performed by considering the relative weights of the respective tasks. The slice length for a given process as represented by a schedulable entity is computed as follows:

kernel/sched_fair.c static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se) {

u64 slice = _sched_period(cfs_rq->nr_running);

slice *= se->load.weight; do_div(slice, cfs_rq->load.weight);

return slice;

Recall that the run queue load weight accumulates the load weights of all active processes on the queue. The resulting time slice is given in real time, but the kernel sometimes also needs to know the equivalent in virtual time.

kernel/sched_fair.c static u64 _sched_vslice(unsigned long rq_weight, unsigned long nr_running)

u64 vslice = _sched_period(nr_running);

return vslice;

static u64 sched_vslice(struct cfs_rq *cfs_rq) {

return _sched_vslice(cfs_rq->load.weight, cfs_rq->nr_running);

Recall that a real-time interval time for a process with a given weight has the length

NICE_0_LOAD

time x -, weight and this is also used to transfer the latency interval portion.

Now we have everything in place to discuss the various methods that must be implemented by CFS to interact with the global scheduler.

Was this article helpful?

0 0

Post a comment