sx: Add sx_has_waiters() macro

This macro will return non-zero if there are threads waiting for this
lock; otherwise, it will return zero.

The function assumes (but does not assert) that the caller already holds
the lock and that it is interested in other threads waiting for it to
release the lock.

The motivation to add this is the implementation of
`rwsem_is_contended()` in linuxkpi.

This Linux function indicates the same thing to the caller: if other
threads are waiting for this semaphore.

The amdgpu DRM driver started to use `rwsem_is_contended()` in Linux
6.12.

Reviewed by:	bz, olce
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D56443
This commit is contained in:
Jean-Sébastien Pédron
2026-04-12 19:20:25 +02:00
parent 65dc0e9071
commit eebb643bb3
3 changed files with 16 additions and 1 deletions
+11 -1
View File
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
.\" DAMAGE.
.\"
.Dd November 11, 2017
.Dd Apri 30, 2026
.Dt SX 9
.Os
.Sh NAME
@@ -46,6 +46,7 @@
.Nm sx_sleep ,
.Nm sx_xholder ,
.Nm sx_xlocked ,
.Nm sx_has_waiters ,
.Nm sx_assert ,
.Nm SX_SYSINIT ,
.Nm SX_SYSINIT_FLAGS
@@ -88,6 +89,8 @@
.Fn sx_xholder "struct sx *sx"
.Ft int
.Fn sx_xlocked "const struct sx *sx"
.Ft int
.Fn sx_has_waiters "const struct sx *sx"
.Pp
.Cd "options INVARIANTS"
.Cd "options INVARIANT_SUPPORT"
@@ -268,6 +271,13 @@ is returned instead.
will return non-zero if the current thread holds the exclusive lock;
otherwise, it will return zero.
.Pp
.Fn sx_has_waiters
will return non-zero if there are threads waiting for this lock;
otherwise, it will return zero.
The function assumes (but does not assert) that the caller already holds the
lock and that it is interested in other threads waiting for it to release the
lock.
.Pp
For ease of programming,
.Fn sx_unlock
is provided as a macro frontend to the respective functions,
@@ -51,6 +51,7 @@ struct rw_semaphore {
#define down_read_nested(_rw, _sc) down_read(_rw)
#define init_rwsem(_rw) linux_init_rwsem(_rw, rwsem_name("lnxrwsem"))
#define down_write_nest_lock(sem, _rw) down_write(_rw)
#define rwsem_is_contended(_rw) sx_has_waiters(&(_rw)->sx);
#ifdef WITNESS_ALL
/* NOTE: the maximum WITNESS name is 64 chars */
+4
View File
@@ -259,6 +259,10 @@ __sx_xunlock(struct sx *sx, struct thread *td, const char *file, int line)
(void)0; /* ensure void type for expression */ \
})
/* Return true if there are threads waiting to acquire this sx lock. */
#define sx_has_waiters(sx) \
((SX_READ_VALUE(sx) & SX_LOCK_WAITERS) != 0)
#define sx_unlock(sx) sx_unlock_((sx), LOCK_FILE, LOCK_LINE)
#define sx_sleep(chan, sx, pri, wmesg, timo) \