Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154037729
D56443.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D56443.diff
View Options
diff --git a/sys/compat/linuxkpi/common/include/linux/rwsem.h b/sys/compat/linuxkpi/common/include/linux/rwsem.h
--- a/sys/compat/linuxkpi/common/include/linux/rwsem.h
+++ b/sys/compat/linuxkpi/common/include/linux/rwsem.h
@@ -37,19 +37,40 @@
struct rw_semaphore {
struct sx sx;
+
+ /*
+ * Implementations of `down_{read,write}()` attempts a "try lock"
+ * first, and if they fail, they bump `waiters_count` and acquire the
+ * lock using the blocking call.
+ *
+ * `rwsem_is_contended()` uses `waiters_count` to determine if other
+ * threads are waiting for this lock. It assumes that the caller also
+ * acquired the lock, though it does not enforce this.
+ *
+ * Linux uses a wait list (with the accompanying lock) instead of a
+ * counter because the list is used for other operations.
+ */
+ int waiters_count;
};
-#define down_write(_rw) sx_xlock(&(_rw)->sx)
-#define up_write(_rw) sx_xunlock(&(_rw)->sx)
-#define down_read(_rw) sx_slock(&(_rw)->sx)
-#define up_read(_rw) sx_sunlock(&(_rw)->sx)
+void linuxkpi_init_rwsem(struct rw_semaphore *rw, const char *name);
+void linuxkpi_down_write(struct rw_semaphore *rw);
+void linuxkpi_up_write(struct rw_semaphore *rw);
+void linuxkpi_down_read(struct rw_semaphore *rw);
+void linuxkpi_up_read(struct rw_semaphore *rw);
+
+#define init_rwsem(_rw) linuxkpi_init_rwsem(_rw, rwsem_name("lnxrwsem"))
+#define down_write(_rw) linuxkpi_down_write(_rw)
+#define up_write(_rw) linuxkpi_up_write(_rw)
+#define down_read(_rw) linuxkpi_down_read(_rw)
+#define up_read(_rw) linuxkpi_up_read(_rw)
+
#define down_read_trylock(_rw) !!sx_try_slock(&(_rw)->sx)
#define down_read_killable(_rw) linux_down_read_killable(_rw)
#define down_write_trylock(_rw) !!sx_try_xlock(&(_rw)->sx)
#define down_write_killable(_rw) linux_down_write_killable(_rw)
#define downgrade_write(_rw) sx_downgrade(&(_rw)->sx)
#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)
#ifdef WITNESS_ALL
@@ -67,16 +88,14 @@
struct rw_semaphore name; \
static void name##_rwsem_init(void *arg) \
{ \
- linux_init_rwsem(&name, rwsem_name(#name)); \
+ linuxkpi_init_rwsem(&name, rwsem_name(#name)); \
} \
SYSINIT(name, SI_SUB_LOCK, SI_ORDER_SECOND, name##_rwsem_init, NULL)
-static inline void
-linux_init_rwsem(struct rw_semaphore *rw, const char *name)
+static inline int
+rwsem_is_contended(struct rw_semaphore *sem)
{
-
- memset(rw, 0, sizeof(*rw));
- sx_init_flags(&rw->sx, name, SX_NOWITNESS);
+ return (sem->waiters_count > 0);
}
extern int linux_down_read_killable(struct rw_semaphore *);
diff --git a/sys/compat/linuxkpi/common/src/linux_rwsem.c b/sys/compat/linuxkpi/common/src/linux_rwsem.c
new file mode 100644
--- /dev/null
+++ b/sys/compat/linuxkpi/common/src/linux_rwsem.c
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
+ * Copyright (c) 2026 The FreeBSD Foundation
+ */
+
+#include <linux/rwsem.h>
+
+void
+linuxkpi_init_rwsem(struct rw_semaphore *rw, const char *name)
+{
+ memset(rw, 0, sizeof(*rw));
+ sx_init_flags(&rw->sx, name, SX_NOWITNESS);
+ /* `rw->waiters_count` is already zero. */
+}
+
+void
+linuxkpi_down_write(struct rw_semaphore *rw)
+{
+ if (!sx_try_xlock(&rw->sx)) {
+ /* `rw->waiters_count` is used by `rwsem_is_contended()`. */
+ rw->waiters_count++;
+ sx_xlock(&rw->sx);
+ rw->waiters_count--;
+ }
+}
+
+void
+linuxkpi_up_write(struct rw_semaphore *rw)
+{
+ sx_xunlock(&rw->sx);
+}
+
+void
+linuxkpi_down_read(struct rw_semaphore *rw)
+{
+ if (!sx_try_slock(&rw->sx)) {
+ /* `rw->waiters_count` is used by `rwsem_is_contended()`. */
+ rw->waiters_count++;
+ sx_slock(&rw->sx);
+ rw->waiters_count--;
+ }
+}
+
+void
+linuxkpi_up_read(struct rw_semaphore *rw)
+{
+ sx_sunlock(&rw->sx);
+}
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4706,6 +4706,8 @@
compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_pci.c optional compat_linuxkpi pci \
compile-with "${LINUXKPI_C}"
+compat/linuxkpi/common/src/linux_rwsem.c optional compat_linuxkpi \
+ compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_tasklet.c optional compat_linuxkpi \
compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_idr.c optional compat_linuxkpi \
diff --git a/sys/modules/linuxkpi/Makefile b/sys/modules/linuxkpi/Makefile
--- a/sys/modules/linuxkpi/Makefile
+++ b/sys/modules/linuxkpi/Makefile
@@ -24,6 +24,7 @@
linux_pci.c \
linux_radix.c \
linux_rcu.c \
+ linux_rwsem.c \
linux_schedule.c \
linux_seq_buf.c \
linux_seq_file.c \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 26, 3:49 PM (10 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32176299
Default Alt Text
D56443.diff (4 KB)
Attached To
Mode
D56443: linuxkpi: Add `rwsem_is_contended()`
Attached
Detach File
Event Timeline
Log In to Comment