mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Wedson Almeida Filho <wedsonaf@gmail.com>
Cc: rust-for-linux@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>,
	linux-kernel@vger.kernel.org,
	"Wedson Almeida Filho" <walmeida@microsoft.com>,
	"Martin Rodriguez Reboredo" <yakoyoku@gmail.com>
Subject: Re: [PATCH v4 11/13] rust: lock: add `Guard::do_unlocked`
Date: Wed, 12 Apr 2023 07:35:28 -0700	[thread overview]
Message-ID: <ZDbBsBIZwMhbquRG@Boquns-Mac-mini.local> (raw)
In-Reply-To: <CANeycqqpR6Gs5Qb_pc2j_QV-JAc8xR360vth6We8xWU1GU5ASA@mail.gmail.com>

On Wed, Apr 12, 2023 at 08:07:40AM -0300, Wedson Almeida Filho wrote:
> On Wed, 12 Apr 2023 at 03:25, Boqun Feng <boqun.feng@gmail.com> wrote:
> >
> > On Tue, Apr 11, 2023 at 02:45:41AM -0300, Wedson Almeida Filho wrote:
> > [...]
> > > +
> > > +    unsafe fn relock(ptr: *mut Self::State, guard_state: &mut Self::GuardState) {
> > > +        let _ = match guard_state {
> > > +            // SAFETY: The safety requiments of this function ensure that `ptr` has been
> > > +            // initialised.
> > > +            None => unsafe { Self::lock(ptr) },
> > > +            // SAFETY: The safety requiments of this function ensure that `ptr` has been
> > > +            // initialised.
> > > +            Some(_) => unsafe { Self::lock_irqsave(ptr) },
> > > +        };
> > > +    }
> > >  }
> > >
> >
> > One thing I'm little worried about the above is that we don't store back
> > the new GuardState into `guard_state`, the particular case I'm worried
> > about is as follow:
> >
> >         // IRQ is enabled.
> >         // Disabling IRQ
> >         unsafe { bindings::local_irq_disable(); }
> >
> >         let mut g = unsafe { SpinLockBackend::lock(&mut lock as *mut _) };
> >         // `g` records irq state is "irq disabled"
> >
> >         unsafe { SpinLockBackend::unlock(&mut lock as *mut _, &g); }
> >         // restore into "irq disabled" mode.
> >         // IRQ is disabled.
> >
> >         // Enabling IRQ
> >         unsafe { bindings::local_irq_enable(); }
> >         // IRQ is enabled.
> >
> >         unsafe { SpinLockBackend::relock(&mut lock as *mut _, &mut g) }
> >         // `g` still records irq state is "irq disabled"
> 
> Yes, that's by design. If you want it to record the new "irq enabled"
> state, then you should call `lock()`, not `relock()`.
> 
> >         unsafe { SpinLockBackend::unlock(&mut lock as *mut _, &g); }
> >         // restore into "irq disabled" mode.
> >         // IRQ is disabled.
> >
> >
> > This looks pretty scary to me, I would expect `relock()` updates the
> > latest GuardState to the guard. Any reason it's implemented this way?
> 
> A `relock()` followed by an `unlock()` takes the state back to how it
> was when `lock()` was originally called: this is precisely why
> `relock()` exists.
> 
> Consider the following case:
> 
> ```
> local_disable_irq();
> let mut guard = spinlock.lock();

I think you meant `spinlock.lock_irqsave()` here, right?

> 
> guard.do_unlocked(|| {
>     local_irq_enable();
>     schedule();
> });
> 
> drop(guard);
> ```
> 
> What would you expect the state to be? It's meant to be the state

I understand your point but I would expect people to code like:

```
local_disable_irq();
let mut guard = spinlock.lock(); // or lock_irqsave(), doesn't matter

guard.do_unlocked(|| {
    local_irq_enable();
    schedule();
    local_irq_disable();
});

drop(guard);
```

And the closure in do_unlocked() can also be something like:
```
	guard.do_unlocked(|| {
	    local_irq_enabled();
	    let _g = ScopeGuard::new(|| {
	        local_irq_disabled();
	    });

	    schedule();

	    if (some_cond) {
	    	return; // return early
	    }

	    if (other_cond) {
	    	return;
	    }
	})

```

