Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp36130179rwd; Mon, 10 Jul 2023 18:43:58 -0700 (PDT) X-Google-Smtp-Source: APBJJlH++z6oiel7dK4GauzaRPmzoNgfalvzbSIonQGP5g+t+S6LGfUkP3qErAjxvq5e8kRMokcm X-Received: by 2002:a05:620a:440e:b0:762:3a20:7719 with SMTP id v14-20020a05620a440e00b007623a207719mr15716160qkp.18.1689039838221; Mon, 10 Jul 2023 18:43:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689039838; cv=none; d=google.com; s=arc-20160816; b=0tmiYhe+G0dB+4SZQoAyVWF16wbvISnOdkHn07Bfed8HOkUwysUkp/TgFksn0IE9iZ 5jtjLncCcHV61EauMySwWAwavNJJoihd7MogY+eMvmYX1irBoO0e6KcjPZJFAPBYF0W1 ZMTKkwkSGjVM4VA9BA5amnNSSIXnw5T3jTioQLC4O8bh7Hl/Z9m/e5UY1quFAWOLWrC3 2YzfgHrl8Ze6epvKIawM2qYr9bQHHk9kUfcZmAWXntfh6UC6a+0E11kaD6/PxWZAGEtR xAO4RGwR7nbyUBLsCE+ERw9dZqyqJDUvwAJOLefheFWB/IwLkuLmz2KVNWUbsyYNAyYy JX6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from:sender :dkim-signature; bh=nuoVWya4YfWY/OJXSRyOO/5rMbdi2w04jJFFLIa1/Nk=; fh=5bvFqXZy/VrzcWOXnXaaKVCt2r2P+2FQUI6EKkM71t8=; b=0BRYfYxvMobyDwbB+Ea22v/dIY0lLE2ckkE4yXH7yHJ1yWKHWVN6JaiI7+/ojPuTI8 ka7vfqY0l67qNikexsTRun8q4EA46d8LDeRxuolF98x36RT1SU5I3P4Vjznom4XPJWXq CzRxPG9EpM8g43AONUoM9jFF6nwJa5bhmQSzRLu0rwAcVLwXQLygdT/bOLc8Xx1W6/w2 1VrHX5hgBe78rjtI5flYcw9m596yW9tVG3vBzOFaLHsF3oYmIEhcq5p81LxcL0x60hTl +JzlMxnvVqOR8UFyKYpeIqfoeX0KIjohyogSoInWY5ddGRcaSl7I61OJ3L0N/aq7iGbU aGPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=rWCNn2mc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j187-20020a638bc4000000b0055c3e870ad5si548106pge.269.2023.07.10.18.43.15; Mon, 10 Jul 2023 18:43:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=rWCNn2mc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231493AbjGKBQg (ORCPT + 99 others); Mon, 10 Jul 2023 21:16:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231446AbjGKBQK (ORCPT ); Mon, 10 Jul 2023 21:16:10 -0400 Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52A90E51; Mon, 10 Jul 2023 18:15:31 -0700 (PDT) Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-1b0606bee45so4716868fac.3; Mon, 10 Jul 2023 18:15:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1689038098; x=1691630098; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=nuoVWya4YfWY/OJXSRyOO/5rMbdi2w04jJFFLIa1/Nk=; b=rWCNn2mc09ao9apGTBwKsxA9FMFDF6AVXkzMsEuissaiCepui96bI0vvDfDKFqwZk1 8IWi1qRfl2sJ0SK/+9jdW48xr15Ak4KqR4EVeQ6w4plDVa7VJm1HfE0H85HXfsBpLvxI rBXPig0EgdXUpPs6OEJacWaeovbMSe5GLfVoOtW5KeApwohhuriOFi1leIe7FEISWGVB Cn1dcD8tUW1CFGIXdKO+E8tE4FBd/fbkUNYNdtQMzblgZoXMzlEyKmUPLmRyi06wvDTl 0kDMQxb1eIPQ4T8JkfwSZBnUGsO9zTn+Si4AC6eUURm1hCqyhiMo/9oYrzQgUKcArHhI 2V/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689038098; x=1691630098; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nuoVWya4YfWY/OJXSRyOO/5rMbdi2w04jJFFLIa1/Nk=; b=jbdijW7F4wwIjnEFjumV135rLRRmx/xSNSryKXrXSbH0oIkdRCN9DsP6Cq7UsGfXZx 0dLDpakslqiy33BfzWXDB2PZXslO/qR+4Td0vMZc4tj7Db/KmWrKqk9luKVxSpc6m0qI ujb9G4M3mHUY+9soOnG0ZUrJz/2d72jN4IvnQZ+u/b2rGuXFj7MBK3fGbxGqpHsIVVdB L9NxqeRuRJW+1IzI1sWEsWIkSA8xMmh3hYTakaxaAjhNiTmhkH01AYgmoDpMIDStukw2 LgRGpFlZ1UBvYxuyoDqcrycNM3GybqW0/5K+k3JT3dNCcVIfuRwc/EkFbbOLR7/4R7Po XOGQ== X-Gm-Message-State: ABy/qLa6Ve2sQvE7kOtsXH3p/AfNlvcOiyzMwPaKxJB30Nim1zntmmeg 21SMnRIkgUNub9wJe/XyeWU= X-Received: by 2002:a05:6870:f720:b0:1b7:43ba:3249 with SMTP id ej32-20020a056870f72000b001b743ba3249mr3254235oab.3.1689038098310; Mon, 10 Jul 2023 18:14:58 -0700 (PDT) Received: from localhost ([2620:10d:c090:400::5:e2fe]) by smtp.gmail.com with ESMTPSA id y20-20020a170902b49400b001a6a6169d45sm504388plr.168.2023.07.10.18.14.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 18:14:57 -0700 (PDT) Sender: Tejun Heo From: Tejun Heo To: torvalds@linux-foundation.org, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@kernel.org, joshdon@google.com, brho@google.com, pjt@google.com, derkling@google.com, haoluo@google.com, dvernet@meta.com, dschatzberg@meta.com, dskarlat@cs.cmu.edu, riel@surriel.com Cc: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, kernel-team@meta.com, Tejun Heo Subject: [PATCH 21/34] sched_ext: Add task state tracking operations Date: Mon, 10 Jul 2023 15:13:39 -1000 Message-ID: <20230711011412.100319-22-tj@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230711011412.100319-1-tj@kernel.org> References: <20230711011412.100319-1-tj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Being able to track the task runnable and running state transitions are useful for a variety of purposes including latency tracking and load factor calculation. Currently, BPF schedulers don't have a good way of tracking these transitions. Becoming runnable can be determined from ops.enqueue() but becoming quiescent can only be inferred from the lack of subsequent enqueue. Also, as the local dsq can have multiple tasks and some events are handled in the sched_ext core, it's difficult to determine when a given task starts and stops executing. This patch adds sched_ext_ops.runnable(), .running(), .stopping() and .quiescent() operations to track the task runnable and running state transitions. They're mostly self explanatory; however, we want to ensure that running <-> stopping transitions are always contained within runnable <-> quiescent transitions which is a bit different from how the scheduler core behaves. This adds a bit of complication. See the comment in dequeue_task_scx(). Signed-off-by: Tejun Heo Reviewed-by: David Vernet Acked-by: Josh Don Acked-by: Hao Luo Acked-by: Barret Rhoden --- include/linux/sched/ext.h | 65 +++++++++++++++++++++++++++++++++++++++ kernel/sched/ext.c | 31 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/include/linux/sched/ext.h b/include/linux/sched/ext.h index 5c2df7ccc0a6..5cc37bc30352 100644 --- a/include/linux/sched/ext.h +++ b/include/linux/sched/ext.h @@ -192,6 +192,71 @@ struct sched_ext_ops { */ void (*dispatch)(s32 cpu, struct task_struct *prev); + /** + * runnable - A task is becoming runnable on its associated CPU + * @p: task becoming runnable + * @enq_flags: %SCX_ENQ_* + * + * This and the following three functions can be used to track a task's + * execution state transitions. A task becomes ->runnable() on a CPU, + * and then goes through one or more ->running() and ->stopping() pairs + * as it runs on the CPU, and eventually becomes ->quiescent() when it's + * done running on the CPU. + * + * @p is becoming runnable on the CPU because it's + * + * - waking up (%SCX_ENQ_WAKEUP) + * - being moved from another CPU + * - being restored after temporarily taken off the queue for an + * attribute change. + * + * This and ->enqueue() are related but not coupled. This operation + * notifies @p's state transition and may not be followed by ->enqueue() + * e.g. when @p is being dispatched to a remote CPU. Likewise, a task + * may be ->enqueue()'d without being preceded by this operation e.g. + * after exhausting its slice. + */ + void (*runnable)(struct task_struct *p, u64 enq_flags); + + /** + * running - A task is starting to run on its associated CPU + * @p: task starting to run + * + * See ->runnable() for explanation on the task state notifiers. + */ + void (*running)(struct task_struct *p); + + /** + * stopping - A task is stopping execution + * @p: task stopping to run + * @runnable: is task @p still runnable? + * + * See ->runnable() for explanation on the task state notifiers. If + * !@runnable, ->quiescent() will be invoked after this operation + * returns. + */ + void (*stopping)(struct task_struct *p, bool runnable); + + /** + * quiescent - A task is becoming not runnable on its associated CPU + * @p: task becoming not runnable + * @deq_flags: %SCX_DEQ_* + * + * See ->runnable() for explanation on the task state notifiers. + * + * @p is becoming quiescent on the CPU because it's + * + * - sleeping (%SCX_DEQ_SLEEP) + * - being moved to another CPU + * - being temporarily taken off the queue for an attribute change + * (%SCX_DEQ_SAVE) + * + * This and ->dequeue() are related but not coupled. This operation + * notifies @p's state transition and may not be preceded by ->dequeue() + * e.g. when @p is being dispatched to a remote CPU. + */ + void (*quiescent)(struct task_struct *p, u64 deq_flags); + /** * yield - Yield CPU * @from: yielding task diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 48e27d59e621..2951200cd81a 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -775,6 +775,9 @@ static void enqueue_task_scx(struct rq *rq, struct task_struct *p, int enq_flags rq->scx.nr_running++; add_nr_running(rq, 1); + if (SCX_HAS_OP(runnable)) + SCX_CALL_OP(SCX_KF_REST, runnable, p, enq_flags); + do_enqueue_task(rq, p, enq_flags, sticky_cpu); } @@ -835,6 +838,26 @@ static void dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags ops_dequeue(p, deq_flags); + /* + * A currently running task which is going off @rq first gets dequeued + * and then stops running. As we want running <-> stopping transitions + * to be contained within runnable <-> quiescent transitions, trigger + * ->stopping() early here instead of in put_prev_task_scx(). + * + * @p may go through multiple stopping <-> running transitions between + * here and put_prev_task_scx() if task attribute changes occur while + * balance_scx() leaves @rq unlocked. However, they don't contain any + * information meaningful to the BPF scheduler and can be suppressed by + * skipping the callbacks if the task is !QUEUED. + */ + if (SCX_HAS_OP(stopping) && task_current(rq, p)) { + update_curr_scx(rq); + SCX_CALL_OP(SCX_KF_REST, stopping, p, false); + } + + if (SCX_HAS_OP(quiescent)) + SCX_CALL_OP(SCX_KF_REST, quiescent, p, deq_flags); + if (deq_flags & SCX_DEQ_SLEEP) p->scx.flags |= SCX_TASK_DEQD_FOR_SLEEP; else @@ -1371,6 +1394,10 @@ static void set_next_task_scx(struct rq *rq, struct task_struct *p, bool first) p->se.exec_start = rq_clock_task(rq); + /* see dequeue_task_scx() on why we skip when !QUEUED */ + if (SCX_HAS_OP(running) && (p->scx.flags & SCX_TASK_QUEUED)) + SCX_CALL_OP(SCX_KF_REST, running, p); + watchdog_unwatch_task(p, true); } @@ -1409,6 +1436,10 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p) update_curr_scx(rq); + /* see dequeue_task_scx() on why we skip when !QUEUED */ + if (SCX_HAS_OP(stopping) && (p->scx.flags & SCX_TASK_QUEUED)) + SCX_CALL_OP(SCX_KF_REST, stopping, p, true); + /* * If we're being called from put_prev_task_balance(), balance_scx() may * have decided that @p should keep running. -- 2.41.0