Received: by 2002:a05:7412:b10a:b0:f3:1519:9f41 with SMTP id az10csp904966rdb; Fri, 1 Dec 2023 01:29:05 -0800 (PST) X-Google-Smtp-Source: AGHT+IEE0VuLbAXIasGW3Yg6ecCUhybaHo2ST2eQDcGFk8fCq3uPc3HCuJuVn94+iimDIuPhOv8n X-Received: by 2002:a05:6a20:baa4:b0:18b:82cb:4092 with SMTP id fb36-20020a056a20baa400b0018b82cb4092mr20791574pzb.11.1701422944896; Fri, 01 Dec 2023 01:29:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701422944; cv=none; d=google.com; s=arc-20160816; b=cijJhO6SneYUZJcVOG46+G7Na2Nrx/YxaQkNcl3k9sr+rDigOn2js3qVeb5CacU69r 5fbQjee4Wfno4e9m3N4KAcLsi9DVzExai0Ov6lnZ7Vk8UQdG3mlLmQytdN3JmbsBvaDZ axziNCmCVjVE6injsIMl08MR40UD6TDRskqFMCfpk9A/oDvRh2vXUcHKNwK27z6Ub26x wozj6ixw6ROCWXcCKtbBXPFv3GNBfDaibgwmXAIL+phrJwWyRoc2Pj9vtwdHwJy9aTDQ x6CXKNl0E9yAwWBLShs1at7eFgsMSK3AstJjzM6O+6VNuEhgUOFMth22DxD/B40iuwsH rqBw== 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:dkim-signature :dkim-signature:from; bh=EMy/vrIt0wUl/L/Xwvre8ZwMi27M9d4t8qpR3rpCe2k=; fh=PG6uS4TiiUSDyl8D/joYkWbwCgDm4ug0ir2h7tHBJXQ=; b=1LqsDlqM2IdcqXZhfeUgRW8ve6l3Y3fwJHjy7zk1w0cKxuEzCZY2NCxv+cTrvK+v94 Hz87DH1NmeX2wV77xFDuXh09ZDFFJBt2unvPbJsWZ1odE5WhrIKd8siai1sTrlfY7+n4 s5DHqjMOto2n1Jfe+EFXxWGaYDjY/Y1KYNj5ya/gcKUVDcA72GTbNkt3iOoSIea51QqN Lf8B5VElcn35CKTNDfyOjTOv+BAMtqcPjFbZuLA7I5dW9ahENcEBc4tc4zbS2xzvQ8UN QTKvHGz6cuu4yZs4mmadjQPax/Sn+pQrVcTUJv6RmG1B8WYqin5ZE6Eh/GarXf8mGfeB dPrA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=yCIUgpS6; dkim=neutral (no key) header.i=@linutronix.de header.b="LwTgEJB/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id f2-20020a17090ab94200b002859a10051fsi3094602pjw.136.2023.12.01.01.29.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 01:29:04 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=yCIUgpS6; dkim=neutral (no key) header.i=@linutronix.de header.b="LwTgEJB/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 4415E815F340; Fri, 1 Dec 2023 01:29:02 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378127AbjLAJ2o (ORCPT + 99 others); Fri, 1 Dec 2023 04:28:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55030 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378171AbjLAJ2J (ORCPT ); Fri, 1 Dec 2023 04:28:09 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2FF21BF0 for ; Fri, 1 Dec 2023 01:27:25 -0800 (PST) From: Anna-Maria Behnsen DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1701422844; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EMy/vrIt0wUl/L/Xwvre8ZwMi27M9d4t8qpR3rpCe2k=; b=yCIUgpS6DAyFZ8C+W8wpV+zk8mIstno8Qba+0sPG3PSxDJo+5BUB5F473xYkcVjgPP3dqD VXjM6gDKpd56m7SVWXJuVMkXwInZHcUxydH+gKyAWwMriE/h/7KF3lMYHr6DR5no3LxqaZ uu4OqVGV5fFmOBxfkTQvWy47cH74awVqLpGZjR2Mz+lCJ8ZQGLagORM4Agy4kf7/06VM/1 nBPTuvltdE2/XdGcl0pE/+sxVTES6ed2yHTYxln+d084ZGenBbqFLcyBExYdlxj2eDXZ+i aD8o5bbmJBzEW/BEvoH+717FWClTXFQVy1XfaCOY8yunMWNY7Mec/EXorOuv6w== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1701422844; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EMy/vrIt0wUl/L/Xwvre8ZwMi27M9d4t8qpR3rpCe2k=; b=LwTgEJB/4Z47VOr90GUt4Dm/KDzYcbxGm3Lp9yeRN6wbMT0NGFec55NSe5xhWf9zfwsoL4 P0W4Qs23JbuKXoAQ== To: linux-kernel@vger.kernel.org Cc: Peter Zijlstra , John Stultz , Thomas Gleixner , Eric Dumazet , "Rafael J . Wysocki" , Arjan van de Ven , "Paul E . McKenney" , Frederic Weisbecker , Rik van Riel , Steven Rostedt , Sebastian Siewior , Giovanni Gherdovich , Lukasz Luba , "Gautham R . Shenoy" , Srinivas Pandruvada , K Prateek Nayak , Anna-Maria Behnsen Subject: [PATCH v9 25/32] timers: Add get next timer interrupt functionality for remote CPUs Date: Fri, 1 Dec 2023 10:26:47 +0100 Message-Id: <20231201092654.34614-26-anna-maria@linutronix.de> In-Reply-To: <20231201092654.34614-1-anna-maria@linutronix.de> References: <20231201092654.34614-1-anna-maria@linutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Fri, 01 Dec 2023 01:29:02 -0800 (PST) To prepare for the conversion of the NOHZ timer placement to a pull at expiry time model it's required to have functionality available getting the next timer interrupt on a remote CPU. Locking of the timer bases and getting the information for the next timer interrupt functionality is split into separate functions. This is required to be compliant with lock ordering when the new model is in place. Signed-off-by: Anna-Maria Behnsen Reviewed-by: Frederic Weisbecker --- v8: - Update comment v7: - Move functions into CONFIG_SMP && CONFIG_NO_HZ_COMMON section - change lock, fetch functions to be unconditional - split out unlock function into a separate function v6: - introduce timer_lock_remote_bases() to fix race --- kernel/time/tick-internal.h | 10 +++++ kernel/time/timer.c | 76 ++++++++++++++++++++++++++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index dc12a938f00f..183ad32330fb 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -8,6 +8,11 @@ #include "timekeeping.h" #include "tick-sched.h" +struct timer_events { + u64 local; + u64 global; +}; + #ifdef CONFIG_GENERIC_CLOCKEVENTS # define TICK_DO_TIMER_NONE -1 @@ -155,6 +160,11 @@ extern unsigned long tick_nohz_active; extern void timers_update_nohz(void); # ifdef CONFIG_SMP extern struct static_key_false timers_migration_enabled; +extern void fetch_next_timer_interrupt_remote(unsigned long basej, u64 basem, + struct timer_events *tevt, + unsigned int cpu); +extern void timer_lock_remote_bases(unsigned int cpu); +extern void timer_unlock_remote_bases(unsigned int cpu); # endif #else /* CONFIG_NO_HZ_COMMON */ static inline void timers_update_nohz(void) { } diff --git a/kernel/time/timer.c b/kernel/time/timer.c index fc376e06980e..2cff43c10329 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -221,11 +221,6 @@ struct timer_base { static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]); -struct timer_events { - u64 local; - u64 global; -}; - #ifdef CONFIG_NO_HZ_COMMON static DEFINE_STATIC_KEY_FALSE(timers_nohz_active); @@ -2039,6 +2034,77 @@ static unsigned long fetch_next_timer_interrupt(unsigned long basej, u64 basem, return nextevt; } +# ifdef CONFIG_SMP +/** + * fetch_next_timer_interrupt_remote() - Store next timers into @tevt + * @basej: base time jiffies + * @basem: base time clock monotonic + * @tevt: Pointer to the storage for the expiry values + * @cpu: Remote CPU + * + * Stores the next pending local and global timer expiry values in the + * struct pointed to by @tevt. If a queue is empty the corresponding + * field is set to KTIME_MAX. If local event expires before global + * event, global event is set to KTIME_MAX as well. + * + * Caller needs to make sure timer base locks are held (use + * timer_lock_remote_bases() for this purpose). + */ +void fetch_next_timer_interrupt_remote(unsigned long basej, u64 basem, + struct timer_events *tevt, + unsigned int cpu) +{ + struct timer_base *base_local, *base_global; + + /* Preset local / global events */ + tevt->local = tevt->global = KTIME_MAX; + + base_local = per_cpu_ptr(&timer_bases[BASE_LOCAL], cpu); + base_global = per_cpu_ptr(&timer_bases[BASE_GLOBAL], cpu); + + lockdep_assert_held(&base_local->lock); + lockdep_assert_held(&base_global->lock); + + fetch_next_timer_interrupt(basej, basem, base_local, base_global, tevt); +} + +/** + * timer_unlock_remote_bases - unlock timer bases of cpu + * @cpu: Remote CPU + * + * Unlocks the remote timer bases. + */ +void timer_unlock_remote_bases(unsigned int cpu) +{ + struct timer_base *base_local, *base_global; + + base_local = per_cpu_ptr(&timer_bases[BASE_LOCAL], cpu); + base_global = per_cpu_ptr(&timer_bases[BASE_GLOBAL], cpu); + + raw_spin_unlock(&base_global->lock); + raw_spin_unlock(&base_local->lock); +} + +/** + * timer_lock_remote_bases - lock timer bases of cpu + * @cpu: Remote CPU + * + * Locks the remote timer bases. + */ +void timer_lock_remote_bases(unsigned int cpu) +{ + struct timer_base *base_local, *base_global; + + base_local = per_cpu_ptr(&timer_bases[BASE_LOCAL], cpu); + base_global = per_cpu_ptr(&timer_bases[BASE_GLOBAL], cpu); + + lockdep_assert_irqs_disabled(); + + raw_spin_lock(&base_local->lock); + raw_spin_lock_nested(&base_global->lock, SINGLE_DEPTH_NESTING); +} +# endif /* CONFIG_SMP */ + static inline u64 __get_next_timer_interrupt(unsigned long basej, u64 basem, bool *idle) { -- 2.39.2