dl_add_task_root_domain() is called during sched domain rebuild: rebuild_sched_domains_locked() partition_and_rebuild_sched_domains() rebuild_root_domains() for all top_cpuset descendants: update_tasks_root_domain() for all tasks of cpuset: dl_add_task_root_domain() Change it so that only the task pi lock is taken to check if the task has a SCHED_DEADLINE (DL) policy. In case that p is a DL task take the rq lock as well to be able to safely de-reference root domain's DL bandwidth structure. Most of the tasks will have another policy (namely SCHED_NORMAL) and can now bail without taking the rq lock. One thing to note here: Even in case that there aren't any DL user tasks, a slow frequency switching system with cpufreq gov schedutil has a DL task (sugov) per frequency domain running which participates in DL bandwidth management.
Unified · Split
| @@ -2388,9 +2388,13 @@ void dl_add_task_root_domain(struct task_struct *p) · 2387 unmodified lines | ||
| 2388 | 2388 | struct rq *rq; |
| 2389 | 2389 | struct dl_bw *dl_b; |
| 2390 | 2390 | |
| 2391 | − rq = task_rq_lock(p, &rf); | |
| 2392 | − if (!dl_task(p)) | |
| 2393 | − goto unlock; | |
| 2391 | + raw_spin_lock_irqsave(&p->pi_lock, rf.flags); | |
| 2392 | + if (!dl_task(p)) { | |
| 2393 | + raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags); | |
| 2394 | + return; | |
| 2395 | + } | |
| 2396 | + | |
| 2397 | + rq = __task_rq_lock(p, &rf); | |
| 2394 | 2398 | |
| 2395 | 2399 | dl_b = &rq->rd->dl_bw; |
| 2396 | 2400 | raw_spin_lock(&dl_b->lock); |
| @@ -2399,7 +2403,6 @@ void dl_add_task_root_domain(struct task_struct *p) · 2 unmodified lines | ||
| 2399 | 2403 | |
| 2400 | 2404 | raw_spin_unlock(&dl_b->lock); |
| 2401 | 2405 | |
| 2402 | −unlock: | |
| 2403 | 2406 | task_rq_unlock(rq, p, &rf); |
| 2404 | 2407 | } |
| 2405 | 2408 | |