All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Lyude Paul <lyude@redhat.com>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Tamir Duberstein" <tamird@gmail.com>,
	"Filipe Xavier" <felipe_life@live.com>,
	"Martin Rodriguez Reboredo" <yakoyoku@gmail.com>,
	"Valentin Obst" <kernel@valentinobst.de>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Wedson Almeida Filho" <walmeida@microsoft.com>
Subject: Re: [PATCH 1/3] rust: sync: Add Lock::is_locked()
Date: Wed, 20 Nov 2024 15:53:52 -0800	[thread overview]
Message-ID: <Zz52kNp4_jRxBv_G@tardis.local> (raw)
In-Reply-To: <20241120223442.2491136-2-lyude@redhat.com>

On Wed, Nov 20, 2024 at 05:30:41PM -0500, Lyude Paul wrote:
> Now that we've added a Lock::from_raw() function and exposed Guard::new(),
> it would be good to actually add the ability to assert the current state
> of a lock to ensure correctness for unsafe code using these functions.
> 
> To do so, let's add Lock::is_locked() which simply returns whether or not a
> Lock is acquired. We'll use this in the next few commits to add some debug
> assertions.
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/helpers/spinlock.c           |  5 +++++
>  rust/kernel/sync/lock.rs          | 18 ++++++++++++++++++
>  rust/kernel/sync/lock/mutex.rs    |  5 +++++
>  rust/kernel/sync/lock/spinlock.rs |  5 +++++
>  4 files changed, 33 insertions(+)
> 
> diff --git a/rust/helpers/spinlock.c b/rust/helpers/spinlock.c
> index b7b0945e8b3cb..90216a69e3ea1 100644
> --- a/rust/helpers/spinlock.c
> +++ b/rust/helpers/spinlock.c
> @@ -26,3 +26,8 @@ int rust_helper_spin_trylock(spinlock_t *lock)
>  {
>  	return spin_trylock(lock);
>  }
> +
> +bool rust_helper_spin_is_locked(spinlock_t *lock)
> +{
> +	return spin_is_locked(lock);
> +}
> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> index 139f17f2ec86b..542f846ac02b2 100644
> --- a/rust/kernel/sync/lock.rs
> +++ b/rust/kernel/sync/lock.rs
> @@ -85,6 +85,13 @@ unsafe fn relock(ptr: *mut Self::State, guard_state: &mut Self::GuardState) {
>          // SAFETY: The safety requirements ensure that the lock is initialised.
>          *guard_state = unsafe { Self::lock(ptr) };
>      }
> +
> +    /// Returns whether or not the lock is currently acquired.
> +    ///
> +    /// # Safety
> +    ///
> +    /// Callers must ensure that `ptr` is a valid initialised pointer to this lock type.
> +    unsafe fn is_locked(ptr: *mut Self::State) -> bool;
>  }
>  
>  /// A mutual exclusion primitive.
> @@ -170,6 +177,17 @@ pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
>          // that `init` was called.
>          unsafe { B::try_lock(self.state.get()).map(|state| Guard::new(self, state)) }
>      }
> +
> +    /// Return whether or not the lock is currently acquired.
> +    ///
> +    /// Keep in mind that this function is inherently racy: a lock could immediately be acquired or
> +    /// released after this function returns. As such, the return value from this function should be
> +    /// treated as a snapshot for debugging purposes.

Then why don't we use the function provided by lockdep? I.e.
lockdep_is_held() and its friends?

Regards,
Boqun

> +    pub fn is_locked(&self) -> bool {

> +        // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
> +        // that `init` was called.
> +        unsafe { B::is_locked(self.state.get()) }
> +    }
>  }
>  
>  /// A lock guard.
> diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs
> index 0e946ebefce12..f21b1f14cbe1b 100644
> --- a/rust/kernel/sync/lock/mutex.rs
> +++ b/rust/kernel/sync/lock/mutex.rs
> @@ -126,4 +126,9 @@ unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> {
>              None
>          }
>      }
> +
> +    unsafe fn is_locked(ptr: *mut Self::State) -> bool {
> +        // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
> +        unsafe { bindings::mutex_is_locked(ptr) }
> +    }
>  }
> diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs
> index 9f4d128bed983..cfccf5e900b80 100644
> --- a/rust/kernel/sync/lock/spinlock.rs
> +++ b/rust/kernel/sync/lock/spinlock.rs
> @@ -125,4 +125,9 @@ unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> {
>              None
>          }
>      }
> +
> +    unsafe fn is_locked(ptr: *mut Self::State) -> bool {
> +        // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
> +        unsafe { bindings::spin_is_locked(ptr) }
> +    }
>  }
> -- 
> 2.47.0
> 

  reply	other threads:[~2024-11-20 23:53 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-20 22:30 [PATCH 0/3] rust: sync: Add Lock::is_locked() Lyude Paul
2024-11-20 22:30 ` [PATCH 1/3] " Lyude Paul
2024-11-20 23:53   ` Boqun Feng [this message]
2024-11-20 22:30 ` [PATCH 2/3] rust: sync: Assert Lock::is_locked in Guard::new for debug builds Lyude Paul
2024-11-20 23:59   ` Boqun Feng
2024-11-22 20:30     ` Lyude Paul
2024-11-25 21:30       ` Boqun Feng
2024-11-20 22:30 ` [PATCH 3/3] rust: sync: Add Guard::new_unchecked() Lyude Paul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Zz52kNp4_jRxBv_G@tardis.local \
    --to=boqun.feng@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=dakr@kernel.org \
    --cc=felipe_life@live.com \
    --cc=gary@garyguo.net \
    --cc=kernel@valentinobst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@gmail.com \
    --cc=tmgross@umich.edu \
    --cc=walmeida@microsoft.com \
    --cc=yakoyoku@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.