One benefit (other that code looks symmetric) is we can use the same
closure in other place. Also it helps klint since we keep the irq
enablement state change as local as possible: we can go ahead and
require irq enabled state should not be changed between the closure in
do_unlock().

Maybe I'm missing something, but the current `relock` semantics is
really tricky to get ;-)

Regards,
Boqun

> right before `spinlock.lock()` was called, that's what the guard
> represents.
> 
> If you want to preserve a new state, then you don't want `relock()`,
> you just want a new `lock()` call.
> 
> > Regards,
> > Boqun
> >
> > >  // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. We use the `irqsave`
> > >  // variant of the C lock acquisition functions to disable interrupts and retrieve the original
> > >  // interrupt state, and the `irqrestore` variant of the lock release functions to restore the state
> > >  // in `unlock` -- we use the guard context to determine which method was used to acquire the lock.
> > > -unsafe impl super::IrqSaveBackend for SpinLockBackend {
> > > +unsafe impl IrqSaveBackend for SpinLockBackend {
> > >      unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState {
> > >          // SAFETY: The safety requirements of this function ensure that `ptr` points to valid
> > >          // memory, and that it has been initialised before.
> > > --
> > > 2.34.1
> > >

  reply	other threads:[~2023-04-12 14:36 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-11  5:45 [PATCH v4 01/13] rust: sync: introduce `LockClassKey` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 02/13] rust: sync: introduce `Lock` and `Guard` Wedson Almeida Filho
2023-04-11 20:42   ` Gary Guo
2023-04-12 11:38     ` Wedson Almeida Filho
2023-04-14 12:02       ` Alice Ryhl
2023-04-13  8:46   ` Benno Lossin
2023-04-11  5:45 ` [PATCH v4 03/13] rust: lock: introduce `Mutex` Wedson Almeida Filho
2023-04-13  8:56   ` Benno Lossin
2023-04-11  5:45 ` [PATCH v4 04/13] locking/spinlock: introduce spin_lock_init_with_key Wedson Almeida Filho
2023-04-11 18:05   ` Wedson Almeida Filho
2023-04-12 19:14     ` Boqun Feng
2023-04-11  5:45 ` [PATCH v4 05/13] rust: lock: introduce `SpinLock` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 06/13] rust: lock: add support for `Lock::lock_irqsave` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 08/13] rust: introduce `ARef` Wedson Almeida Filho
2023-04-11 20:45   ` Gary Guo
2023-04-13  9:19   ` Benno Lossin
2023-04-13 17:06     ` Wedson Almeida Filho
2023-04-13 22:29       ` Benno Lossin
2023-04-14  9:00         ` Wedson Almeida Filho
2023-04-14  9:46           ` Benno Lossin
2023-04-14 14:38             ` Gary Guo
2023-04-14 17:03               ` Boqun Feng
2023-04-11  5:45 ` [PATCH v4 09/13] rust: add basic `Task` Wedson Almeida Filho
2023-04-11 20:47   ` Gary Guo
2023-04-12 11:42     ` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 10/13] rust: introduce `current` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 11/13] rust: lock: add `Guard::do_unlocked` Wedson Almeida Filho
2023-04-11 20:54   ` Gary Guo
2023-04-12 11:16     ` Wedson Almeida Filho
2023-04-11 21:17   ` Boqun Feng
2023-04-12 11:09     ` Wedson Almeida Filho
2023-04-12  6:25   ` Boqun Feng
2023-04-12 11:07     ` Wedson Almeida Filho
2023-04-12 14:35       ` Boqun Feng [this message]
2023-04-12 17:41         ` Wedson Almeida Filho
2023-04-11  5:45 ` [PATCH v4 12/13] rust: sync: introduce `CondVar` Wedson Almeida Filho
2023-04-14 11:55   ` Alice Ryhl
2023-04-11  5:45 ` [PATCH v4 13/13] rust: sync: introduce `LockedBy` Wedson Almeida Filho
2023-04-13  9:45   ` Benno Lossin
2023-04-11 20:35 ` [PATCH v4 01/13] rust: sync: introduce `LockClassKey` Gary Guo
2023-04-13  8:02 ` Benno Lossin
2023-04-21 23:48 ` Miguel Ojeda

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=ZDbBsBIZwMhbquRG@Boquns-Mac-mini.local \
    --to=boqun.feng@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=walmeida@microsoft.com \
    --cc=wedsonaf@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®