From: Peter Zijlstra <peterz@infradead.org>
To: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
linux-kernel@vger.kernel.org, David Vernet <void@manifault.com>,
Ingo Molnar <mingo@redhat.com>,
Alexei Starovoitov <ast@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>
Subject: Re: [GIT PULL] sched_ext: Initial pull request for v6.11
Date: Fri, 2 Aug 2024 14:20:34 +0200 [thread overview]
Message-ID: <20240802122034.GZ12673@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20240723163358.GM26750@noisy.programming.kicks-ass.net>
A few more..
> +static bool scx_switching_all;
> +DEFINE_STATIC_KEY_FALSE(__scx_switched_all);
> + WRITE_ONCE(scx_switching_all, !(ops->flags & SCX_OPS_SWITCH_PARTIAL));
> + if (!(ops->flags & SCX_OPS_SWITCH_PARTIAL))
> + static_branch_enable(&__scx_switched_all);
> + static_branch_disable(&__scx_switched_all);
> + WRITE_ONCE(scx_switching_all, false);
FYI the static_key contains a variable you can read if you want, see
static_key_count()/static_key_enabled(). No need to mirror the state.
> +static struct task_struct *
> +scx_task_iter_next_locked(struct scx_task_iter *iter, bool include_dead)
> +{
> + struct task_struct *p;
> +retry:
> + scx_task_iter_rq_unlock(iter);
> +
> + while ((p = scx_task_iter_next(iter))) {
> + /*
> + * is_idle_task() tests %PF_IDLE which may not be set for CPUs
> + * which haven't yet been onlined. Test sched_class directly.
> + */
> + if (p->sched_class != &idle_sched_class)
> + break;
This isn't quite the same; please look at play_idle_precise() in
drivers/powercap/idle_inject.c.
That is, there are PF_IDLE tasks that are not idle_sched_class.
> + }
> + if (!p)
> + return NULL;
> +
> + iter->rq = task_rq_lock(p, &iter->rf);
> + iter->locked = p;
> +
> + /*
> + * If we see %TASK_DEAD, @p already disabled preemption, is about to do
> + * the final __schedule(), won't ever need to be scheduled again and can
> + * thus be safely ignored. If we don't see %TASK_DEAD, @p can't enter
> + * the final __schedle() while we're locking its rq and thus will stay
> + * alive until the rq is unlocked.
> + */
> + if (!include_dead && READ_ONCE(p->__state) == TASK_DEAD)
> + goto retry;
> +
> + return p;
> +}
> +static void update_curr_scx(struct rq *rq)
> +{
> + struct task_struct *curr = rq->curr;
> + u64 now = rq_clock_task(rq);
> + u64 delta_exec;
> +
> + if (time_before_eq64(now, curr->se.exec_start))
> + return;
> +
> + delta_exec = now - curr->se.exec_start;
> + curr->se.exec_start = now;
> + curr->se.sum_exec_runtime += delta_exec;
> + account_group_exec_runtime(curr, delta_exec);
> + cgroup_account_cputime(curr, delta_exec);
Could you please use update_curr_common() here?
This helps keep the accounting in one place. For instance, see this
patch:
https://lkml.kernel.org/r/20240727105031.053611186@infradead.org
That adds a sum_exec_runtime variant that is scaled by DVFS and
capacity.
You should be able to make the function:
u64 delta_exec = update_curr_common(rq);
> + struct task_struct *curr = rq->curr;
> +
> + if (curr->scx.slice != SCX_SLICE_INF) {
> + curr->scx.slice -= min(curr->scx.slice, delta_exec);
> + if (!curr->scx.slice)
> + touch_core_sched(rq, curr);
> + }
> +}
> +static bool move_task_to_local_dsq(struct rq *rq, struct task_struct *p,
> + u64 enq_flags)
> +{
> + struct rq *task_rq;
> +
> + lockdep_assert_rq_held(rq);
> +
> + /*
> + * If dequeue got to @p while we were trying to lock both rq's, it'd
> + * have cleared @p->scx.holding_cpu to -1. While other cpus may have
> + * updated it to different values afterwards, as this operation can't be
> + * preempted or recurse, @p->scx.holding_cpu can never become
> + * raw_smp_processor_id() again before we're done. Thus, we can tell
> + * whether we lost to dequeue by testing whether @p->scx.holding_cpu is
> + * still raw_smp_processor_id().
> + *
> + * See dispatch_dequeue() for the counterpart.
> + */
> + if (unlikely(p->scx.holding_cpu != raw_smp_processor_id()))
> + return false;
> +
> + /* @p->rq couldn't have changed if we're still the holding cpu */
> + task_rq = task_rq(p);
> + lockdep_assert_rq_held(task_rq);
> +
> + WARN_ON_ONCE(!cpumask_test_cpu(cpu_of(rq), p->cpus_ptr));
> + deactivate_task(task_rq, p, 0);
> + set_task_cpu(p, cpu_of(rq));
> + p->scx.sticky_cpu = cpu_of(rq);
(this *could* live in ->migrate_task_rq(), but yeah, you only have this
one site, so meh)
> +
> + /*
> + * We want to pass scx-specific enq_flags but activate_task() will
> + * truncate the upper 32 bit. As we own @rq, we can pass them through
> + * @rq->scx.extra_enq_flags instead.
> + */
> + WARN_ON_ONCE(rq->scx.extra_enq_flags);
> + rq->scx.extra_enq_flags = enq_flags;
eeew.. it's not just activate_task(), its the whole callchain having
'int' flags. That said, we should be having plenty free bits there no?
> + activate_task(rq, p, 0);
> + rq->scx.extra_enq_flags = 0;
> +
> + return true;
> +}
> +static bool consume_remote_task(struct rq *rq, struct scx_dispatch_q *dsq,
> + struct task_struct *p, struct rq *task_rq)
> +{
> + bool moved = false;
> +
> + lockdep_assert_held(&dsq->lock); /* released on return */
> +
> + /*
> + * @dsq is locked and @p is on a remote rq. @p is currently protected by
> + * @dsq->lock. We want to pull @p to @rq but may deadlock if we grab
> + * @task_rq while holding @dsq and @rq locks. As dequeue can't drop the
> + * rq lock or fail, do a little dancing from our side. See
> + * move_task_to_local_dsq().
> + */
> + WARN_ON_ONCE(p->scx.holding_cpu >= 0);
> + task_unlink_from_dsq(p, dsq);
> + dsq_mod_nr(dsq, -1);
> + p->scx.holding_cpu = raw_smp_processor_id();
> + raw_spin_unlock(&dsq->lock);
> +
> + double_lock_balance(rq, task_rq);
> +
> + moved = move_task_to_local_dsq(rq, p, 0);
> +
> + double_unlock_balance(rq, task_rq);
> +
> + return moved;
> +}
I've gotta ask, why are you using the double_lock_balance() pattern
instead of the one in move_queued_task() that does:
lock src
dequeue src, task
set_task_cpu task, dst
unlock src
lock dst
enqueue dst, task
unlock dst
> +/*
> + * Similar to kernel/sched/core.c::is_cpu_allowed() but we're testing whether @p
> + * can be pulled to @rq.
> + */
> +static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq)
> +{
> + int cpu = cpu_of(rq);
> +
> + if (!cpumask_test_cpu(cpu, p->cpus_ptr))
> + return false;
> + if (unlikely(is_migration_disabled(p)))
> + return false;
> + if (!(p->flags & PF_KTHREAD) && unlikely(!task_cpu_possible(cpu, p)))
> + return false;
> + if (!scx_rq_online(rq))
> + return false;
> + return true;
> +}
I'm a little confused, is_cpu_allowed() is used for that same purpose
no?
next prev parent reply other threads:[~2024-08-02 12:20 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-15 22:32 [GIT PULL] sched_ext: Initial pull request for v6.11 Tejun Heo
2024-07-23 16:33 ` Peter Zijlstra
2024-07-23 19:34 ` Tejun Heo
2024-07-24 8:52 ` Peter Zijlstra
2024-07-24 17:38 ` David Vernet
2024-07-31 1:36 ` Tejun Heo
2024-08-02 11:10 ` Peter Zijlstra
2024-08-02 16:09 ` Tejun Heo
2024-08-02 17:37 ` Peter Zijlstra
2024-08-06 21:10 ` Peter Zijlstra
2024-08-06 21:34 ` Tejun Heo
2024-08-06 21:55 ` Peter Zijlstra
2024-08-06 22:09 ` Tejun Heo
2024-08-10 20:45 ` Peter Zijlstra
2024-08-13 19:14 ` Tejun Heo
2024-08-13 22:53 ` Peter Zijlstra
2024-08-21 23:08 ` Tejun Heo
2024-08-06 19:56 ` Tejun Heo
2024-08-06 20:18 ` Peter Zijlstra
2024-08-06 20:20 ` Tejun Heo
2024-08-02 12:20 ` Peter Zijlstra [this message]
2024-08-02 18:47 ` Tejun Heo
2024-08-06 8:27 ` Peter Zijlstra
2024-08-06 19:17 ` Tejun Heo
2024-07-25 1:19 ` Qais Yousef
2024-07-30 9:04 ` Peter Zijlstra
2024-07-31 1:11 ` Tejun Heo
2024-07-31 1:22 ` Tejun Heo
2024-08-01 13:17 ` Qais Yousef
2024-08-01 16:36 ` Tejun Heo
2024-08-05 1:44 ` Qais Yousef
2024-08-01 2:50 ` Russell Haley
2024-08-01 15:52 ` Qais Yousef
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240802122034.GZ12673@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=ast@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@linutronix.de \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=void@manifault.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.