From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F131217663 for ; Tue, 27 May 2025 22:23:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384594; cv=none; b=bJv5ZqtnutBP9uo+ii4dN8X2xkB4oWH6smr1xtSz4qw+TP3NQvhHOgx1iRZdkQowxvv1NBhCNhL7Chh7z1B5sqZRduncjvOXOJAuqOFCVD0iu/1iwvvx//3louthUfDKh9odRG//HY2/Nh3ld/9rUgiAG2gDoghe2tRrW4woRtU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384594; c=relaxed/simple; bh=DhNE6lF14CPdGsZE0KobLqxwSQt0aNL4B193ePPpRQ8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OigLziFEMleD8EVTpoknSDUsCbaESPTL4R/MAyZNxI2PTSHLdi5Inn89sTDKrfC6VI2vBfZWuPUMh/j5xrFJ4ITLi8z+d+Nu3vjctZcqNCZ3QiuR70GTqmYBE0XzD8cKeauAyn/jALmf0YxBgeVPzxFHK+nXGHiYmswdMiw6C9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CiPBvl6b; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CiPBvl6b" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384591; 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=o1D/dLQQvIMU1jnPqA8TcYF0yBodWfuRo9ocdMJdqcc=; b=CiPBvl6bAXl7aBSiqryVo6G+W2+bSkkqiWQNaFGeLFJKviVQx2KyMOwIG5apsCAHDBfGSC WIbL9k1MJ0Np070vvz8L/WdbmjOflwRIcJ2PxRhQw/0SBLxM91Xsucu9aggPewNhM4Pwcp nu11iAUO9l+3SKK/KdaGNO3yA8Bu5P4= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-302-40AAxw4SN0G-Ou-nYyE32g-1; Tue, 27 May 2025 18:23:08 -0400 X-MC-Unique: 40AAxw4SN0G-Ou-nYyE32g-1 X-Mimecast-MFC-AGG-ID: 40AAxw4SN0G-Ou-nYyE32g_1748384586 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C2FA51955DAD; Tue, 27 May 2025 22:23:05 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A4C03180047F; Tue, 27 May 2025 22:23:01 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider Subject: [RFC RESEND v10 01/14] preempt: Introduce HARDIRQ_DISABLE_BITS Date: Tue, 27 May 2025 18:21:42 -0400 Message-ID: <20250527222254.565881-2-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" From: Boqun Feng In order to support preempt_disable()-like interrupt disabling, that is, using part of preempt_count() to track interrupt disabling nested level, change the preempt_count() layout to contain 8-bit HARDIRQ_DISABLE count. Note that HARDIRQ_BITS and NMI_BITS are reduced by 1 because of this, and it changes the maximum of their (hardirq and nmi) nesting level. Signed-off-by: Boqun Feng Signed-off-by: Lyude Paul --- include/linux/preempt.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/preempt.h b/include/linux/preempt.h index b0af8d4ef6e66..809af7b57470a 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -17,6 +17,7 @@ * * - bits 0-7 are the preemption count (max preemption depth: 256) * - bits 8-15 are the softirq count (max # of softirqs: 256) + * - bits 16-23 are the hardirq disable count (max # of hardirq disable: 2= 56) * * The hardirq count could in theory be the same as the number of * interrupts in the system, but we run all interrupt handlers with @@ -26,29 +27,34 @@ * * PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 - * HARDIRQ_MASK: 0x000f0000 - * NMI_MASK: 0x00f00000 + * HARDIRQ_DISABLE_MASK: 0x00ff0000 + * HARDIRQ_MASK: 0x07000000 + * NMI_MASK: 0x38000000 * PREEMPT_NEED_RESCHED: 0x80000000 */ #define PREEMPT_BITS 8 #define SOFTIRQ_BITS 8 -#define HARDIRQ_BITS 4 -#define NMI_BITS 4 +#define HARDIRQ_DISABLE_BITS 8 +#define HARDIRQ_BITS 3 +#define NMI_BITS 3 =20 #define PREEMPT_SHIFT 0 #define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) -#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS) +#define HARDIRQ_DISABLE_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS) +#define HARDIRQ_SHIFT (HARDIRQ_DISABLE_SHIFT + HARDIRQ_DISABLE_BITS) #define NMI_SHIFT (HARDIRQ_SHIFT + HARDIRQ_BITS) =20 #define __IRQ_MASK(x) ((1UL << (x))-1) =20 #define PREEMPT_MASK (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT) #define SOFTIRQ_MASK (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) +#define HARDIRQ_DISABLE_MASK (__IRQ_MASK(SOFTIRQ_BITS) << HARDIRQ_DISABLE_= SHIFT) #define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) #define NMI_MASK (__IRQ_MASK(NMI_BITS) << NMI_SHIFT) =20 #define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT) #define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT) +#define HARDIRQ_DISABLE_OFFSET (1UL << HARDIRQ_DISABLE_SHIFT) #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) #define NMI_OFFSET (1UL << NMI_SHIFT) =20 --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E23C82153CE for ; Tue, 27 May 2025 22:23:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384604; cv=none; b=FyRQLUOliV82Hwxn9L5Ws2u9+b2ocoADpFGbz9oNM2UOUzkW7azPKLefB+Ys+7G7oGWvHoBYT8daqe1YsB/lHr7pJPK+QpFePv+9YMsRbK3wt04Q3ga+MyQyOBBDI+zqvMB8uu58q6l6RuTNHk0DJ2+9S5MKVda7vc8hRRY2IKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384604; c=relaxed/simple; bh=9cTdol3MMnOjJH1jz5ap+/NwOMEbIz134B2Qe0qHmwo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=odCOll5Qd+sOBjbwO0+NE2xBXJ/LZDO6o4xXfE3xn17/wUlOz0LDDlyZhSssU6EZnYjUgPt0LtztNAvs9I6bWUzt2k68se6nCXKAJK6roOHh326OJM5a8cWc1Qq4lCltUegTLseLiPXLcsX4wjUJfTiiX4n6QEZSqY7uTf6WySw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=OwtCP4S1; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OwtCP4S1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384601; 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=dwjzi5fBBrhf+4k/JvlyIlug6jfDDxsGNSd2rZoY3lk=; b=OwtCP4S1bDU5qm1r3eHdJCJMEPEmh7Cs2fCE83kLA59CpSz60Yxz24IQ5uCazHZxt6gaEl rQV/t5lplAgHb+Swo9Esj7vhAu+VSZdRM44h6FzsppCjFv98rhNDPc5WP7NKMCD1lDc8eG d6QnJArYutc3rqPv/X8EmJsn+hiJGtE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-117-UhWP4Y6OP0qj4sF1Ku4IlA-1; Tue, 27 May 2025 18:23:18 -0400 X-MC-Unique: UhWP4Y6OP0qj4sF1Ku4IlA-1 X-Mimecast-MFC-AGG-ID: UhWP4Y6OP0qj4sF1Ku4IlA_1748384596 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 695BB1800447; Tue, 27 May 2025 22:23:15 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 844E819560AF; Tue, 27 May 2025 22:23:08 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Catalin Marinas , Will Deacon , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)), "H. Peter Anvin" , Arnd Bergmann , Juergen Christ , Uros Bizjak , Brian Gerst , linux-arm-kernel@lists.infradead.org (moderated list:ARM64 PORT (AARCH64 ARCHITECTURE)), linux-s390@vger.kernel.org (open list:S390 ARCHITECTURE), linux-arch@vger.kernel.org (open list:GENERIC INCLUDE/ASM HEADER FILES) Subject: [RFC RESEND v10 02/14] preempt: Introduce __preempt_count_{sub, add}_return() Date: Tue, 27 May 2025 18:21:43 -0400 Message-ID: <20250527222254.565881-3-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Content-Type: text/plain; charset="utf-8" From: Boqun Feng In order to use preempt_count() to tracking the interrupt disable nesting level, __preempt_count_{add,sub}_return() are introduced, as their name suggest, these primitives return the new value of the preempt_count() after changing it. The following example shows the usage of it in local_interrupt_disable(): // increase the HARDIRQ_DISABLE bit new_count =3D __preempt_count_add_return(HARDIRQ_DISABLE_OFFSET); // if it's the first-time increment, then disable the interrupt // at hardware level. if (new_count & HARDIRQ_DISABLE_MASK =3D=3D HARDIRQ_DISABLE_OFFSET) { local_irq_save(flags); raw_cpu_write(local_interrupt_disable_state.flags, flags); } Having these primitives will avoid a read of preempt_count() after changing preempt_count() on certain architectures. Signed-off-by: Boqun Feng --- V10: * Add commit message I forgot * Rebase against latest pcpu_hot changes Signed-off-by: Lyude Paul --- arch/arm64/include/asm/preempt.h | 18 ++++++++++++++++++ arch/s390/include/asm/preempt.h | 19 +++++++++++++++++++ arch/x86/include/asm/preempt.h | 10 ++++++++++ include/asm-generic/preempt.h | 14 ++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/pree= mpt.h index 0159b625cc7f0..49cb886c8e1dd 100644 --- a/arch/arm64/include/asm/preempt.h +++ b/arch/arm64/include/asm/preempt.h @@ -56,6 +56,24 @@ static inline void __preempt_count_sub(int val) WRITE_ONCE(current_thread_info()->preempt.count, pc); } =20 +static inline int __preempt_count_add_return(int val) +{ + u32 pc =3D READ_ONCE(current_thread_info()->preempt.count); + pc +=3D val; + WRITE_ONCE(current_thread_info()->preempt.count, pc); + + return pc; +} + +static inline int __preempt_count_sub_return(int val) +{ + u32 pc =3D READ_ONCE(current_thread_info()->preempt.count); + pc -=3D val; + WRITE_ONCE(current_thread_info()->preempt.count, pc); + + return pc; +} + static inline bool __preempt_count_dec_and_test(void) { struct thread_info *ti =3D current_thread_info(); diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preemp= t.h index 6ccd033acfe52..67a6e265e9fff 100644 --- a/arch/s390/include/asm/preempt.h +++ b/arch/s390/include/asm/preempt.h @@ -98,6 +98,25 @@ static __always_inline bool should_resched(int preempt_o= ffset) return unlikely(READ_ONCE(get_lowcore()->preempt_count) =3D=3D preempt_of= fset); } =20 +static __always_inline int __preempt_count_add_return(int val) +{ + /* + * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES + * enabled, gcc 12 fails to handle __builtin_constant_p(). + */ + if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) { + if (__builtin_constant_p(val) && (val >=3D -128) && (val <=3D 127)) { + return val + __atomic_add_const(val, &get_lowcore()->preempt_count); + } + } + return val + __atomic_add(val, &get_lowcore()->preempt_count); +} + +static __always_inline int __preempt_count_sub_return(int val) +{ + return __preempt_count_add_return(-val); +} + #define init_task_preempt_count(p) do { } while (0) /* Deferred to CPU bringup time */ #define init_idle_preempt_count(p, cpu) do { } while (0) diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h index 578441db09f0b..1220656f3370b 100644 --- a/arch/x86/include/asm/preempt.h +++ b/arch/x86/include/asm/preempt.h @@ -85,6 +85,16 @@ static __always_inline void __preempt_count_sub(int val) raw_cpu_add_4(__preempt_count, -val); } =20 +static __always_inline int __preempt_count_add_return(int val) +{ + return raw_cpu_add_return_4(__preempt_count, val); +} + +static __always_inline int __preempt_count_sub_return(int val) +{ + return raw_cpu_add_return_4(__preempt_count, -val); +} + /* * Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to resch= edule * a decrement which hits zero means we have no preempt_count and should diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index 51f8f3881523a..c8683c046615d 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -59,6 +59,20 @@ static __always_inline void __preempt_count_sub(int val) *preempt_count_ptr() -=3D val; } =20 +static __always_inline int __preempt_count_add_return(int val) +{ + *preempt_count_ptr() +=3D val; + + return *preempt_count_ptr(); +} + +static __always_inline int __preempt_count_sub_return(int val) +{ + *preempt_count_ptr() -=3D val; + + return *preempt_count_ptr(); +} + static __always_inline bool __preempt_count_dec_and_test(void) { /* --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD2042165E2 for ; Tue, 27 May 2025 22:23:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384615; cv=none; b=IGvGnMmrwrEGa/f6aHM/WXVBOpTZLlQHGDfIOFuRFI6mSvzBUQc1DDO4LzEoMr7UVcezCc8eLv+bLAxgiLEvYBWubYwHN3ADf3sIgWjTL5qIg0JTWNOH0PeEGOGr+MS+szR5dW0KJubrF4mvbgh9cvd8xx3U3fzjKcDIedeAFH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384615; c=relaxed/simple; bh=UaENH4ZMsNZOYxFnOKGRkn6MSzP+9Jy05qq0A4Yb2Bs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JKIxrp2e2iFHIwkMONI6Qc16OWFxu5/ewFUhllK7kpn6UUuNQaeXlGwkQTSGxNKu7itkBm6gKAhcWRCFQRbQ6sXj8zLEcRgmt9Bf9EsgrPucD7Qs3GWK+SbwErqAW7w92aeKvtv8qW62PUMvPOFULCGAN6rjCs/YGqCCej1mkt4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=YWYX8pjK; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="YWYX8pjK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384612; 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=ZJV7g59pyf6aKPqQMD4Msa88yTBoagBc3guWzXNfM6w=; b=YWYX8pjKca+h0riDOkgKp2q4cn69Tz+ISA+gJatoASnqskkAxKJJjmb/fvNL8kZgTE0IN7 zE5CMxN2LgEuAOgbn1WML3taVrbGTAUOYuSFyXEwKSVBZS7bB/nR73sDhMfB8UZAOITOpd 6OiIjbC0rMu0Mm2ptMMY6a6f6tZ34+E= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-681-KLeJmRb9N365Zs8jhJp7MQ-1; Tue, 27 May 2025 18:23:29 -0400 X-MC-Unique: KLeJmRb9N365Zs8jhJp7MQ-1 X-Mimecast-MFC-AGG-ID: KLeJmRb9N365Zs8jhJp7MQ_1748384605 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 952161800447; Tue, 27 May 2025 22:23:24 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7DDED195608D; Tue, 27 May 2025 22:23:18 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , David Woodhouse , Jens Axboe , Sebastian Andrzej Siewior , NeilBrown , Caleb Sander Mateos , Ryo Takakura , K Prateek Nayak Subject: [RFC RESEND v10 03/14] irq & spin_lock: Add counted interrupt disabling/enabling Date: Tue, 27 May 2025 18:21:44 -0400 Message-ID: <20250527222254.565881-4-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" From: Boqun Feng Currently the nested interrupt disabling and enabling is present by _irqsave() and _irqrestore() APIs, which are relatively unsafe, for example: spin_lock_irqsave(l1, flag1); spin_lock_irqsave(l2, flag2); spin_unlock_irqrestore(l1, flags1); // accesses to interrupt-disable protect data will cause races. This is even easier to triggered with guard facilities: unsigned long flag2; scoped_guard(spin_lock_irqsave, l1) { spin_lock_irqsave(l2, flag2); } // l2 locked but interrupts are enabled. spin_unlock_irqrestore(l2, flag2); (Hand-to-hand locking critical sections are not uncommon for a fine-grained lock design) And because this unsafety, Rust cannot easily wrap the interrupt-disabling locks in a safe API, which complicates the design. To resolve this, introduce a new set of interrupt disabling APIs: * local_interrupt_disable(); * local_interrupt_enable(); They work like local_irq_save() and local_irq_restore() except that 1) the outermost local_interrupt_disable() call save the interrupt state into a percpu variable, so that the outermost local_interrupt_enable() can restore the state, and 2) a percpu counter is added to record the nest level of these calls, so that interrupts are not accidentally enabled inside the outermost critical section. Also add the corresponding spin_lock primitives: spin_lock_irq_disable() and spin_unlock_irq_enable(), as a result, code as follow: spin_lock_irq_disable(l1); spin_lock_irq_disable(l2); spin_unlock_irq_enable(l1); // Interrupts are still disabled. spin_unlock_irq_enable(l2); doesn't have the issue that interrupts are accidentally enabled. This also makes the wrapper of interrupt-disabling locks on Rust easier to design. Signed-off-by: Boqun Feng --- V10: * Add missing __raw_spin_lock_irq_disable() definition in spinlock.c Signed-off-by: Lyude Paul --- include/linux/irqflags.h | 1 - include/linux/irqflags_types.h | 6 ++++ include/linux/preempt.h | 4 +++ include/linux/spinlock.h | 62 ++++++++++++++++++++++++++++++++ include/linux/spinlock_api_smp.h | 27 ++++++++++++++ include/linux/spinlock_api_up.h | 8 +++++ include/linux/spinlock_rt.h | 10 ++++++ kernel/locking/spinlock.c | 31 ++++++++++++++++ kernel/softirq.c | 3 ++ 9 files changed, 151 insertions(+), 1 deletion(-) diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 57b074e0cfbbb..3519d06db55e0 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -231,7 +231,6 @@ extern void warn_bogus_irq_restore(void); raw_safe_halt(); \ } while (0) =20 - #else /* !CONFIG_TRACE_IRQFLAGS */ =20 #define local_irq_enable() do { raw_local_irq_enable(); } while (0) diff --git a/include/linux/irqflags_types.h b/include/linux/irqflags_types.h index c13f0d915097a..277433f7f53eb 100644 --- a/include/linux/irqflags_types.h +++ b/include/linux/irqflags_types.h @@ -19,4 +19,10 @@ struct irqtrace_events { =20 #endif =20 +/* Per-cpu interrupt disabling state for local_interrupt_{disable,enable}(= ) */ +struct interrupt_disable_state { + unsigned long flags; + long count; +}; + #endif /* _LINUX_IRQFLAGS_TYPES_H */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 809af7b57470a..c1c5795be5d0f 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -148,6 +148,10 @@ static __always_inline unsigned char interrupt_context= _level(void) #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) =20 +#define hardirq_disable_count() ((preempt_count() & HARDIRQ_DISABLE_MASK) = >> HARDIRQ_DISABLE_SHIFT) +#define hardirq_disable_enter() __preempt_count_add_return(HARDIRQ_DISABLE= _OFFSET) +#define hardirq_disable_exit() __preempt_count_sub_return(HARDIRQ_DISABLE_= OFFSET) + /* * The preempt_count offset after preempt_disable(); */ diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index d3561c4a080e2..b21da4bd51a42 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -272,9 +272,11 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *= lock) __releases(lock) #endif =20 #define raw_spin_lock_irq(lock) _raw_spin_lock_irq(lock) +#define raw_spin_lock_irq_disable(lock) _raw_spin_lock_irq_disable(lock) #define raw_spin_lock_bh(lock) _raw_spin_lock_bh(lock) #define raw_spin_unlock(lock) _raw_spin_unlock(lock) #define raw_spin_unlock_irq(lock) _raw_spin_unlock_irq(lock) +#define raw_spin_unlock_irq_enable(lock) _raw_spin_unlock_irq_enable(lock) =20 #define raw_spin_unlock_irqrestore(lock, flags) \ do { \ @@ -300,11 +302,56 @@ static inline void do_raw_spin_unlock(raw_spinlock_t = *lock) __releases(lock) 1 : ({ local_irq_restore(flags); 0; }); \ }) =20 +#define raw_spin_trylock_irq_disable(lock) \ +({ \ + local_interrupt_disable(); \ + raw_spin_trylock(lock) ? \ + 1 : ({ local_interrupt_enable(); 0; }); \ +}) + #ifndef CONFIG_PREEMPT_RT /* Include rwlock functions for !RT */ #include #endif =20 +DECLARE_PER_CPU(struct interrupt_disable_state, local_interrupt_disable_st= ate); + +static inline void local_interrupt_disable(void) +{ + unsigned long flags; + int new_count; + + new_count =3D hardirq_disable_enter(); + + if ((new_count & HARDIRQ_DISABLE_MASK) =3D=3D HARDIRQ_DISABLE_OFFSET) { + local_irq_save(flags); + raw_cpu_write(local_interrupt_disable_state.flags, flags); + } +} + +static inline void local_interrupt_enable(void) +{ + int new_count; + + new_count =3D hardirq_disable_exit(); + + if ((new_count & HARDIRQ_DISABLE_MASK) =3D=3D 0) { + unsigned long flags; + + flags =3D raw_cpu_read(local_interrupt_disable_state.flags); + local_irq_restore(flags); + /* + * TODO: re-read preempt count can be avoided, but it needs + * should_resched() taking another parameter as the current + * preempt count + */ +#ifdef PREEMPTION + if (should_resched(0)) + __preempt_schedule(); +#endif + } +} + /* * Pull the _spin_*()/_read_*()/_write_*() functions/declarations: */ @@ -376,6 +423,11 @@ static __always_inline void spin_lock_irq(spinlock_t *= lock) raw_spin_lock_irq(&lock->rlock); } =20 +static __always_inline void spin_lock_irq_disable(spinlock_t *lock) +{ + raw_spin_lock_irq_disable(&lock->rlock); +} + #define spin_lock_irqsave(lock, flags) \ do { \ raw_spin_lock_irqsave(spinlock_check(lock), flags); \ @@ -401,6 +453,11 @@ static __always_inline void spin_unlock_irq(spinlock_t= *lock) raw_spin_unlock_irq(&lock->rlock); } =20 +static __always_inline void spin_unlock_irq_enable(spinlock_t *lock) +{ + raw_spin_unlock_irq_enable(&lock->rlock); +} + static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsig= ned long flags) { raw_spin_unlock_irqrestore(&lock->rlock, flags); @@ -421,6 +478,11 @@ static __always_inline int spin_trylock_irq(spinlock_t= *lock) raw_spin_trylock_irqsave(spinlock_check(lock), flags); \ }) =20 +static __always_inline int spin_trylock_irq_disable(spinlock_t *lock) +{ + return raw_spin_trylock_irq_disable(&lock->rlock); +} + /** * spin_is_locked() - Check whether a spinlock is locked. * @lock: Pointer to the spinlock. diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_= smp.h index 9ecb0ab504e32..92532103b9eaa 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -28,6 +28,8 @@ _raw_spin_lock_nest_lock(raw_spinlock_t *lock, struct loc= kdep_map *map) void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock) __acquires(lock); void __lockfunc _raw_spin_lock_irq(raw_spinlock_t *lock) __acquires(lock); +void __lockfunc _raw_spin_lock_irq_disable(raw_spinlock_t *lock) + __acquires(lock); =20 unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock) __acquires(lock); @@ -39,6 +41,7 @@ int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock); void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) __releases(lock); void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) __releases(lock); void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) __releases(lock= ); +void __lockfunc _raw_spin_unlock_irq_enable(raw_spinlock_t *lock) __releas= es(lock); void __lockfunc _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) __releases(lock); @@ -55,6 +58,11 @@ _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsign= ed long flags) #define _raw_spin_lock_irq(lock) __raw_spin_lock_irq(lock) #endif =20 +/* Use the same config as spin_lock_irq() temporarily. */ +#ifdef CONFIG_INLINE_SPIN_LOCK_IRQ +#define _raw_spin_lock_irq_disable(lock) __raw_spin_lock_irq_disable(lock) +#endif + #ifdef CONFIG_INLINE_SPIN_LOCK_IRQSAVE #define _raw_spin_lock_irqsave(lock) __raw_spin_lock_irqsave(lock) #endif @@ -79,6 +87,11 @@ _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsign= ed long flags) #define _raw_spin_unlock_irq(lock) __raw_spin_unlock_irq(lock) #endif =20 +/* Use the same config as spin_unlock_irq() temporarily. */ +#ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQ +#define _raw_spin_unlock_irq_enable(lock) __raw_spin_unlock_irq_enable(loc= k) +#endif + #ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE #define _raw_spin_unlock_irqrestore(lock, flags) __raw_spin_unlock_irqrest= ore(lock, flags) #endif @@ -120,6 +133,13 @@ static inline void __raw_spin_lock_irq(raw_spinlock_t = *lock) LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); } =20 +static inline void __raw_spin_lock_irq_disable(raw_spinlock_t *lock) +{ + local_interrupt_disable(); + spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); + LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); +} + static inline void __raw_spin_lock_bh(raw_spinlock_t *lock) { __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); @@ -160,6 +180,13 @@ static inline void __raw_spin_unlock_irq(raw_spinlock_= t *lock) preempt_enable(); } =20 +static inline void __raw_spin_unlock_irq_enable(raw_spinlock_t *lock) +{ + spin_release(&lock->dep_map, _RET_IP_); + do_raw_spin_unlock(lock); + local_interrupt_enable(); +} + static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock) { spin_release(&lock->dep_map, _RET_IP_); diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_u= p.h index 819aeba1c87e6..d02a73671713b 100644 --- a/include/linux/spinlock_api_up.h +++ b/include/linux/spinlock_api_up.h @@ -36,6 +36,9 @@ #define __LOCK_IRQ(lock) \ do { local_irq_disable(); __LOCK(lock); } while (0) =20 +#define __LOCK_IRQ_DISABLE(lock) \ + do { local_interrupt_disable(); __LOCK(lock); } while (0) + #define __LOCK_IRQSAVE(lock, flags) \ do { local_irq_save(flags); __LOCK(lock); } while (0) =20 @@ -52,6 +55,9 @@ #define __UNLOCK_IRQ(lock) \ do { local_irq_enable(); __UNLOCK(lock); } while (0) =20 +#define __UNLOCK_IRQ_ENABLE(lock) \ + do { __UNLOCK(lock); local_interrupt_enable(); } while (0) + #define __UNLOCK_IRQRESTORE(lock, flags) \ do { local_irq_restore(flags); __UNLOCK(lock); } while (0) =20 @@ -64,6 +70,7 @@ #define _raw_read_lock_bh(lock) __LOCK_BH(lock) #define _raw_write_lock_bh(lock) __LOCK_BH(lock) #define _raw_spin_lock_irq(lock) __LOCK_IRQ(lock) +#define _raw_spin_lock_irq_disable(lock) __LOCK_IRQ_DISABLE(lock) #define _raw_read_lock_irq(lock) __LOCK_IRQ(lock) #define _raw_write_lock_irq(lock) __LOCK_IRQ(lock) #define _raw_spin_lock_irqsave(lock, flags) __LOCK_IRQSAVE(lock, flags) @@ -80,6 +87,7 @@ #define _raw_write_unlock_bh(lock) __UNLOCK_BH(lock) #define _raw_read_unlock_bh(lock) __UNLOCK_BH(lock) #define _raw_spin_unlock_irq(lock) __UNLOCK_IRQ(lock) +#define _raw_spin_unlock_irq_enable(lock) __UNLOCK_IRQ_ENABLE(lock) #define _raw_read_unlock_irq(lock) __UNLOCK_IRQ(lock) #define _raw_write_unlock_irq(lock) __UNLOCK_IRQ(lock) #define _raw_spin_unlock_irqrestore(lock, flags) \ diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h index f6499c37157df..6ea08fafa6d7b 100644 --- a/include/linux/spinlock_rt.h +++ b/include/linux/spinlock_rt.h @@ -93,6 +93,11 @@ static __always_inline void spin_lock_irq(spinlock_t *lo= ck) rt_spin_lock(lock); } =20 +static __always_inline void spin_lock_irq_disable(spinlock_t *lock) +{ + rt_spin_lock(lock); +} + #define spin_lock_irqsave(lock, flags) \ do { \ typecheck(unsigned long, flags); \ @@ -116,6 +121,11 @@ static __always_inline void spin_unlock_irq(spinlock_t= *lock) rt_spin_unlock(lock); } =20 +static __always_inline void spin_unlock_irq_enable(spinlock_t *lock) +{ + rt_spin_unlock(lock); +} + static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) { diff --git a/kernel/locking/spinlock.c b/kernel/locking/spinlock.c index 7685defd7c526..13f91117794fd 100644 --- a/kernel/locking/spinlock.c +++ b/kernel/locking/spinlock.c @@ -125,6 +125,21 @@ static void __lockfunc __raw_##op##_lock_bh(locktype##= _t *lock) \ */ BUILD_LOCK_OPS(spin, raw_spinlock); =20 +/* No rwlock_t variants for now, so just build this function by hand */ +static void __lockfunc __raw_spin_lock_irq_disable(raw_spinlock_t *lock) +{ + for (;;) { + preempt_disable(); + local_interrupt_disable(); + if (likely(do_raw_spin_trylock(lock))) + break; + local_interrupt_enable(); + preempt_enable(); + + arch_spin_relax(&lock->raw_lock); + } +} + #ifndef CONFIG_PREEMPT_RT BUILD_LOCK_OPS(read, rwlock); BUILD_LOCK_OPS(write, rwlock); @@ -172,6 +187,14 @@ noinline void __lockfunc _raw_spin_lock_irq(raw_spinlo= ck_t *lock) EXPORT_SYMBOL(_raw_spin_lock_irq); #endif =20 +#ifndef CONFIG_INLINE_SPIN_LOCK_IRQ +noinline void __lockfunc _raw_spin_lock_irq_disable(raw_spinlock_t *lock) +{ + __raw_spin_lock_irq_disable(lock); +} +EXPORT_SYMBOL_GPL(_raw_spin_lock_irq_disable); +#endif + #ifndef CONFIG_INLINE_SPIN_LOCK_BH noinline void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock) { @@ -204,6 +227,14 @@ noinline void __lockfunc _raw_spin_unlock_irq(raw_spin= lock_t *lock) EXPORT_SYMBOL(_raw_spin_unlock_irq); #endif =20 +#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQ +noinline void __lockfunc _raw_spin_unlock_irq_enable(raw_spinlock_t *lock) +{ + __raw_spin_unlock_irq_enable(lock); +} +EXPORT_SYMBOL_GPL(_raw_spin_unlock_irq_enable); +#endif + #ifndef CONFIG_INLINE_SPIN_UNLOCK_BH noinline void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) { diff --git a/kernel/softirq.c b/kernel/softirq.c index 513b1945987cc..f7a2ff4d123be 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -88,6 +88,9 @@ EXPORT_PER_CPU_SYMBOL_GPL(hardirqs_enabled); EXPORT_PER_CPU_SYMBOL_GPL(hardirq_context); #endif =20 +DEFINE_PER_CPU(struct interrupt_disable_state, local_interrupt_disable_sta= te); +EXPORT_PER_CPU_SYMBOL_GPL(local_interrupt_disable_state); + /* * SOFTIRQ_OFFSET usage: * --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0012F218589 for ; Tue, 27 May 2025 22:23:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384621; cv=none; b=DusgAmJ868MnU5EHJxX1FfN995CqU+3xZt+5sIgy2Z7lxOTjhMm4GrnVcAWTseU+V7hDPVq/6ZgcOED5hxb8s8WrvvJeBudDPH7BhGg30R7abQ98oQsLK4xI49aWNcQRJGDbida0vNneVyMcZUq0Y0MwL/X/aZcmGGZZYW038AY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384621; c=relaxed/simple; bh=WuRaaqybfRPeiLskZLXWDyW7QCLvTpZbQA5M8p9JdIw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rgj630gpWjfgKoBVK5R6/RUwykbYjEPEo87yTqAiiOpwk/GOGnVqBzny5mA9p6+9c359RWv+LR/rtfV33BtdJ+T2qa7NK5XBZ2299N+mhyZQ99L7Wy9t14Op5/a2W4Zi8qByxGrq+3BsM6YD+uT84qC4ep48H1v5hvWYylEaWEc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=KAiFENva; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="KAiFENva" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384618; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t1rQPARK6TWjeLuQXJrGFSHiI6XMO4wCvWlCuqSRr80=; b=KAiFENvavrrudPRcDPPF4ZslU4FooBb8SC6cNkNoq4DqtYgPkQe4xKrS36w1tO3tF9P++d BMxDF6gmnyh+NXB/WzV7eB353m+mvu8RT/E02wKOlbQJu6hAFed6fLKb8kWjBl9eDbnUPW ohdXyTayWqmp6FWAgJQMvQ3kwQ/uJbM= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-7-sYmUbs5GNP6CvetJhhOIYg-1; Tue, 27 May 2025 18:23:35 -0400 X-MC-Unique: sYmUbs5GNP6CvetJhhOIYg-1 X-Mimecast-MFC-AGG-ID: sYmUbs5GNP6CvetJhhOIYg_1748384613 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 36DC819560BC; Tue, 27 May 2025 22:23:33 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F09DF1956095; Tue, 27 May 2025 22:23:29 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Wedson Almeida Filho , FUJITA Tomonori , Greg Kroah-Hartman , Xiangfei Ding Subject: [RFC RESEND v10 04/14] rust: Introduce interrupt module Date: Tue, 27 May 2025 18:21:45 -0400 Message-ID: <20250527222254.565881-5-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 This introduces a module for dealing with interrupt-disabled contexts, including the ability to enable and disable interrupts along with the ability to annotate functions as expecting that IRQs are already disabled on the local CPU. [Boqun: This is based on Lyude's work on interrupt disable abstraction, I port to the new local_interrupt_disable() mechanism to make it work as a guard type. I cannot even take the credit of this design, since Lyude also brought up the same idea in zulip. Anyway, this is only for POC purpose, and of course all bugs are mine] Signed-off-by: Lyude Paul Co-Developed-by: Boqun Feng Signed-off-by: Boqun Feng Reviewed-by: Benno Lossin --- V10: * Fix documentation typos Signed-off-by: Lyude Paul --- rust/helpers/helpers.c | 1 + rust/helpers/interrupt.c | 18 +++++++++ rust/kernel/interrupt.rs | 83 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 4 files changed, 103 insertions(+) create mode 100644 rust/helpers/interrupt.c create mode 100644 rust/kernel/interrupt.rs diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 80785b1e7a63e..ddf812af3aff8 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -17,6 +17,7 @@ #include "dma.c" #include "err.c" #include "fs.c" +#include "interrupt.c" #include "io.c" #include "jump_label.c" #include "kunit.c" diff --git a/rust/helpers/interrupt.c b/rust/helpers/interrupt.c new file mode 100644 index 0000000000000..f2380dd461ca5 --- /dev/null +++ b/rust/helpers/interrupt.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_local_interrupt_disable(void) +{ + local_interrupt_disable(); +} + +void rust_helper_local_interrupt_enable(void) +{ + local_interrupt_enable(); +} + +bool rust_helper_irqs_disabled(void) +{ + return irqs_disabled(); +} diff --git a/rust/kernel/interrupt.rs b/rust/kernel/interrupt.rs new file mode 100644 index 0000000000000..e66aa85f79940 --- /dev/null +++ b/rust/kernel/interrupt.rs @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Interrupt controls +//! +//! This module allows Rust code to annotate areas of code where local pro= cessor interrupts should +//! be disabled, along with actually disabling local processor interrupts. +//! +//! # =E2=9A=A0=EF=B8=8F Warning! =E2=9A=A0=EF=B8=8F +//! +//! The usage of this module can be more complicated than meets the eye, e= specially surrounding +//! [preemptible kernels]. It's recommended to take care when using the fu= nctions and types defined +//! here and familiarize yourself with the various documentation we have b= efore using them, along +//! with the various documents we link to here. +//! +//! # Reading material +//! +//! - [Software interrupts and realtime (LWN)](https://lwn.net/Articles/52= 0076) +//! +//! [preemptible kernels]: https://www.kernel.org/doc/html/latest/locking/= preempt-locking.html + +use bindings; +use kernel::types::NotThreadSafe; + +/// A guard that represents local processor interrupt disablement on preem= ptible kernels. +/// +/// [`LocalInterruptDisabled`] is a guard type that represents that local = processor interrupts have +/// been disabled on a preemptible kernel. +/// +/// Certain functions take an immutable reference of [`LocalInterruptDisab= led`] in order to require +/// that they may only be run in local-interrupt-disabled contexts on pree= mptible kernels. +/// +/// This is a marker type; it has no size, and is simply used as a compile= -time guarantee that local +/// processor interrupts interrupts are disabled on preemptible kernels. N= ote that no guarantees +/// about the state of interrupts are made by this type on non-preemptible= kernels. +/// +/// # Invariants +/// +/// Local processor interrupts are disabled on preemptible kernels for as = long as an object of this +/// type exists. +pub struct LocalInterruptDisabled(NotThreadSafe); + +/// Disable local processor interrupts on a preemptible kernel. +/// +/// This function disables local processor interrupts on a preemptible ker= nel, and returns a +/// [`LocalInterruptDisabled`] token as proof of this. On non-preemptible = kernels, this function is +/// a no-op. +/// +/// **Usage of this function is discouraged** unless you are absolutely su= re you know what you are +/// doing, as kernel interfaces for rust that deal with interrupt state wi= ll typically handle local +/// processor interrupt state management on their own and managing this by= hand is quite error +/// prone. +pub fn local_interrupt_disable() -> LocalInterruptDisabled { + // SAFETY: It's always safe to call `local_interrupt_disable()`. + unsafe { bindings::local_interrupt_disable() }; + + LocalInterruptDisabled(NotThreadSafe) +} + +impl Drop for LocalInterruptDisabled { + fn drop(&mut self) { + // SAFETY: Per type invariants, a `local_interrupt_disable()` must= be called to create this + // object, hence call the corresponding `local_interrupt_enable()`= is safe. + unsafe { bindings::local_interrupt_enable() }; + } +} + +impl LocalInterruptDisabled { + const ASSUME_DISABLED: &'static LocalInterruptDisabled =3D &LocalInter= ruptDisabled(NotThreadSafe); + + /// Assume that local processor interrupts are disabled on preemptible= kernels. + /// + /// This can be used for annotating code that is known to be run in co= ntexts where local + /// processor interrupts are disabled on preemptible kernels. It makes= no changes to the local + /// interrupt state on its own. + /// + /// # Safety + /// + /// For the whole life `'a`, local interrupts must be disabled on pree= mptible kernels. This + /// could be a context like for example, an interrupt handler. + pub unsafe fn assume_disabled<'a>() -> &'a LocalInterruptDisabled { + Self::ASSUME_DISABLED + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 6e9287136cac7..cd5edccafdad7 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -68,6 +68,7 @@ pub mod firmware; pub mod fs; pub mod init; +pub mod interrupt; pub mod io; pub mod ioctl; pub mod jump_label; --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9210218AC1 for ; Tue, 27 May 2025 22:23:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384626; cv=none; b=nU/AkgY+NJozUFvGC0xpDOHh+VRbVGHzIk6hEDWf82yc9jRG17oPacB9jTxZ9chmstVah2wLV+0oMGtI/lc9wzPxwoWc/XUP2pIgpvQiPpD5no4b7mrYaAmu2FVfnmjMuMLHPrrWzLFDe4UzYV11u2JkWnWWxI/nkYB7jJ4hi+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384626; c=relaxed/simple; bh=K3f/Ch1Couu5LNaqpSCdAgoZ/LY5pt6YLuj7P4argIo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uN4vtFhocMnpVIJ8YkcCo2ionGCiGNE694VDBGUwCSmh+AkxdO3h+2X8uAnTJfI1EoI6J85TWJa0Vr6CIFJSk24z/WNNR2qjFKRAMukGELF7LiMsOo1PYZltZH6bJG8jiibCrCNWmkxDPCIoNy8/Swqa9qG370salq+HJxxS/xs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=IoIUfaQN; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IoIUfaQN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384624; 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=k03BW5qAYRVw2eHI73IwqIEj48PZjRj/Cpc91vy3rNU=; b=IoIUfaQN06GxrC2LSdQPYUCP4xiRPk9lzDKiVjwtMgNtHxX7HnWhymWA8CfeUZTJg3XaWj hsiM4yZxyWtWPhIU8qgWpxNrSyRSoMYEovC4l3WYILAmEC33pSKSwyWzU8WIPP0SCIHkOV FniSJ1nTs67ydrfZbfAGOKlZY3aTq9M= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-618-2__u91S6Oym-tngleTRM8Q-1; Tue, 27 May 2025 18:23:40 -0400 X-MC-Unique: 2__u91S6Oym-tngleTRM8Q-1 X-Mimecast-MFC-AGG-ID: 2__u91S6Oym-tngleTRM8Q_1748384618 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F35AF180036D; Tue, 27 May 2025 22:23:37 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6642319560AB; Tue, 27 May 2025 22:23:34 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 05/14] rust: helper: Add spin_{un,}lock_irq_{enable,disable}() helpers Date: Tue, 27 May 2025 18:21:46 -0400 Message-ID: <20250527222254.565881-6-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" From: Boqun Feng spin_lock_irq_disable() and spin_unlock_irq_enable() are inline functions, to use them in Rust, helpers are introduced. This is for interrupt disabling lock abstraction in Rust. Signed-off-by: Boqun Feng Signed-off-by: Lyude Paul --- rust/helpers/spinlock.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rust/helpers/spinlock.c b/rust/helpers/spinlock.c index 42c4bf01a23e4..d4e61057c2a7a 100644 --- a/rust/helpers/spinlock.c +++ b/rust/helpers/spinlock.c @@ -35,3 +35,18 @@ void rust_helper_spin_assert_is_held(spinlock_t *lock) { lockdep_assert_held(lock); } + +void rust_helper_spin_lock_irq_disable(spinlock_t *lock) +{ + spin_lock_irq_disable(lock); +} + +void rust_helper_spin_unlock_irq_enable(spinlock_t *lock) +{ + spin_unlock_irq_enable(lock); +} + +int rust_helper_spin_trylock_irq_disable(spinlock_t *lock) +{ + return spin_trylock_irq_disable(lock); +} --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3012E218EBA for ; Tue, 27 May 2025 22:23:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384630; cv=none; b=gjJAYp9F5Yhm7KaZP9ItUqJf9Hnsf6z5ywQAL+rYAK5XoWIb8vakQpuFDS0lsAJ4RmRHUxC9KYtlnM39qEhTdoXPDMYJ9oeKrKDAz3GE4N0n3HGuWk8xd7S5Inao2QI1dA7vrq9dvGctEHFFfpOVNLwzCsgfCBh7I6cU5D9q4OU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384630; c=relaxed/simple; bh=ePu8BVwWz4CcP33RkJL//NtqsBk8F8/EH3/wsjdTZOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CieFHaus14i1tUBRqEpLWjs0K7LKR2fOwrivNeZvFHm0pYce7kJWGMpUEQPtxAB3CQ5bm0fkOhosoZ6xxFVUv3OtC0pRnsv1okqOwPoXbmfWQnf2LeCK8lSchdEIULUzRBuFza6fbxPLdbFQbVRCz7tfAkPWNH/f0e8R0zfT8mA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CUW+NwCw; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CUW+NwCw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384627; 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=xbqhgC3A/TbOraVkQUQ0RN7Suk368O2IC9TDHM6wKkg=; b=CUW+NwCwoupQZBkFXp7+40btAPD/1TIlqFj7D12cuHl+Hwmc1MEh9OAQIlKm8UgUtbRNP/ FyyvUUYoieCSm3gwOfBmbLwJp8Eb9KiNRsUwcVgiYWJW9ESXwbCeHRpmw+7mQt1jlaeVsi 2gQpxcSeuuPtHOiTmBlDfcRKfJQ8hcM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-55-EK0MF0dQPgGJFB6nue86OQ-1; Tue, 27 May 2025 18:23:45 -0400 X-MC-Unique: EK0MF0dQPgGJFB6nue86OQ-1 X-Mimecast-MFC-AGG-ID: EK0MF0dQPgGJFB6nue86OQ_1748384623 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 90B6C1800258; Tue, 27 May 2025 22:23:43 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 82F741956095; Tue, 27 May 2025 22:23:39 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Mitchell Levy , Wedson Almeida Filho Subject: [RFC RESEND v10 06/14] rust: sync: Add SpinLockIrq Date: Tue, 27 May 2025 18:21:47 -0400 Message-ID: <20250527222254.565881-7-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Content-Type: text/plain; charset="utf-8" A variant of SpinLock that is expected to be used in noirq contexts, so lock() will disable interrupts and unlock() (i.e. `Guard::drop()` will undo the interrupt disable. [Boqun: Port to use spin_lock_irq_disable() and spin_unlock_irq_enable()] Signed-off-by: Lyude Paul Co-Developed-by: Boqun Feng Signed-off-by: Boqun Feng --- V10: * Also add support to GlobalLock * Documentation fixes from Dirk Signed-off-by: Lyude Paul --- rust/kernel/sync.rs | 4 +- rust/kernel/sync/lock/global.rs | 3 + rust/kernel/sync/lock/spinlock.rs | 142 ++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 36a7190155833..07e83992490d5 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -20,7 +20,9 @@ pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult}; pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBac= kend, GlobalLockedBy}; pub use lock::mutex::{new_mutex, Mutex, MutexGuard}; -pub use lock::spinlock::{new_spinlock, SpinLock, SpinLockGuard}; +pub use lock::spinlock::{ + new_spinlock, new_spinlock_irq, SpinLock, SpinLockGuard, SpinLockIrq, = SpinLockIrqGuard, +}; pub use locked_by::LockedBy; =20 /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index d65f94b5caf26..47e200b750c1d 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -299,4 +299,7 @@ macro_rules! global_lock_inner { (backend SpinLock) =3D> { $crate::sync::lock::spinlock::SpinLockBackend }; + (backend SpinLockIrq) =3D> { + $crate::sync::lock::spinlock::SpinLockIrqBackend + }; } diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spin= lock.rs index d7be38ccbdc7d..a1d76184a5bb4 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -139,3 +139,145 @@ unsafe fn assert_is_held(ptr: *mut Self::State) { unsafe { bindings::spin_assert_is_held(ptr) } } } + +/// Creates a [`SpinLockIrq`] initialiser with the given name and a newly-= created lock class. +/// +/// It uses the name if one is given, otherwise it generates one based on = the file name and line +/// number. +#[macro_export] +macro_rules! new_spinlock_irq { + ($inner:expr $(, $name:literal)? $(,)?) =3D> { + $crate::sync::SpinLockIrq::new( + $inner, $crate::optional_name!($($name)?), $crate::static_lock= _class!()) + }; +} +pub use new_spinlock_irq; + +/// A spinlock that may be acquired when local processor interrupts are di= sabled. +/// +/// This is a version of [`SpinLock`] that can only be used in contexts wh= ere interrupts for the +/// local CPU are disabled. It can be acquired in two ways: +/// +/// - Using [`lock()`] like any other type of lock, in which case the bind= ings will modify the +/// interrupt state to ensure that local processor interrupts remain dis= abled for at least as long +/// as the [`SpinLockIrqGuard`] exists. +/// - Using [`lock_with()`] in contexts where a [`LocalInterruptDisabled`]= token is present and +/// local processor interrupts are already known to be disabled, in whic= h case the local interrupt +/// state will not be touched. This method should be preferred if a [`Lo= calInterruptDisabled`] +/// token is present in the scope. +/// +/// For more info on spinlocks, see [`SpinLock`]. For more information on = interrupts, +/// [see the interrupt module](kernel::interrupt). +/// +/// # Examples +/// +/// The following example shows how to declare, allocate initialise and ac= cess a struct (`Example`) +/// that contains an inner struct (`Inner`) that is protected by a spinloc= k that requires local +/// processor interrupts to be disabled. +/// +/// ``` +/// use kernel::sync::{new_spinlock_irq, SpinLockIrq}; +/// +/// struct Inner { +/// a: u32, +/// b: u32, +/// } +/// +/// #[pin_data] +/// struct Example { +/// #[pin] +/// c: SpinLockIrq, +/// #[pin] +/// d: SpinLockIrq, +/// } +/// +/// impl Example { +/// fn new() -> impl PinInit { +/// pin_init!(Self { +/// c <- new_spinlock_irq!(Inner { a: 0, b: 10 }), +/// d <- new_spinlock_irq!(Inner { a: 20, b: 30 }), +/// }) +/// } +/// } +/// +/// // Allocate a boxed `Example` +/// let e =3D KBox::pin_init(Example::new(), GFP_KERNEL)?; +/// +/// // Accessing an `Example` from a context where interrupts may not be d= isabled already. +/// let c_guard =3D e.c.lock(); // interrupts are disabled now, +1 interru= pt disable refcount +/// let d_guard =3D e.d.lock(); // no interrupt state change, +1 interrupt= disable refcount +/// +/// assert_eq!(c_guard.a, 0); +/// assert_eq!(c_guard.b, 10); +/// assert_eq!(d_guard.a, 20); +/// assert_eq!(d_guard.b, 30); +/// +/// drop(c_guard); // Dropping c_guard will not re-enable interrupts just = yet, since d_guard is +/// // still in scope. +/// drop(d_guard); // Last interrupt disable reference dropped here, so in= terrupts are re-enabled +/// // now +/// # Ok::<(), Error>(()) +/// ``` +/// +/// [`lock()`]: SpinLockIrq::lock +/// [`lock_with()`]: SpinLockIrq::lock_with +pub type SpinLockIrq =3D super::Lock; + +/// A kernel `spinlock_t` lock backend that is acquired in interrupt disab= led contexts. +pub struct SpinLockIrqBackend; + +/// A [`Guard`] acquired from locking a [`SpinLockIrq`] using [`lock()`]. +/// +/// This is simply a type alias for a [`Guard`] returned from locking a [`= SpinLockIrq`] using +/// [`lock_with()`]. It will unlock the [`SpinLockIrq`] and decrement the = local processor's +/// interrupt disablement refcount upon being dropped. +/// +/// [`Guard`]: super::Guard +/// [`lock()`]: SpinLockIrq::lock +/// [`lock_with()`]: SpinLockIrq::lock_with +pub type SpinLockIrqGuard<'a, T> =3D super::Guard<'a, T, SpinLockIrqBacken= d>; + +// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclus= ion. `relock` uses the +// default implementation that always calls the same locking method. +unsafe impl super::Backend for SpinLockIrqBackend { + type State =3D bindings::spinlock_t; + type GuardState =3D (); + + unsafe fn init( + ptr: *mut Self::State, + name: *const crate::ffi::c_char, + key: *mut bindings::lock_class_key, + ) { + // SAFETY: The safety requirements ensure that `ptr` is valid for = writes, and `name` and + // `key` are valid for read indefinitely. + unsafe { bindings::__spin_lock_init(ptr, name, key) } + } + + unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { + // SAFETY: The safety requirements of this function ensure that `p= tr` points to valid + // memory, and that it has been initialised before. + unsafe { bindings::spin_lock_irq_disable(ptr) } + } + + unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardStat= e) { + // SAFETY: The safety requirements of this function ensure that `p= tr` is valid and that the + // caller is the owner of the spinlock. + unsafe { bindings::spin_unlock_irq_enable(ptr) } + } + + unsafe fn try_lock(ptr: *mut Self::State) -> Option { + // SAFETY: The `ptr` pointer is guaranteed to be valid and initial= ized before use. + let result =3D unsafe { bindings::spin_trylock_irq_disable(ptr) }; + + if result !=3D 0 { + Some(()) + } else { + None + } + } + + unsafe fn assert_is_held(ptr: *mut Self::State) { + // SAFETY: The `ptr` pointer is guaranteed to be valid and initial= ized before use. + unsafe { bindings::spin_assert_is_held(ptr) } + } +} --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D3C42219A9B for ; Tue, 27 May 2025 22:23:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384638; cv=none; b=MRyYhkvOGaMX7rdt/fpfNPKn6PDq0QZ9LsbtP11la/xyfKD8DzcSbINdFqnOmhzR9sujphBLnryOgae/evwNqgQm41aYeKrJ3rZ5iy+DMCbpJAHNa+Nbb8rxi2e88pxWMlJhlWmoFnkgesycmzZJCPaMBskklM67Fhi95RYYO6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384638; c=relaxed/simple; bh=iyN9np/xVFIv3Eksb2k4W4/BeVrtDJGJ8iQYqgl/KGI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NMMi3wzHmTMYsoFm1tUrt6wSJvE0KztJCAGlFEkyiqDbNzxDLtTcJRZenHChIv0mziper6hmN3jWu3bvgnzZx1lUX8ZZGRaB5sLho7hxqUG8CClhDdDe/F3Ow7kRRFtHzdfLS6EmXTsGP09USlDRshQFg7p2lSCcWO8QnE9Zg6w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Q4w4KJ//; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Q4w4KJ//" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384635; 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=n4FONPi+3zPFCa0oB0I1LXHAYQTljuOdTTgCI7xxKTw=; b=Q4w4KJ//jDuJ/cZNHws0dOWUKRWQ9axJsxWqxi2a2av59IIHLltUDtOACYOgv1FoSp9A8i +Z5knBsNT/7HpTG0az7v9uw2QxtrBOkTG493mhT3Juyl+trlfQ5zvCTodSQQ1b84TfF/2U 01di3EDClWWxOc99Nd8s5fPcVmNd5NA= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-374-oV1tzUtWOTKKuWTJ4n4pDw-1; Tue, 27 May 2025 18:23:50 -0400 X-MC-Unique: oV1tzUtWOTKKuWTJ4n4pDw-1 X-Mimecast-MFC-AGG-ID: oV1tzUtWOTKKuWTJ4n4pDw_1748384628 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 29D601800361; Tue, 27 May 2025 22:23:48 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BD2451956095; Tue, 27 May 2025 22:23:44 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 07/14] rust: sync: Introduce lock::Backend::Context Date: Tue, 27 May 2025 18:21:48 -0400 Message-ID: <20250527222254.565881-8-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Content-Type: text/plain; charset="utf-8" Now that we've introduced an `InterruptDisabled` token for marking contexts in which IRQs are disabled, we can have a way to avoid `SpinLockIrq` disabling interrupts if the interrupts have already been disabled. Basically, a `SpinLockIrq` should work like a `SpinLock` if interrupts are disabled. So a function: (&'a SpinLockIrq, &'a InterruptDisabled) -> Guard<'a, .., SpinLockBackend> makes senses. Note that due to `Guard` and `InterruptDisabled` having the same lifetime, interrupts cannot be enabled while the Guard exists. Add a `lock_with()` interface for `Lock`, and an associate type of `Backend` to describe the context. Signed-off-by: Lyude Paul Co-Developed-by: Boqun Feng Signed-off-by: Boqun Feng --- V10: - Fix typos - Dirk Signed-off-by: Lyude Paul --- rust/kernel/sync/lock.rs | 12 +++++++++++- rust/kernel/sync/lock/mutex.rs | 1 + rust/kernel/sync/lock/spinlock.rs | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index e82fa5be289c1..f94ed1a825f6d 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -44,6 +44,9 @@ pub unsafe trait Backend { /// [`unlock`]: Backend::unlock type GuardState; =20 + /// The context which can be provided to acquire the lock with a diffe= rent backend. + type Context<'a>; + /// Initialises the lock. /// /// # Safety @@ -163,8 +166,15 @@ pub unsafe fn from_raw<'a>(ptr: *mut B::State) -> &'a = Self { } =20 impl Lock { + /// Acquires the lock with the given context and gives the caller acce= ss to the data protected + /// by it. + pub fn lock_with<'a>(&'a self, _context: B::Context<'a>) -> Guard<'a, = T, B> { + todo!() + } + /// Acquires the lock and gives the caller access to the data protecte= d by it. - pub fn lock(&self) -> Guard<'_, T, B> { + #[inline] + pub fn lock<'a>(&'a self) -> Guard<'a, T, B> { // SAFETY: The constructor of the type calls `init`, so the existe= nce of the object proves // that `init` was called. let state =3D unsafe { B::lock(self.state.get()) }; diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs index 581cee7ab842a..be1e2e18cf42d 100644 --- a/rust/kernel/sync/lock/mutex.rs +++ b/rust/kernel/sync/lock/mutex.rs @@ -101,6 +101,7 @@ macro_rules! new_mutex { unsafe impl super::Backend for MutexBackend { type State =3D bindings::mutex; type GuardState =3D (); + type Context<'a> =3D (); =20 unsafe fn init( ptr: *mut Self::State, diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spin= lock.rs index a1d76184a5bb4..f3dac0931f6a2 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -3,6 +3,7 @@ //! A kernel spinlock. //! //! This module allows Rust code to use the kernel's `spinlock_t`. +use crate::interrupt::LocalInterruptDisabled; =20 /// Creates a [`SpinLock`] initialiser with the given name and a newly-cre= ated lock class. /// @@ -100,6 +101,7 @@ macro_rules! new_spinlock { unsafe impl super::Backend for SpinLockBackend { type State =3D bindings::spinlock_t; type GuardState =3D (); + type Context<'a> =3D (); =20 unsafe fn init( ptr: *mut Self::State, @@ -242,6 +244,7 @@ macro_rules! new_spinlock_irq { unsafe impl super::Backend for SpinLockIrqBackend { type State =3D bindings::spinlock_t; type GuardState =3D (); + type Context<'a> =3D &'a LocalInterruptDisabled; =20 unsafe fn init( ptr: *mut Self::State, --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A5AC217F53 for ; Tue, 27 May 2025 22:24:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384643; cv=none; b=tqkWRMVYl8Nj76NShK0CWVlR5CN39glL/9uWRhYBqOBe4inBsmA2Kk9k9PBT8SerVMpoq8rPt8IWx8vQOs4c+d5pxYDrs4XF/6EU4WYFy0jA9E4COCOqGhR4PD2DOzxMTLih/nmg4+qUcRI+kCPGUM9cgwG7HHfAaASzwzeRW4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384643; c=relaxed/simple; bh=K/kCRV+vYD+2YO+oFslJP5wDdoaYlsm2sq9RCzg3FCs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U7mfaj2LFZGuWPAFWq+Cecds4X0FIQ2fnWehM6k98XP9R0kGsKACnuSlnao4N9gkeM6dp172iZSUO8eBaFLzG/qEW/OGujqXGW0j9w77GNI9Nbt3qlD48R/GT/g+5PuaMnokN4bT44+ZPtsyBc99/SQ0Ok80vZnAXurrDZG0wEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=IId2KlnO; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IId2KlnO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384640; 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=CBVPvFqpc4S6zyfnT4FHDRkMI9Y7cez+gb/r6f3/m84=; b=IId2KlnOFqyyp38MKbvH2mxCRYaDhqKVKCLfpUthqNQz3/hNzKmQCI3Zl7dp8bPr+GCPjN aPSqHR+c5IERTXQtIWFe8d+zIAAk+uQvk/soPUxVZ/yS2MVYMfwoSOctWDNAC8TrpUIFKo nk6uJ+4VZidapWvZ0KxymVC3tOP61M4= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-88-hK8i15VGMhOLSlgzc6hpdQ-1; Tue, 27 May 2025 18:23:55 -0400 X-MC-Unique: hK8i15VGMhOLSlgzc6hpdQ-1 X-Mimecast-MFC-AGG-ID: hK8i15VGMhOLSlgzc6hpdQ_1748384633 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0CC99195608B; Tue, 27 May 2025 22:23:53 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 40DF030001B0; Tue, 27 May 2025 22:23:49 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 08/14] rust: sync: lock: Add `Backend::BackendInContext` Date: Tue, 27 May 2025 18:21:49 -0400 Message-ID: <20250527222254.565881-9-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" From: Boqun Feng `SpinLock`'s backend can be used for `SpinLockIrq`, if the interrupts are disabled. And it actually provides performance gains since interrupts are not needed to be disabled anymore. So add `Backend::BackendInContext` to describe the case where one backend can be used for another. Use it to implement the `lock_with()` so that `SpinLockIrq` can avoid disabling interrupts by using `SpinLock`'s backend. Signed-off-by: Boqun Feng Co-authored-by: Lyude Paul --- V10: * Fix typos - Dirk/Lyude * Since we're adding support for context locks to GlobalLock as well, let's also make sure to cover try_lock while we're at it and add try_lock_with * Add a private function as_lock_in_context() for handling casting from a Lock to Lock so we don't have to duplicate safety comments Signed-off-by: Lyude Paul --- rust/kernel/sync/lock.rs | 61 ++++++++++++++++++++++++++++++- rust/kernel/sync/lock/mutex.rs | 1 + rust/kernel/sync/lock/spinlock.rs | 41 +++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index f94ed1a825f6d..64a7a78ea2dde 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -30,10 +30,15 @@ /// is owned, that is, between calls to [`lock`] and [`unlock`]. /// - Implementers must also ensure that [`relock`] uses the same locking = method as the original /// lock operation. +/// - Implementers must ensure if [`BackendInContext`] is a [`Backend`], i= t's safe to acquire the +/// lock under the [`Context`], the [`State`] of two backends must be th= e same. /// /// [`lock`]: Backend::lock /// [`unlock`]: Backend::unlock /// [`relock`]: Backend::relock +/// [`BackendInContext`]: Backend::BackendInContext +/// [`Context`]: Backend::Context +/// [`State`]: Backend::State pub unsafe trait Backend { /// The state required by the lock. type State; @@ -47,6 +52,9 @@ pub unsafe trait Backend { /// The context which can be provided to acquire the lock with a diffe= rent backend. type Context<'a>; =20 + /// The alternative backend we can use if a [`Context`](Backend::Conte= xt) is provided. + type BackendInContext: Sized; + /// Initialises the lock. /// /// # Safety @@ -166,10 +174,59 @@ pub unsafe fn from_raw<'a>(ptr: *mut B::State) -> &'a= Self { } =20 impl Lock { + /// Casts the lock as a `Lock`. + fn as_lock_in_context<'a>( + &'a self, + _context: B::Context<'a>, + ) -> &'a Lock + where + B::BackendInContext: Backend, + { + // SAFETY: + // - Per the safety guarantee of `Backend`, if `B::BackendInContex= t` and `B` should + // have the same state, the layout of the lock is the same so it= 's safe to convert one to + // another. + // - The caller provided `B::Context<'a>`, so it is safe to recast= and return this lock. + unsafe { &*(self as *const _ as *const Lock) } + } + /// Acquires the lock with the given context and gives the caller acce= ss to the data protected /// by it. - pub fn lock_with<'a>(&'a self, _context: B::Context<'a>) -> Guard<'a, = T, B> { - todo!() + pub fn lock_with<'a>(&'a self, context: B::Context<'a>) -> Guard<'a, T= , B::BackendInContext> + where + B::BackendInContext: Backend, + { + let lock =3D self.as_lock_in_context(context); + + // SAFETY: The constructor of the type calls `init`, so the existe= nce of the object proves + // that `init` was called. Plus the safety guarantee of `Backend` = guarantees that `B::State` + // is the same as `B::BackendInContext::State`, also it's safe to = call another backend + // because there is `B::Context<'a>`. + let state =3D unsafe { B::BackendInContext::lock(lock.state.get())= }; + + // SAFETY: The lock was just acquired. + unsafe { Guard::new(lock, state) } + } + + /// Tries to acquire the lock with the given context. + /// + /// Returns a guard that can be used to access the data protected by t= he lock if successful. + pub fn try_lock_with<'a>( + &'a self, + context: B::Context<'a>, + ) -> Option> + where + B::BackendInContext: Backend, + { + let lock =3D self.as_lock_in_context(context); + + // SAFETY: The constructor of the type calls `init`, so the existe= nce of the object proves + // that `init` was called. Plus the safety guarantee of `Backend` = guarantees that `B::State` + // is the same as `B::BackendInContext::State`, also it's safe to = call another backend + // because there is `B::Context<'a>`. + unsafe { + B::BackendInContext::try_lock(lock.state.get()).map(|state| Gu= ard::new(lock, state)) + } } =20 /// Acquires the lock and gives the caller access to the data protecte= d by it. diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs index be1e2e18cf42d..662a530750703 100644 --- a/rust/kernel/sync/lock/mutex.rs +++ b/rust/kernel/sync/lock/mutex.rs @@ -102,6 +102,7 @@ unsafe impl super::Backend for MutexBackend { type State =3D bindings::mutex; type GuardState =3D (); type Context<'a> =3D (); + type BackendInContext =3D (); =20 unsafe fn init( ptr: *mut Self::State, diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spin= lock.rs index f3dac0931f6a2..a2d60d5da5e11 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -102,6 +102,7 @@ unsafe impl super::Backend for SpinLockBackend { type State =3D bindings::spinlock_t; type GuardState =3D (); type Context<'a> =3D (); + type BackendInContext =3D (); =20 unsafe fn init( ptr: *mut Self::State, @@ -221,6 +222,45 @@ macro_rules! new_spinlock_irq { /// # Ok::<(), Error>(()) /// ``` /// +/// The next example demonstrates locking a [`SpinLockIrq`] using [`lock_w= ith()`] in a function +/// which can only be called when local processor interrupts are already d= isabled. +/// +/// ``` +/// use kernel::sync::{new_spinlock_irq, SpinLockIrq}; +/// use kernel::interrupt::*; +/// +/// struct Inner { +/// a: u32, +/// } +/// +/// #[pin_data] +/// struct Example { +/// #[pin] +/// inner: SpinLockIrq, +/// } +/// +/// impl Example { +/// fn new() -> impl PinInit { +/// pin_init!(Self { +/// inner <- new_spinlock_irq!(Inner { a: 20 }), +/// }) +/// } +/// } +/// +/// // Accessing an `Example` from a function that can only be called in n= o-interrupt contexts. +/// fn noirq_work(e: &Example, interrupt_disabled: &LocalInterruptDisabled= ) { +/// // Because we know interrupts are disabled from interrupt_disable,= we can skip toggling +/// // interrupt state using lock_with() and the provided token +/// assert_eq!(e.inner.lock_with(interrupt_disabled).a, 20); +/// } +/// +/// # let e =3D KBox::pin_init(Example::new(), GFP_KERNEL)?; +/// # let interrupt_guard =3D local_interrupt_disable(); +/// # noirq_work(&e, &interrupt_guard); +/// # +/// # Ok::<(), Error>(()) +/// ``` +/// /// [`lock()`]: SpinLockIrq::lock /// [`lock_with()`]: SpinLockIrq::lock_with pub type SpinLockIrq =3D super::Lock; @@ -245,6 +285,7 @@ unsafe impl super::Backend for SpinLockIrqBackend { type State =3D bindings::spinlock_t; type GuardState =3D (); type Context<'a> =3D &'a LocalInterruptDisabled; + type BackendInContext =3D SpinLockBackend; =20 unsafe fn init( ptr: *mut Self::State, --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D791421A928 for ; Tue, 27 May 2025 22:24:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384645; cv=none; b=MVw69Pk4oqm0U+iQdAzp8kRznqUJb+4McMfOHPtMAqmCXBnAUID1HP9ZfcvTT8qSYstu84aK2Bbx5pBr9IwrtirdMDQsJCqa4DyCWFgKf3AGrTrI6EFZlclr5KAr5xNgW83hM3D63Z9m4Z7KWSrm5PB8czfmvZihM6j8tB6HGH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384645; c=relaxed/simple; bh=PVaj8/EVXA1CeA9kqbXdBYiDwZpHxa8saR3Rd70C81A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k8Ds+TBE7g1hv0zmOT063UchbFmh0B3yauvfWE6i4tvoLgnBroZ2NCYgPnJZaVZdtOvMk+eFqNhxGr7Od1+6Q8O3maL4rZi08dXFi4uRFHQBehmvfj5J+N8ZF2NEEvuMSHLiYUjIfyu5fAvIYNFUVj8xB7SSpUCbMu+mt82U78c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=de9+jFYV; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="de9+jFYV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384642; 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=MjrbJaMYIn3bcpL9GAFqRs/9YheFIo7lqlBabeM9tMU=; b=de9+jFYVzyDOSQBWzkwtpPZfcjG4xl6uoRU8DDyOnXwEwzPs+BMJQ3sF09bNdT6Cp5vz0X kG54dltD8ZJxibsDgmwAw8QqZs2hxlAbymWNfcdVVD5SJmOqUBOFbO956O5RW0xKvW8jER RQyeiteD6YQEO6L/xyfYCBFP3YX2DCc= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-691-x69BTkSJMPiSeytzrnI4Aw-1; Tue, 27 May 2025 18:23:59 -0400 X-MC-Unique: x69BTkSJMPiSeytzrnI4Aw-1 X-Mimecast-MFC-AGG-ID: x69BTkSJMPiSeytzrnI4Aw_1748384637 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4940B195608C; Tue, 27 May 2025 22:23:57 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0C88630001B0; Tue, 27 May 2025 22:23:53 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 09/14] rust: sync: Add a lifetime parameter to lock::global::GlobalGuard Date: Tue, 27 May 2025 18:21:50 -0400 Message-ID: <20250527222254.565881-10-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" While a GlobalLock is always going to be static, in the case of locks with explicit backend contexts the GlobalGuard will not be 'static and will instead share the lifetime of the context. So, add a lifetime parameter to GlobalGuard to allow for this so we can implement GlobalGuard support for SpinlockIrq. Signed-off-by: Lyude Paul --- rust/kernel/sync/lock/global.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 47e200b750c1d..45400824b0940 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -37,7 +37,7 @@ pub struct GlobalLock { inner: Lock, } =20 -impl GlobalLock { +impl<'a, B: GlobalLockBackend> GlobalLock { /// Creates a global lock. /// /// # Safety @@ -77,14 +77,14 @@ pub unsafe fn init(&'static self) { } =20 /// Lock this global lock. - pub fn lock(&'static self) -> GlobalGuard { + pub fn lock(&'static self) -> GlobalGuard<'static, B> { GlobalGuard { inner: self.inner.lock(), } } =20 /// Try to lock this global lock. - pub fn try_lock(&'static self) -> Option> { + pub fn try_lock(&'static self) -> Option> { Some(GlobalGuard { inner: self.inner.try_lock()?, }) @@ -94,11 +94,11 @@ pub fn try_lock(&'static self) -> Option= > { /// A guard for a [`GlobalLock`]. /// /// See [`global_lock!`] for examples. -pub struct GlobalGuard { - inner: Guard<'static, B::Item, B::Backend>, +pub struct GlobalGuard<'a, B: GlobalLockBackend> { + inner: Guard<'a, B::Item, B::Backend>, } =20 -impl core::ops::Deref for GlobalGuard { +impl<'a, B: GlobalLockBackend> core::ops::Deref for GlobalGuard<'a, B> { type Target =3D B::Item; =20 fn deref(&self) -> &Self::Target { @@ -106,7 +106,7 @@ fn deref(&self) -> &Self::Target { } } =20 -impl core::ops::DerefMut for GlobalGuard { +impl<'a, B: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<'a, B> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } @@ -154,7 +154,7 @@ impl GlobalLockedBy { /// Access the value immutably. /// /// The caller must prove shared access to the lock. - pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard) -> &'a T { + pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_, B>) -> &'a T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &*self.value.get() } } @@ -162,7 +162,7 @@ pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard)= -> &'a T { /// Access the value mutably. /// /// The caller must prove shared exclusive to the lock. - pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard) -> &'a mut= T { + pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<'_, B>) -> &'a= mut T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &mut *self.value.get() } } @@ -232,7 +232,7 @@ pub fn get_mut(&mut self) -> &mut T { /// /// Increment the counter in this instance. /// /// /// /// The caller must hold the `MY_MUTEX` mutex. -/// fn increment(&self, guard: &mut GlobalGuard) -> u32 { +/// fn increment(&self, guard: &mut GlobalGuard<'_, MY_MUTEX>) -> u32 { /// let my_counter =3D self.my_counter.as_mut(guard); /// *my_counter +=3D 1; /// *my_counter --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B331421B182 for ; Tue, 27 May 2025 22:24:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384650; cv=none; b=abHsocoqT5TFS4DLTDPSK5noKaKHyfDFDoTv7wc0G9ZLp3F5BvuPa1R+DdBfaAEc6tcwGKMFCLgX/wkBFQ7rmfnzXidpwQP/XoS2APZUctxkXoDSLpqYbL1c3if5d6heVJRltVW1yI0kvAw3M+DQrruswyYPdY4KA+zC9GHzWd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384650; c=relaxed/simple; bh=AydgeMBxQmfRC50EYCC7u9zKePxoR7+R6ojZT1ByqY4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F1A3IBZOFwI1H2H3fMBpEx9zzqcodnhWyOHaV3kyzpKF49R0Gv09P46lG2pGz/0w/3OY/NAuWDVr1TKMmQuRlphoz/Lo4N1fmvtk2GUw87Dm48OuuZJdccXReqWWMBVzpesJ8suTmdjgwoZj4nV0tEwmil6Jb9x/orz8ubxaVqI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MBv7Nelo; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MBv7Nelo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384647; 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=pb6GJmOC89y5wwjfDdoygoI3FossLZXmvu5/ODyB7LU=; b=MBv7Nelo+/SinjXWsIZlxSzz0jB0t5HhCJU7FUc2NRLMAML367SY1N/1mBM56pbkvaHRoG ZyXI7tfqx62gqRSXvy2L8/Rq/o6ZhTh3Xw+TEfkhFVdIHnxy18uZiyy9jIJLbdYaH210Mi Fyv9exkt2abtxqZJKWhSp+J5uMh5AA0= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-126-0DOzfyj-Mu6ODQlyJtpc8A-1; Tue, 27 May 2025 18:24:04 -0400 X-MC-Unique: 0DOzfyj-Mu6ODQlyJtpc8A-1 X-Mimecast-MFC-AGG-ID: 0DOzfyj-Mu6ODQlyJtpc8A_1748384642 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2FB29180034E; Tue, 27 May 2025 22:24:02 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4F6EA19560AA; Tue, 27 May 2025 22:23:58 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 10/14] rust: sync: lock/global: Rename B to G in trait bounds Date: Tue, 27 May 2025 18:21:51 -0400 Message-ID: <20250527222254.565881-11-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Due to the introduction of Backend::BackendInContext, if we want to be able support Lock types with a Context we need to be able to handle the fact that the Backend for a returned Guard may not exactly match the Backend for the lock. Before we add this though, rename B to G in all of our trait bounds to make sure things don't become more difficult to understand once we add a Backend bound. There should be no functional changes in this patch. Signed-off-by: Lyude Paul --- rust/kernel/sync/lock/global.rs | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 45400824b0940..37209882e006b 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -33,18 +33,18 @@ pub trait GlobalLockBackend { /// Type used for global locks. /// /// See [`global_lock!`] for examples. -pub struct GlobalLock { - inner: Lock, +pub struct GlobalLock { + inner: Lock, } =20 -impl<'a, B: GlobalLockBackend> GlobalLock { +impl<'a, G: GlobalLockBackend> GlobalLock { /// Creates a global lock. /// /// # Safety /// /// * Before any other method on this lock is called, [`Self::init`] m= ust be called. - /// * The type `B` must not be used with any other lock. - pub const unsafe fn new(data: B::Item) -> Self { + /// * The type `G` must not be used with any other lock. + pub const unsafe fn new(data: G::Item) -> Self { Self { inner: Lock { state: Opaque::uninit(), @@ -68,23 +68,23 @@ pub unsafe fn init(&'static self) { // `init` before using any other methods. As `init` can only be ca= lled once, all other // uses of this lock must happen after this call. unsafe { - B::Backend::init( + G::Backend::init( self.inner.state.get(), - B::NAME.as_char_ptr(), - B::get_lock_class().as_ptr(), + G::NAME.as_char_ptr(), + G::get_lock_class().as_ptr(), ) } } =20 /// Lock this global lock. - pub fn lock(&'static self) -> GlobalGuard<'static, B> { + pub fn lock(&'static self) -> GlobalGuard<'static, G> { GlobalGuard { inner: self.inner.lock(), } } =20 /// Try to lock this global lock. - pub fn try_lock(&'static self) -> Option> { + pub fn try_lock(&'static self) -> Option> { Some(GlobalGuard { inner: self.inner.try_lock()?, }) @@ -94,19 +94,19 @@ pub fn try_lock(&'static self) -> Option> { /// A guard for a [`GlobalLock`]. /// /// See [`global_lock!`] for examples. -pub struct GlobalGuard<'a, B: GlobalLockBackend> { - inner: Guard<'a, B::Item, B::Backend>, +pub struct GlobalGuard<'a, G: GlobalLockBackend> { + inner: Guard<'a, G::Item, G::Backend>, } =20 -impl<'a, B: GlobalLockBackend> core::ops::Deref for GlobalGuard<'a, B> { - type Target =3D B::Item; +impl<'a, G: GlobalLockBackend> core::ops::Deref for GlobalGuard<'a, G> { + type Target =3D G::Item; =20 fn deref(&self) -> &Self::Target { &self.inner } } =20 -impl<'a, B: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<'a, B> { +impl<'a, G: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<'a, G> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } @@ -115,33 +115,33 @@ fn deref_mut(&mut self) -> &mut Self::Target { /// A version of [`LockedBy`] for a [`GlobalLock`]. /// /// See [`global_lock!`] for examples. -pub struct GlobalLockedBy { - _backend: PhantomData, +pub struct GlobalLockedBy { + _backend: PhantomData, value: UnsafeCell, } =20 // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLock= edBy`. -unsafe impl Send for GlobalLockedBy +unsafe impl Send for GlobalLockedBy where T: ?Sized, - B: GlobalLockBackend, - LockedBy: Send, + G: GlobalLockBackend, + LockedBy: Send, { } =20 // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLock= edBy`. -unsafe impl Sync for GlobalLockedBy +unsafe impl Sync for GlobalLockedBy where T: ?Sized, - B: GlobalLockBackend, - LockedBy: Sync, + G: GlobalLockBackend, + LockedBy: Sync, { } =20 -impl GlobalLockedBy { +impl GlobalLockedBy { /// Create a new [`GlobalLockedBy`]. /// - /// The provided value will be protected by the global lock indicated = by `B`. + /// The provided value will be protected by the global lock indicated = by `G`. pub fn new(val: T) -> Self { Self { value: UnsafeCell::new(val), @@ -150,11 +150,11 @@ pub fn new(val: T) -> Self { } } =20 -impl GlobalLockedBy { +impl GlobalLockedBy { /// Access the value immutably. /// /// The caller must prove shared access to the lock. - pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_, B>) -> &'a T { + pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_, G>) -> &'a T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &*self.value.get() } } @@ -162,7 +162,7 @@ pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_,= B>) -> &'a T { /// Access the value mutably. /// /// The caller must prove shared exclusive to the lock. - pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<'_, B>) -> &'a= mut T { + pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<'_, G>) -> &'a= mut T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &mut *self.value.get() } } --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6E9E218AC4 for ; Tue, 27 May 2025 22:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384657; cv=none; b=ZR8xnUEmwjjd/yjmjHgnx2cYEF6L/Ci6g3GyLW9IoYkyBS2gUOmTLiemsUIyzbO8FcnJSjWVeGzKDIxm9F6HAkg6OWDIso60z3/VKtKoA5VYv5KRaeFUd120HYU7n3wnl3Z9zeL7CsKKTpaJ1VWJljfcvTXy9mtTsk85LrnNtfc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384657; c=relaxed/simple; bh=5i9/y+Ape+Gy0HgAXWSjhnnANvLH+9s02jL5ioTrk7A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Al/MVa0kjh6Bo/JDNm4mque7tAEzgk7yzSC58TyicBkAtJeaYUvUTgbo0FCHAJWYX1Fa9bWKS3oXnmAAU6ThYBBC++HkKzY+GnPiS/bPSP0VU+IhJbF5B7Y6vmXM7vzJ1+ti3dACQrUbhwCQA94JLlVNXIQ97kB3UihZSY/RLNc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=OxeK5Z0j; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OxeK5Z0j" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384654; 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=2/5YUrPV3C5m+tws2LG2mHT3fyexUVeYO2Q1tZ+A/II=; b=OxeK5Z0jSdGWZY5Onf2c8M+Ckc/7mHds3JKvlG+ycdEG5EGrcG2x+FSP+IGQX5n+7r14dk 9rMnSNEwcPYM1wd0IVULl0+lQUtfdxBKQnfaq6G1eSAeeuAUiqhwEve8+hRrrXFv+OF+Zw TNwqLdCkEoH0INl2az0CBKczMVi3rc4= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-398-WxQV3eXDMOS7V0Q5Z6VzUg-1; Tue, 27 May 2025 18:24:11 -0400 X-MC-Unique: WxQV3eXDMOS7V0Q5Z6VzUg-1 X-Mimecast-MFC-AGG-ID: WxQV3eXDMOS7V0Q5Z6VzUg_1748384647 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 35CC219560AA; Tue, 27 May 2025 22:24:07 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AB33C19560AA; Tue, 27 May 2025 22:24:03 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Ingo Molnar , Mitchell Levy , Wedson Almeida Filho Subject: [RFC RESEND v10 11/14] rust: sync: Expose lock::Backend Date: Tue, 27 May 2025 18:21:52 -0400 Message-ID: <20250527222254.565881-12-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Due to the addition of sync::lock::Backend::Context, lock guards can be returned with a different Backend than their respective lock. Since we'll be adding a trait bound for Backend to GlobalGuard in order to support this, users will need to be able to directly refer to Backend so that they can use it in trait bounds. So, let's make this easier for users and expose Backend in sync. Signed-off-by: Lyude Paul --- rust/kernel/sync.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 07e83992490d5..0d9c3353c8d69 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -23,6 +23,7 @@ pub use lock::spinlock::{ new_spinlock, new_spinlock_irq, SpinLock, SpinLockGuard, SpinLockIrq, = SpinLockIrqGuard, }; +pub use lock::Backend; pub use locked_by::LockedBy; =20 /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE00221C18D for ; Tue, 27 May 2025 22:24:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384659; cv=none; b=pRzlN0dnk0EZc9PAns88MlP9QgJUKMSos+gLRj38W0Dzl/eUVyvE6Qk8QgIbNiEfgX3Fh0BfnCtfM78gI24tJqNXmfxzuTDwZKiEtltyAHNJnb0+gPTNCVwQ4HBZtYBDu3r3Xoi59T6/lfT1GhGhw3s+opSuKTWsCBeKBNmSRMs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384659; c=relaxed/simple; bh=uktaqPLGYFThz2NOiuu7G0P60nubNqBxhcPq0eA6gdA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SgovzN/uBdIpnih/Q1dpjqEZYkj5ODmDOe3MyUJBj20+q66QterDIMwl+6k//FybanYhhCz547izYvQ+g+a5EGB64cOW1BhteNZBLpEl56ZV/JZoVmTHFDfoO6THB4ki0R64kQRcdiAyAD1C4HTlBUdJLcHDWxyuK1hlkDo+Kho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Vc/4/Bjs; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Vc/4/Bjs" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384656; 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=7Dc1B1ViQhAuL8J3llMovxspzHOXW+tb2JzUw0/EYtE=; b=Vc/4/BjsufyeWp6DaT99huKvzFKf5DguyiEpAOKN2An+MiDAfxp+5jQtiTZ3BEX/t50VWp phGCAhKHf5dszS+CFmgdybyPM/FUaNpfW9c3Cji+4Yvc7t+hdJjs+wWKDkdZZdf6N2R3Qa IgX3kLi48OlqC8NN/RrV0aecD6T4JaY= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-592--mhULbN9PUeMkqVhsDRIOw-1; Tue, 27 May 2025 18:24:13 -0400 X-MC-Unique: -mhULbN9PUeMkqVhsDRIOw-1 X-Mimecast-MFC-AGG-ID: -mhULbN9PUeMkqVhsDRIOw_1748384651 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 827CD19560A7; Tue, 27 May 2025 22:24:11 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4671B195608D; Tue, 27 May 2025 22:24:08 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 12/14] rust: sync: lock/global: Add Backend parameter to GlobalGuard Date: Tue, 27 May 2025 18:21:53 -0400 Message-ID: <20250527222254.565881-13-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Due to the introduction of sync::lock::Backend::Context, it's now possible for normal locks to return a Guard with a different Backend than their respective lock (e.g. Backend::BackendInContext). We want to be able to support global locks with contexts as well, so add a trait bound to explicitly specify which Backend is in use for a GlobalGuard. Signed-off-by: Lyude Paul --- rust/kernel/sync/lock/global.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 37209882e006b..1678655faae32 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -77,14 +77,14 @@ pub unsafe fn init(&'static self) { } =20 /// Lock this global lock. - pub fn lock(&'static self) -> GlobalGuard<'static, G> { + pub fn lock(&'static self) -> GlobalGuard<'static, G, G::Backend> { GlobalGuard { inner: self.inner.lock(), } } =20 /// Try to lock this global lock. - pub fn try_lock(&'static self) -> Option> { + pub fn try_lock(&'static self) -> Option> { Some(GlobalGuard { inner: self.inner.try_lock()?, }) @@ -94,11 +94,11 @@ pub fn try_lock(&'static self) -> Option> { /// A guard for a [`GlobalLock`]. /// /// See [`global_lock!`] for examples. -pub struct GlobalGuard<'a, G: GlobalLockBackend> { - inner: Guard<'a, G::Item, G::Backend>, +pub struct GlobalGuard<'a, G: GlobalLockBackend, B: Backend> { + inner: Guard<'a, G::Item, B>, } =20 -impl<'a, G: GlobalLockBackend> core::ops::Deref for GlobalGuard<'a, G> { +impl<'a, G: GlobalLockBackend, B: Backend> core::ops::Deref for GlobalGuar= d<'a, G, B> { type Target =3D G::Item; =20 fn deref(&self) -> &Self::Target { @@ -106,7 +106,7 @@ fn deref(&self) -> &Self::Target { } } =20 -impl<'a, G: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<'a, G> { +impl<'a, G: GlobalLockBackend, B: Backend> core::ops::DerefMut for GlobalG= uard<'a, G, B> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } @@ -154,7 +154,7 @@ impl GlobalLockedBy { /// Access the value immutably. /// /// The caller must prove shared access to the lock. - pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_, G>) -> &'a T { + pub fn as_ref<'a, B: Backend>(&'a self, _guard: &'a GlobalGuard<'_, G,= B>) -> &'a T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &*self.value.get() } } @@ -162,7 +162,7 @@ pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<'_,= G>) -> &'a T { /// Access the value mutably. /// /// The caller must prove shared exclusive to the lock. - pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<'_, G>) -> &'a= mut T { + pub fn as_mut<'a, B: Backend>(&'a self, _guard: &'a mut GlobalGuard<'_= , G, B>) -> &'a mut T { // SAFETY: The lock is globally unique, so there can only be one g= uard. unsafe { &mut *self.value.get() } } @@ -216,7 +216,7 @@ pub fn get_mut(&mut self) -> &mut T { /// ``` /// # mod ex { /// # use kernel::prelude::*; -/// use kernel::sync::{GlobalGuard, GlobalLockedBy}; +/// use kernel::sync::{Backend, GlobalGuard, GlobalLockedBy}; /// /// kernel::sync::global_lock! { /// // SAFETY: Initialized in module initializer before first use. @@ -232,7 +232,7 @@ pub fn get_mut(&mut self) -> &mut T { /// /// Increment the counter in this instance. /// /// /// /// The caller must hold the `MY_MUTEX` mutex. -/// fn increment(&self, guard: &mut GlobalGuard<'_, MY_MUTEX>) -> u32 { +/// fn increment(&self, guard: &mut GlobalGuard<'_, MY_MUT= EX, B>) -> u32 { /// let my_counter =3D self.my_counter.as_mut(guard); /// *my_counter +=3D 1; /// *my_counter --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C1E021CC60 for ; Tue, 27 May 2025 22:24:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384665; cv=none; b=AY6zj0Bqz3S5QmZlnNzU/MQ80zPCaZn8QIdFQwOJ3M0iPAuuo1zRdDH40H0ZW+SNH3wkxVve39weIcnFSfOBjvu3AvRrlJSL/BYUtNpmC2WwenA3sCyhSKO65J506VK6ViCMW9NypqYrTibHPQBR+fvUcz2zikOezh7R3D6NNzg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384665; c=relaxed/simple; bh=6e1hGsbiLPn3G4HmRaHrsMbLYS0h5QwozNlUuKFpbrk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DIfUGpYwXMPEb9kTMse4e9S0yA9ubdENbvDFYTyfwKicdwrQe2EIOhdr0FL2ajlVcSKXoc1cPB0s/n1dy8huaeNJk0a7tPkqYvLdyoFhOkYI+4OzVr/WRq8QsKmt9scs/+MQGQzrT3CQAvLVHgTaPEblJY6isMcgxdhwIbI9UN4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=fPvE3pvB; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fPvE3pvB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384663; 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=lw6yO6YLVcj9INbokZOavvRu5qL/tSIGes0wbNGIl8I=; b=fPvE3pvBf/Vq1FzfNlj88ufuXDFBhg+wwcceYfAUz0fz6HSg/aRokfWzq7yz9SnrcWAXsW ycJlifkMZ3J7MrRJbNHTbuGYyJLOSf7MvGjvdKPpipDg85jwJlcaEi673rbDs58MOTgjPO gg5flldhxDXGqIFQSwfOt+mBaZoq+6w= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-91-n9bDNZKRPoiIyRrWyn67Ug-1; Tue, 27 May 2025 18:24:17 -0400 X-MC-Unique: n9bDNZKRPoiIyRrWyn67Ug-1 X-Mimecast-MFC-AGG-ID: n9bDNZKRPoiIyRrWyn67Ug_1748384655 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9F1A41955D9A; Tue, 27 May 2025 22:24:15 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 81A6F195608D; Tue, 27 May 2025 22:24:12 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [RFC RESEND v10 13/14] rust: sync: lock/global: Add BackendInContext support to GlobalLock Date: Tue, 27 May 2025 18:21:54 -0400 Message-ID: <20250527222254.565881-14-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Now that we have the ability to provide an explicit lifetime for a GlobalGuard and an explicit Backend for a GlobalGuard, we can finally implement lock_with() and try_lock_with(). Signed-off-by: Lyude Paul --- rust/kernel/sync/lock/global.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 1678655faae32..108b15f4466f5 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -89,6 +89,34 @@ pub fn try_lock(&'static self) -> Option> { inner: self.inner.try_lock()?, }) } + + /// Lock this global lock with the provided `context`. + pub fn lock_with( + &'static self, + context: ::Context<'a>, + ) -> GlobalGuard<'a, G, B> + where + G::Backend: Backend, + B: Backend, + { + GlobalGuard { + inner: self.inner.lock_with(context), + } + } + + /// Try to lock this global lock with the provided `context`. + pub fn try_lock_with( + &'static self, + context: ::Context<'a>, + ) -> Option> + where + G::Backend: Backend, + B: Backend, + { + Some(GlobalGuard { + inner: self.inner.try_lock_with(context)?, + }) + } } =20 /// A guard for a [`GlobalLock`]. --=20 2.49.0 From nobody Sun Feb 8 14:55:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44E9D217F23 for ; Tue, 27 May 2025 22:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384666; cv=none; b=O+ept6RcL1EgHnC3HV5vtL6p9BboY/SCLP0ZdY216iYm1n9A7bu7yxYAsKUrb2/6LGvRej4lVQ8qj1TYRHamYVMkqB0bq657+Ynqw3ZdEtP6qUc+yzwb4411rGYpqpBUQaji6TOpZQ7NpYbdiYi15GftMWq/6/VwS/yuwwPf3So= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748384666; c=relaxed/simple; bh=dsaaq539ASGElsdDblRiI+bymC9vwMFvF0DeSf6dfvE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dj4SJQQxnewv3WO6swFlEmIdW88qPfemSKj9KX1B3mav19mejZCtJvC06gwfxkMrhNuND+rlw9XfGuqQmeCzRN5R43n1/xm9VV0yaxMAwMoiVGpGBH4f1hcrRYXPLBUF1AQvhY7rStQ2EAUkuGb/BjjJRUm7xm/roaXSUjJmrdw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ZRQzOFV/; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZRQzOFV/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748384664; 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=rfiYWSSZQP5GjInQFBdw+nv+9qskNJD1Z3HudCLoGME=; b=ZRQzOFV/rVLis9Vgdzrr4DJ5LB4xAXNe9nfTiE872DumxVR4LZnLIalwqUbz2Jh9t/Cwvi DLBXzJOK1E8G0VyeE8V9JLZazUdQ2rurbseeDVQelu8NJui72HBV2VHOAw0A32X4R4MQ6O w71kVqlMi/B4UcmFtRiKdJTBTnZBo7U= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-610-_9YLQ1HqOPmojewD5IqzGQ-1; Tue, 27 May 2025 18:24:21 -0400 X-MC-Unique: _9YLQ1HqOPmojewD5IqzGQ-1 X-Mimecast-MFC-AGG-ID: _9YLQ1HqOPmojewD5IqzGQ_1748384659 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AA5F8195608A; Tue, 27 May 2025 22:24:19 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.88.105]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AC18A1956095; Tue, 27 May 2025 22:24:16 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Thomas Gleixner , Boqun Feng , linux-kernel@vger.kernel.org, Daniel Almeida Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , linux-rt-devel@lists.linux.dev (open list:Real-time Linux (PREEMPT_RT):Keyword:PREEMPT_RT) Subject: [RFC RESEND v10 14/14] locking: Switch to _irq_{disable,enable}() variants in cleanup guards Date: Tue, 27 May 2025 18:21:55 -0400 Message-ID: <20250527222254.565881-15-lyude@redhat.com> In-Reply-To: <20250527222254.565881-1-lyude@redhat.com> References: <20250527222254.565881-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Content-Type: text/plain; charset="utf-8" From: Boqun Feng The semantics of various irq disabling guards match what *_irq_{disable,enable}() provide, i.e. the interrupt disabling is properly nested, therefore it's OK to switch to use *_irq_{disable,enable}() primitives. Signed-off-by: Boqun Feng --- V10: * Add PREEMPT_RT build fix from Guangbo Cui Signed-off-by: Lyude Paul --- include/linux/spinlock.h | 26 ++++++++++++-------------- include/linux/spinlock_rt.h | 6 ++++++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index b21da4bd51a42..7ff11c893940b 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -605,10 +605,10 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock= _t, raw_spin_unlock(_T->lock)) =20 DEFINE_LOCK_GUARD_1(raw_spinlock_irq, raw_spinlock_t, - raw_spin_lock_irq(_T->lock), - raw_spin_unlock_irq(_T->lock)) + raw_spin_lock_irq_disable(_T->lock), + raw_spin_unlock_irq_enable(_T->lock)) =20 -DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->= lock)) +DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq_disa= ble(_T->lock)) =20 DEFINE_LOCK_GUARD_1(raw_spinlock_bh, raw_spinlock_t, raw_spin_lock_bh(_T->lock), @@ -617,12 +617,11 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_bh, raw_spinlock_t, DEFINE_LOCK_GUARD_1_COND(raw_spinlock_bh, _try, raw_spin_trylock_bh(_T->lo= ck)) =20 DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t, - raw_spin_lock_irqsave(_T->lock, _T->flags), - raw_spin_unlock_irqrestore(_T->lock, _T->flags), - unsigned long flags) + raw_spin_lock_irq_disable(_T->lock), + raw_spin_unlock_irq_enable(_T->lock)) =20 DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try, - raw_spin_trylock_irqsave(_T->lock, _T->flags)) + raw_spin_trylock_irq_disable(_T->lock)) =20 DEFINE_LOCK_GUARD_1(spinlock, spinlock_t, spin_lock(_T->lock), @@ -631,11 +630,11 @@ DEFINE_LOCK_GUARD_1(spinlock, spinlock_t, DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock)) =20 DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t, - spin_lock_irq(_T->lock), - spin_unlock_irq(_T->lock)) + spin_lock_irq_disable(_T->lock), + spin_unlock_irq_enable(_T->lock)) =20 DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try, - spin_trylock_irq(_T->lock)) + spin_trylock_irq_disable(_T->lock)) =20 DEFINE_LOCK_GUARD_1(spinlock_bh, spinlock_t, spin_lock_bh(_T->lock), @@ -645,12 +644,11 @@ DEFINE_LOCK_GUARD_1_COND(spinlock_bh, _try, spin_trylock_bh(_T->lock)) =20 DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t, - spin_lock_irqsave(_T->lock, _T->flags), - spin_unlock_irqrestore(_T->lock, _T->flags), - unsigned long flags) + spin_lock_irq_disable(_T->lock), + spin_unlock_irq_enable(_T->lock)) =20 DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try, - spin_trylock_irqsave(_T->lock, _T->flags)) + spin_trylock_irq_disable(_T->lock)) =20 DEFINE_LOCK_GUARD_1(read_lock, rwlock_t, read_lock(_T->lock), diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h index 6ea08fafa6d7b..f54e184735563 100644 --- a/include/linux/spinlock_rt.h +++ b/include/linux/spinlock_rt.h @@ -132,6 +132,12 @@ static __always_inline void spin_unlock_irqrestore(spi= nlock_t *lock, rt_spin_unlock(lock); } =20 +static __always_inline int spin_trylock_irq_disable(spinlock_t *lock) +{ + return rt_spin_trylock(lock); +} + + #define spin_trylock(lock) \ __cond_lock(lock, rt_spin_trylock(lock)) =20 --=20 2.49.0