[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250913162540.77167-1-ammarfaizi2@gnuweeb.org>
Date: Sat, 13 Sep 2025 23:25:40 +0700
From: Ammar Faizi <ammarfaizi2@...weeb.org>
To: Jens Axboe <axboe@...nel.dk>
Cc: Ammar Faizi <ammarfaizi2@...weeb.org>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
io-uring Mailing List <io-uring@...r.kernel.org>,
Alviro Iskandar Setiawan <alviro.iskandar@...weeb.org>,
Bart Van Assche <bvanassche@....org>,
dr.xiaosa@...il.com
Subject: [PATCH liburing] liburing.h: Support C++20 module export feature
Having "static inline" functions in liburing header file results in
compilation errors when using the new C++20 module export feature:
In file included from src/work.cpp:3:
./include/liburing.h:343:20: error: \
‘void io_uring_cq_advance(io_uring*, unsigned int)’ \
exposes TU-local entity ‘void io_uring_smp_store_release(T*, T) [with T = unsigned int]’
343 | IOURINGINLINE void io_uring_cq_advance(struct io_uring *ring, unsigned nr)
| ^~~~~~~~~~~~~~~~~~~
In file included from ./include/liburing.h:20:
./include/liburing/barrier.h:42:20: note: \
‘void io_uring_smp_store_release(T*, T) [with T = unsigned int]’ is a \
specialization of TU-local template \
‘template<class T> void io_uring_smp_store_release(T*, T)’
42 | static inline void io_uring_smp_store_release(T *p, T v)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/liburing/barrier.h:42:20: note: \
‘template<class T> void io_uring_smp_store_release(T*, T)’ declared with internal linkage
Introduce a new macro _LOCAL_INLINE, which will expand to "inline"
instead of "static inline" if compiled using C++20 or later. Also, make
IOURINGINLINE behave the same way in the same condition.
No functional change is expected for C and older C++ versions.
Closes: https://github.com/axboe/liburing/issues/1457
Reported-by: @xiaosa-zhz # A GitHub user
Fixes: 3d74c677c45e ("Make the liburing header files again compatible with C++")
Fixes: f2b6fb85b79b ("liburing: Don't use `IOURINGINLINE` on private helpers")
Cc: dr.xiaosa@...il.com
Cc: Alviro Iskandar Setiawan <alviro.iskandar@...weeb.org>
Suggested-by: Bart Van Assche <bvanassche@....org>
Link: https://lore.kernel.org/io-uring/e0559c10-104d-4da8-9f7f-d2ffd73d8df3@acm.org
Signed-off-by: Ammar Faizi <ammarfaizi2@...weeb.org>
---
This patch is a follow up to:
"[PATCH liburing v1] barrier: Convert C++ barrier functions into macros".
Link: https://lore.kernel.org/io-uring/20250913131547.466233-1-ammarfaizi2@gnuweeb.org
src/include/liburing.h | 56 ++++++++++++++++++++++++++--------
src/include/liburing/barrier.h | 10 +++---
2 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index e3f394eab860..f9dcd52c1537 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -17,8 +17,6 @@
#include "liburing/compat.h"
#include "liburing/io_uring.h"
#include "liburing/io_uring_version.h"
-#include "liburing/barrier.h"
-
#ifndef uring_unlikely
#define uring_unlikely(cond) __builtin_expect(!!(cond), 0)
@@ -29,15 +27,45 @@
#endif
/*
- * NOTE: Only use IOURINGINLINE macro for 'static inline' functions
- * that are expected to be available in the FFI bindings.
+ * NOTE: Use IOURINGINLINE macro for "static inline" functions that are
+ * expected to be available in the FFI bindings. They must also
+ * be included in the liburing-ffi.map file.
+ *
+ * Use _LOCAL_INLINE macro for "static inline" functions that are
+ * not expected to be available in the FFI bindings.
+ *
+ * Don't use "static inline" directly when defining new functions
+ * in this header file.
+ *
+ * Reason:
+ * The C++20 module export feature fails to operate correctly
+ * with the "static inline" functions. Use "inline" instead of
+ * "static inline" when compiling with C++20 or later.
*
- * Functions that are marked as IOURINGINLINE should be
- * included in the liburing-ffi.map file.
+ * See:
+ * https://github.com/axboe/liburing/issues/1457
+ * https://lore.kernel.org/io-uring/e0559c10-104d-4da8-9f7f-d2ffd73d8df3@acm.org
*/
#ifndef IOURINGINLINE
+#if defined(__cplusplus) && __cplusplus >= 202002L
+#define IOURINGINLINE inline
+#else
#define IOURINGINLINE static inline
#endif
+#endif
+
+#ifndef _LOCAL_INLINE
+#if defined(__cplusplus) && __cplusplus >= 202002L
+#define _LOCAL_INLINE inline
+#else
+#define _LOCAL_INLINE static inline
+#endif
+#endif
+
+/*
+ * barrier.h needs _LOCAL_INLINE.
+ */
+#include "liburing/barrier.h"
#ifdef __alpha__
/*
@@ -159,7 +187,7 @@ struct io_uring_zcrx_rq {
* Library interface
*/
-static inline __u64 uring_ptr_to_u64(const void *ptr) LIBURING_NOEXCEPT
+_LOCAL_INLINE __u64 uring_ptr_to_u64(const void *ptr) LIBURING_NOEXCEPT
{
return (__u64) (unsigned long) ptr;
}
@@ -402,7 +430,7 @@ struct io_uring_cqe_iter {
unsigned tail;
};
-static inline struct io_uring_cqe_iter
+_LOCAL_INLINE struct io_uring_cqe_iter
io_uring_cqe_iter_init(const struct io_uring *ring)
LIBURING_NOEXCEPT
{
@@ -416,7 +444,7 @@ io_uring_cqe_iter_init(const struct io_uring *ring)
};
}
-static inline bool io_uring_cqe_iter_next(struct io_uring_cqe_iter *iter,
+_LOCAL_INLINE bool io_uring_cqe_iter_next(struct io_uring_cqe_iter *iter,
struct io_uring_cqe **cqe)
LIBURING_NOEXCEPT
{
@@ -522,7 +550,7 @@ IOURINGINLINE void io_uring_sqe_set_buf_group(struct io_uring_sqe *sqe,
sqe->buf_group = (__u16) bgid;
}
-static inline void __io_uring_set_target_fixed_file(struct io_uring_sqe *sqe,
+_LOCAL_INLINE void __io_uring_set_target_fixed_file(struct io_uring_sqe *sqe,
unsigned int file_index)
LIBURING_NOEXCEPT
{
@@ -704,7 +732,7 @@ IOURINGINLINE void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd,
sqe->msg_flags = flags;
}
-static inline unsigned __io_uring_prep_poll_mask(unsigned poll_mask)
+_LOCAL_INLINE unsigned __io_uring_prep_poll_mask(unsigned poll_mask)
LIBURING_NOEXCEPT
{
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -1742,7 +1770,7 @@ IOURINGINLINE int io_uring_wait_cqe_nr(struct io_uring *ring,
* "official" versions of this, io_uring_peek_cqe(), io_uring_wait_cqe(),
* or io_uring_wait_cqes*().
*/
-static inline int __io_uring_peek_cqe(struct io_uring *ring,
+_LOCAL_INLINE int __io_uring_peek_cqe(struct io_uring *ring,
struct io_uring_cqe **cqe_ptr,
unsigned *nr_available)
LIBURING_NOEXCEPT
@@ -1987,4 +2015,8 @@ bool io_uring_check_version(int major, int minor) LIBURING_NOEXCEPT;
#undef IOURINGINLINE
#endif
+#ifdef _LOCAL_INLINE
+#undef _LOCAL_INLINE
+#endif
+
#endif
diff --git a/src/include/liburing/barrier.h b/src/include/liburing/barrier.h
index 985569f496a8..0ae77b16ecf3 100644
--- a/src/include/liburing/barrier.h
+++ b/src/include/liburing/barrier.h
@@ -26,14 +26,14 @@ after the acquire operation executes. This is implemented using
#define LIBURING_NOEXCEPT noexcept
template <typename T>
-static inline void IO_URING_WRITE_ONCE(T &var, T val)
+_LOCAL_INLINE void IO_URING_WRITE_ONCE(T &var, T val)
LIBURING_NOEXCEPT
{
std::atomic_store_explicit(reinterpret_cast<std::atomic<T> *>(&var),
val, std::memory_order_relaxed);
}
template <typename T>
-static inline T IO_URING_READ_ONCE(const T &var)
+_LOCAL_INLINE T IO_URING_READ_ONCE(const T &var)
LIBURING_NOEXCEPT
{
return std::atomic_load_explicit(
@@ -42,7 +42,7 @@ static inline T IO_URING_READ_ONCE(const T &var)
}
template <typename T>
-static inline void io_uring_smp_store_release(T *p, T v)
+_LOCAL_INLINE void io_uring_smp_store_release(T *p, T v)
LIBURING_NOEXCEPT
{
std::atomic_store_explicit(reinterpret_cast<std::atomic<T> *>(p), v,
@@ -50,7 +50,7 @@ static inline void io_uring_smp_store_release(T *p, T v)
}
template <typename T>
-static inline T io_uring_smp_load_acquire(const T *p)
+_LOCAL_INLINE T io_uring_smp_load_acquire(const T *p)
LIBURING_NOEXCEPT
{
return std::atomic_load_explicit(
@@ -58,7 +58,7 @@ static inline T io_uring_smp_load_acquire(const T *p)
std::memory_order_acquire);
}
-static inline void io_uring_smp_mb()
+_LOCAL_INLINE void io_uring_smp_mb()
LIBURING_NOEXCEPT
{
std::atomic_thread_fence(std::memory_order_seq_cst);
base-commit: 97c596056b81488b86ff300cdbaf06471af3cc6e
--
Ammar Faizi
Powered by blists - more mailing lists