[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 <[email protected]>
| Newsgroups | dev.linux.lists.oe-kbuild-all,dev.linux.lists.llvm |
|---|---|
| Message-ID | <[email protected]> |
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/[email protected]/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/[email protected]/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 <[email protected]> | Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ 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