From: Peter Zijlstra <peterz@infradead.org>
To: "Nuno Sá" <noname.nuno@gmail.com>
Cc: David Lechner <dlechner@baylibre.com>,
Jonathan Cameron <jic23@kernel.org>,
linux-iio@vger.kernel.org,
Cosmin Tanislav <demonsingur@gmail.com>,
Jagath Jog J <jagathjog1996@gmail.com>,
Gwendal Grignou <gwendal@chromium.org>,
Daniel Campello <campello@chromium.org>,
gregkh@linuxfoundation.org,
Jonathan Cameron <Jonathan.Cameron@huawei.com>
Subject: Re: [RFC PATCH 1/8] iio: locking: introduce __cleanup() based direct mode claiming infrastructure
Date: Tue, 24 Oct 2023 17:11:23 +0200 [thread overview]
Message-ID: <20231024151123.GB40044@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <462c181eab1c0b70c0350099b7f70aaf736aabe1.camel@gmail.com>
On Mon, Oct 23, 2023 at 10:55:56AM +0200, Nuno Sá wrote:
> > > +/*
> > > + * Auto cleanup version of iio_device_claim_direct_mode,
> > > + *
> > > + * CLASS(iio_claim_direct, claimed_dev)(indio_dev);
> > > + * if (IS_ERR(claimed_dev))
> > > + * return PTR_ERR(claimed_dev);
> > > + *
> > > + * st = iio_priv(claimed_dev);
> > > + * ....
> > > + */
> > > +DEFINE_CLASS(iio_claim_direct, struct iio_dev *,
> > > + iio_device_release_direct_mode(_T),
> > > + ({
> > > + struct iio_dev *dev;
> > > + int d = iio_device_claim_direct_mode(_T);
> > > +
> > > + if (d < 0)
> > > + dev = ERR_PTR(d);
> > > + else
> > > + dev = _T;
> > > + dev;
> > > + }),
> > > + struct iio_dev *_T);
> > > +
> I don't really have a very strong opinion on this but what I really don't like
> much is the pattern:
>
> CLASS(type, ret), where the return value is an argument of the macro... It would
> be nice if we could just make it like:
>
> ret = guard(type)(...); //or any other variation of the guard() macro
> if (ret)
> return ret;
>
> the above could also be an error pointer or even have one variation of each. but
> yeah, that likely means changing the cleanup.h file and that might be out of
> scope for Jonathan's patch series.
So I have a version for trylocks that I've not managed to send out.. it
doesn't deal with arbitrary error codes, and as someone else down-thread
noted, the guard() thing is not really suited for tricks like this.
Notably I have a patch that converts ptrace_attach() to have a loop like:
scoped_guard (mutex_intr, &task->signal->cred_guard_mutex) {
goto success;
}
return -ERESTARTNOINTR;
success:
...
return 0;
And another patch that does something like:
scoped_cond_guard (rwsem_read_intr, no_lock,
task ? &task->signal->exec_update_lock : NULL) {
if (0) {
no_lock:
if (task)
return -EINTR;
}
...
}
---
Subject: cleanup: Add conditional guard support
From: Peter Zijlstra <peterz@infradead.org>
Date: Sun Sep 17 13:22:17 CEST 2023
Adds:
- DEFINE_GUARD_COND() / DEFINE_LOCK_GUARD_1_COND() to extend existing
guards with conditional lock primitives, eg. mutex_trylock(),
mutex_lock_interruptible().
nb. both primitives allow NULL 'locks', which cause the lock to
fail (obviously).
- extends scoped_guard() to not take the body when the the
conditional guard 'fails'. eg.
scoped_guard (mutex_intr, &task->signal_cred_guard_mutex) {
...
}
will only execute the body when the mutex is held.
- provides scoped_cond_guard(name, label, args...); which extends
scoped_guard() to jump to @label when the lock fails.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
Index: linux-2.6/include/linux/cleanup.h
===================================================================
--- linux-2.6.orig/include/linux/cleanup.h
+++ linux-2.6/include/linux/cleanup.h
@@ -136,14 +136,35 @@ static inline class_##_name##_t class_##
*/
#define DEFINE_GUARD(_name, _type, _lock, _unlock) \
- DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T)
+ DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
+ static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \
+ { return *_T; }
+
+#define DEFINE_GUARD_COND(_name, _ext, _condlock) \
+ EXTEND_CLASS(_name, _ext, \
+ ({ void *_t = _T; if (_T && !(_condlock)) _t = NULL; _t; }), \
+ class_##_name##_t _T) \
+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
+ { return class_##_name##_lock_ptr(_T); }
+
+#define _guard(_name, var) \
+ class_##_name##_t var __cleanup(class_##_name##_destructor) = \
+ class_##_name##_constructor
#define guard(_name) \
- CLASS(_name, __UNIQUE_ID(guard))
+ _guard(_name, __UNIQUE_ID(guard))
+
+#define __guard_ptr(_name) class_##_name##_lock_ptr
#define scoped_guard(_name, args...) \
for (CLASS(_name, scope)(args), \
- *done = NULL; !done; done = (void *)1)
+ *done = NULL; __guard_ptr(_name)(&scope) && !done; done = (void *)1)
+
+#define scoped_cond_guard(_name, _label, args...) \
+ for (CLASS(_name, scope)(args), \
+ *done = NULL; !done; done = (void *)1) \
+ if (!__guard_ptr(_name)(&scope)) goto _label; \
+ else
/*
* Additional helper macros for generating lock guards with types, either for
@@ -173,6 +194,11 @@ typedef struct { \
static inline void class_##_name##_destructor(class_##_name##_t *_T) \
{ \
if (_T->lock) { _unlock; } \
+} \
+ \
+static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \
+{ \
+ return _T->lock; \
}
@@ -201,4 +227,14 @@ __DEFINE_LOCK_GUARD_1(_name, _type, _loc
__DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \
__DEFINE_LOCK_GUARD_0(_name, _lock)
+#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock) \
+ EXTEND_CLASS(_name, _ext, \
+ ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
+ if (_T->lock && !(_condlock)) _T->lock = NULL; \
+ _t; }), \
+ typeof_member(class_##_name##_t, lock) l) \
+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
+ { return class_##_name##_lock_ptr(_T); }
+
+
#endif /* __LINUX_GUARDS_H */
Index: linux-2.6/include/linux/mutex.h
===================================================================
--- linux-2.6.orig/include/linux/mutex.h
+++ linux-2.6/include/linux/mutex.h
@@ -221,6 +221,7 @@ extern void mutex_unlock(struct mutex *l
extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T))
-DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T))
+DEFINE_GUARD_COND(mutex, _try, mutex_trylock(_T))
+DEFINE_GUARD_COND(mutex, _intr, mutex_lock_interruptible(_T) == 0)
#endif /* __LINUX_MUTEX_H */
Index: linux-2.6/include/linux/spinlock.h
===================================================================
--- linux-2.6.orig/include/linux/spinlock.h
+++ linux-2.6/include/linux/spinlock.h
@@ -507,6 +507,8 @@ DEFINE_LOCK_GUARD_1(raw_spinlock, raw_sp
raw_spin_lock(_T->lock),
raw_spin_unlock(_T->lock))
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock, _try, raw_spin_trylock(_T->lock))
+
DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock_t,
raw_spin_lock_nested(_T->lock, SINGLE_DEPTH_NESTING),
raw_spin_unlock(_T->lock))
@@ -515,23 +517,36 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_irq, ra
raw_spin_lock_irq(_T->lock),
raw_spin_unlock_irq(_T->lock))
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->lock))
+
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)
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try,
+ raw_spin_trylock_irqsave(_T->lock, _T->flags))
+
DEFINE_LOCK_GUARD_1(spinlock, spinlock_t,
spin_lock(_T->lock),
spin_unlock(_T->lock))
+DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock))
+
DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t,
spin_lock_irq(_T->lock),
spin_unlock_irq(_T->lock))
+DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try,
+ spin_trylock_irq(_T->lock))
+
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)
+DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try,
+ spin_trylock_irqsave(_T->lock, _T->flags))
+
#undef __LINUX_INSIDE_SPINLOCK_H
#endif /* __LINUX_SPINLOCK_H */
Index: linux-2.6/include/linux/rwsem.h
===================================================================
--- linux-2.6.orig/include/linux/rwsem.h
+++ linux-2.6/include/linux/rwsem.h
@@ -203,11 +203,11 @@ extern void up_read(struct rw_semaphore
extern void up_write(struct rw_semaphore *sem);
DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T))
-DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T))
-
-DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T))
-DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T))
+DEFINE_GUARD_COND(rwsem_read, _try, down_read_trylock(_T))
+DEFINE_GUARD_COND(rwsem_read, _intr, down_read_interruptible(_T) == 0)
+DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T))
+DEFINE_GUARD_COND(rwsem_write, _try, down_write_trylock(_T))
/*
* downgrade write lock to read lock
next prev parent reply other threads:[~2023-10-24 15:12 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-22 15:47 [RFC PATCH 0/8] IIO: Use the new cleanup.h magic Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 1/8] iio: locking: introduce __cleanup() based direct mode claiming infrastructure Jonathan Cameron
2023-10-22 21:10 ` David Lechner
2023-10-23 8:55 ` Nuno Sá
2023-10-23 9:53 ` Jonathan Cameron
2023-10-23 11:51 ` Nuno Sá
2023-10-23 14:34 ` Jonathan Cameron
2023-10-23 14:58 ` Nuno Sá
2023-10-24 12:23 ` Jonathan Cameron
2023-10-25 7:24 ` Nuno Sá
2023-10-24 15:11 ` Peter Zijlstra [this message]
2023-10-24 15:28 ` Peter Zijlstra
2023-10-28 16:59 ` Jonathan Cameron
2023-11-02 10:48 ` Peter Zijlstra
2023-11-03 15:19 ` Jonathan Cameron
2023-10-23 9:49 ` Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 2/8] iio: dummy: Add use of new automated cleanup of locks and direct mode claiming Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 3/8] iio: accel: adxl367: Use automated cleanup for locks and iio direct mode Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 4/8] iio: imu: bmi323: Use cleanup handling for iio_device_claim_direct_mode() Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 5/8] iio: adc: max1363: Use automatic cleanup for locks and iio mode claiming Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 6/8] iio: proximity: sx9360: Use automated cleanup for locks and IIO " Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 7/8] iio: proximity: sx9324: " Jonathan Cameron
2023-10-22 15:47 ` [RFC PATCH 8/8] iio: proximity: sx9310: " Jonathan Cameron
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=20231024151123.GB40044@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=Jonathan.Cameron@huawei.com \
--cc=campello@chromium.org \
--cc=demonsingur@gmail.com \
--cc=dlechner@baylibre.com \
--cc=gregkh@linuxfoundation.org \
--cc=gwendal@chromium.org \
--cc=jagathjog1996@gmail.com \
--cc=jic23@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=noname.nuno@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