* [peterz-queue:sched/hackery 6/7] kernel/sched/fair.c:13490:4: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held
@ 2026-08-23 12:29 kernel test robot
0 siblings, 0 replies; only message in thread
From: kernel test robot @ 2026-08-23 12:29 UTC (permalink / raw)
To: Peter Zijlstra; +Cc: llvm, oe-kbuild-all
tree: https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git sched/hackery
head: 312c23a8d476a8f31cad58181b12950e9662a45c
commit: 65c5833b169f85988d1f1f48726c3554a92c7884 [6/7] sched/fair: Push sched_balance_newidle() unlock down
config: arm-randconfig-004-20260822 (https://download.01.org/0day-ci/archive/20260822/202608222234.4uKB0FCs-lkp@intel.com/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 935bfc708590c60147a79c7df145bb6e68b1d388)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260822/202608222234.4uKB0FCs-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608222234.4uKB0FCs-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> kernel/sched/fair.c:13490:4: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held [-Wthread-safety-analysis]
13490 | raw_spin_rq_unlock(this_rq);
| ^
kernel/sched/fair.c:13624:3: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held [-Wthread-safety-analysis]
13624 | raw_spin_rq_unlock(this_rq);
| ^
>> kernel/sched/fair.c:13725:9: warning: raw_spinlock 'rq_lockp(this_rq)' is not held on every path through here [-Wthread-safety-analysis]
13725 | return ld_moved;
| ^
kernel/sched/fair.c:13723:3: note: raw_spinlock acquired here
13723 | raw_spin_rq_lock(this_rq);
| ^
3 warnings generated.
vim +13490 kernel/sched/fair.c
13411
13412 /*
13413 * Check this_cpu to ensure it is balanced within domain. Attempt to move
13414 * tasks if there is an imbalance.
13415 */
13416 static int sched_balance_rq(int this_cpu, struct rq *this_rq,
13417 struct sched_domain *sd, enum cpu_idle_type idle,
13418 int *continue_balancing)
13419 {
13420 bool lock_rq = false, unlock_rq = idle == CPU_NEWLY_IDLE;
13421 int ld_moved, cur_ld_moved, active_balance = 0;
13422 struct sched_domain *sd_parent = sd->parent;
13423 struct sched_group *group;
13424 struct rq *busiest;
13425 struct rq_flags rf;
13426 struct cpumask *cpus = this_cpu_cpumask_var_ptr(load_balance_mask);
13427 struct lb_env env = {
13428 .sd = sd,
13429 .dst_cpu = this_cpu,
13430 .dst_rq = this_rq,
13431 .dst_grpmask = group_balance_mask(sd->groups),
13432 .idle = idle,
13433 .loop_break = SCHED_NR_MIGRATE_BREAK,
13434 .cpus = cpus,
13435 .fbq_type = all,
13436 .tasks = LIST_HEAD_INIT(env.tasks),
13437 };
13438 bool need_unlock = false;
13439
13440 cpumask_and(cpus, sched_domain_span(sd), cpu_active_mask);
13441
13442 schedstat_inc(sd->lb_count[idle]);
13443
13444 redo:
13445 if (!should_we_balance(&env)) {
13446 *continue_balancing = 0;
13447 goto out_balanced;
13448 }
13449
13450 if (!need_unlock && (sd->flags & SD_SERIALIZE)) {
13451 int zero = 0;
13452 if (!atomic_try_cmpxchg_acquire(&sched_balance_running, &zero, 1))
13453 goto out_balanced;
13454
13455 need_unlock = true;
13456 }
13457
13458 group = sched_balance_find_src_group(&env);
13459 if (!group) {
13460 schedstat_inc(sd->lb_nobusyg[idle]);
13461 goto out_balanced;
13462 }
13463
13464 busiest = sched_balance_find_src_rq(&env, group);
13465 if (!busiest) {
13466 schedstat_inc(sd->lb_nobusyq[idle]);
13467 goto out_balanced;
13468 }
13469
13470 WARN_ON_ONCE(busiest == env.dst_rq);
13471
13472 update_lb_imbalance_stat(&env, sd, idle);
13473
13474 env.src_cpu = busiest->cpu;
13475 env.src_rq = busiest;
13476
13477 ld_moved = 0;
13478 /* Clear this flag as soon as we find a pullable task */
13479 env.flags |= LBF_ALL_PINNED;
13480 if (busiest->nr_running > 1) {
13481 /*
13482 * Attempt to move tasks. If sched_balance_find_src_group has found
13483 * an imbalance but busiest->nr_running <= 1, the group is
13484 * still unbalanced. ld_moved simply stays zero, so it is
13485 * correctly treated as an imbalance.
13486 */
13487 env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running);
13488
13489 if (unlock_rq) {
13490 raw_spin_rq_unlock(this_rq);
13491 unlock_rq = false;
13492 lock_rq = true;
13493 }
13494
13495 more_balance:
13496 rq_lock_irqsave(busiest, &rf);
13497 update_rq_clock(busiest);
13498
13499 /*
13500 * cur_ld_moved - load moved in current iteration
13501 * ld_moved - cumulative load moved across iterations
13502 */
13503 cur_ld_moved = detach_tasks(&env);
13504
13505 /*
13506 * We've detached some tasks from busiest_rq. Every
13507 * task is masked "TASK_ON_RQ_MIGRATING", so we can safely
13508 * unlock busiest->lock, and we are able to be sure
13509 * that nobody can manipulate the tasks in parallel.
13510 * See task_rq_lock() family for the details.
13511 */
13512
13513 rq_unlock(busiest, &rf);
13514
13515 if (cur_ld_moved) {
13516 attach_tasks(&env);
13517 ld_moved += cur_ld_moved;
13518 }
13519
13520 local_irq_restore(rf.flags);
13521
13522 if (env.flags & LBF_NEED_BREAK) {
13523 env.flags &= ~LBF_NEED_BREAK;
13524 goto more_balance;
13525 }
13526
13527 /*
13528 * Revisit (affine) tasks on src_cpu that couldn't be moved to
13529 * us and move them to an alternate dst_cpu in our sched_group
13530 * where they can run. The upper limit on how many times we
13531 * iterate on same src_cpu is dependent on number of CPUs in our
13532 * sched_group.
13533 *
13534 * This changes load balance semantics a bit on who can move
13535 * load to a given_cpu. In addition to the given_cpu itself
13536 * (or a ilb_cpu acting on its behalf where given_cpu is
13537 * nohz-idle), we now have balance_cpu in a position to move
13538 * load to given_cpu. In rare situations, this may cause
13539 * conflicts (balance_cpu and given_cpu/ilb_cpu deciding
13540 * _independently_ and at _same_ time to move some load to
13541 * given_cpu) causing excess load to be moved to given_cpu.
13542 * This however should not happen so much in practice and
13543 * moreover subsequent load balance cycles should correct the
13544 * excess load moved.
13545 */
13546 if ((env.flags & LBF_DST_PINNED) && env.imbalance > 0) {
13547
13548 /* Prevent to re-select dst_cpu via env's CPUs */
13549 __cpumask_clear_cpu(env.dst_cpu, env.cpus);
13550
13551 env.dst_rq = cpu_rq(env.new_dst_cpu);
13552 env.dst_cpu = env.new_dst_cpu;
13553 env.flags &= ~LBF_DST_PINNED;
13554 env.loop = 0;
13555 env.loop_break = SCHED_NR_MIGRATE_BREAK;
13556
13557 /*
13558 * Go back to "more_balance" rather than "redo" since we
13559 * need to continue with same src_cpu.
13560 */
13561 goto more_balance;
13562 }
13563
13564 /*
13565 * We failed to reach balance because of affinity.
13566 */
13567 if (sd_parent) {
13568 int *group_imbalance = &sd_parent->groups->sgc->imbalance;
13569
13570 if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0)
13571 *group_imbalance = 1;
13572 }
13573
13574 /* All tasks on this runqueue were pinned by CPU affinity */
13575 if (unlikely(env.flags & LBF_ALL_PINNED)) {
13576 __cpumask_clear_cpu(cpu_of(busiest), cpus);
13577 /*
13578 * Attempting to continue load balancing at the current
13579 * sched_domain level only makes sense if there are
13580 * active CPUs remaining as possible busiest CPUs to
13581 * pull load from which are not contained within the
13582 * destination group that is receiving any migrated
13583 * load.
13584 */
13585 if (!cpumask_subset(cpus, env.dst_grpmask)) {
13586 env.loop = 0;
13587 env.loop_break = SCHED_NR_MIGRATE_BREAK;
13588 goto redo;
13589 }
13590 goto out_all_pinned;
13591 }
13592 }
13593
13594 if (ld_moved) {
13595 sd->nr_balance_failed = 0;
13596 goto out_unbalanced;
13597 }
13598
13599 schedstat_inc(sd->lb_failed[idle]);
13600 /*
13601 * Increment the failure counter only on periodic balance.
13602 * We do not want newidle balance, which can be very
13603 * frequent, pollute the failure counter causing
13604 * excessive cache_hot migrations and active balances.
13605 *
13606 * Similarly for migration_misfit which is not related to
13607 * load/util migration, don't pollute nr_balance_failed.
13608 *
13609 * The same for cache aware scheduling's allowance for
13610 * load imbalance. If regular load balance does not
13611 * migrate task due to LLC locality, it is a expected
13612 * behavior and don't pollute nr_balance_failed.
13613 * See can_migrate_task().
13614 */
13615 if (idle != CPU_NEWLY_IDLE &&
13616 env.migration_type != migrate_misfit &&
13617 !(env.flags & LBF_LLC_PINNED))
13618 sd->nr_balance_failed++;
13619
13620 if (!need_active_balance(&env))
13621 goto out_unbalanced;
13622
13623 if (unlock_rq) {
13624 raw_spin_rq_unlock(this_rq);
13625 unlock_rq = false;
13626 lock_rq = true;
13627 }
13628
13629 scoped_guard (raw_spin_rq_lock_irqsave, busiest) {
13630 /*
13631 * Don't kick the active_load_balance_cpu_stop,
13632 * if the curr task on busiest CPU can't be
13633 * moved to this_cpu:
13634 */
13635 if (!cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr))
13636 goto out_one_pinned;
13637
13638 /* Record that we found at least one task that could run on this_cpu */
13639 env.flags &= ~LBF_ALL_PINNED;
13640
13641 /*
13642 * ->active_balance synchronizes accesses to
13643 * ->active_balance_work. Once set, it's cleared
13644 * only after active load balance is finished.
13645 */
13646 if (busiest->active_balance)
13647 goto out_unbalanced;
13648
13649 /*
13650 * @busiest dropped its rq_lock in the middle of
13651 * scheduling out its ->curr task (->on_rq := 0), no
13652 * need to forcefully punt it away with active balance.
13653 */
13654 if (!busiest->curr->on_rq)
13655 goto out_unbalanced;
13656
13657 busiest->active_balance = 1;
13658 busiest->push_cpu = this_cpu;
13659 active_balance = 1;
13660 preempt_disable();
13661 }
13662 if (active_balance) {
13663 stop_one_cpu_nowait(cpu_of(busiest),
13664 active_load_balance_cpu_stop, busiest,
13665 &busiest->active_balance_work);
13666 }
13667 preempt_enable();
13668
13669 out_unbalanced:
13670 /* We were unbalanced, so reset the balancing interval */
13671 sd->balance_interval = sd->min_interval;
13672 goto out;
13673
13674 out_balanced:
13675 /*
13676 * We reach balance although we may have faced some affinity
13677 * constraints. Clear the imbalance flag only if other tasks got
13678 * a chance to move and fix the imbalance.
13679 */
13680 if (sd_parent && !(env.flags & LBF_ALL_PINNED)) {
13681 int *group_imbalance = &sd_parent->groups->sgc->imbalance;
13682
13683 if (*group_imbalance)
13684 *group_imbalance = 0;
13685 }
13686
13687 out_all_pinned:
13688 /*
13689 * We reach balance because all tasks are pinned at this level so
13690 * we can't migrate them. Let the imbalance flag set so parent level
13691 * can try to migrate them.
13692 */
13693 schedstat_inc(sd->lb_balanced[idle]);
13694
13695 sd->nr_balance_failed = 0;
13696
13697 out_one_pinned:
13698 ld_moved = 0;
13699
13700 /*
13701 * sched_balance_newidle() disregards balance intervals, so we could
13702 * repeatedly reach this code, which would lead to balance_interval
13703 * skyrocketing in a short amount of time. Skip the balance_interval
13704 * increase logic to avoid that.
13705 *
13706 * Similarly misfit migration which is not necessarily an indication of
13707 * the system being busy and requires lb to backoff to let it settle
13708 * down.
13709 */
13710 if (env.idle == CPU_NEWLY_IDLE ||
13711 env.migration_type == migrate_misfit)
13712 goto out;
13713
13714 /* tune up the balancing interval */
13715 if ((env.flags & LBF_ALL_PINNED &&
13716 sd->balance_interval < MAX_PINNED_INTERVAL) ||
13717 sd->balance_interval < sd->max_interval)
13718 sd->balance_interval *= 2;
13719 out:
13720 if (need_unlock)
13721 atomic_set_release(&sched_balance_running, 0);
13722 if (lock_rq)
13723 raw_spin_rq_lock(this_rq);
13724
13725 return ld_moved;
13726 }
13727
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-23 12:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-23 12:29 [peterz-queue:sched/hackery 6/7] kernel/sched/fair.c:13490:4: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.