lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