`io_uring_opcode_supported` should be compiled
As it stands now, io_uring_opcode_supported is currently a static inline function in the liburing.h header file.
This is fine for C and C++ code. However, it makes this library more difficult to use from languages like Rust or from other language's FFIs.
The function appears trivial but relies on the struct definition.
io_uring_opcode_supported should be compiled and appear in the resulting .a/.so.
We can probably probably weak versions of the static inline ones. What do you currently do for the other functions, like io_uring_cqe_seen() or io_uring_cq_advance()?
What I'm doing now in my Rust project is just creating an intermediate .c file that contains stuff like:
#include <liburing.h>
int rio_io_uring_opcode_supported(const struct io_uring_probe *p,
int op)
{
return io_uring_opcode_supported(p, op);
}
and then I'll compile this to a static archive which I link against in the final binary.
Related: https://github.com/axboe/liburing/issues/660#issuecomment-1328533871 ...
@axboe I ran into the same issue calling
liburingfrom Julia.I am guessing that the same issue will effect each new language that wants to interface with
liburing.Would you consider adding a C file to the library with functions something like
_noinline__io_uring_prep_poll_add()to wrap each of thestatic inlinefunctions ?The alternatives are:
- Each language interface library builds its own C wrapper for the
static inlinefunctions- Each language interface library translates the content of the
static inlinefunctions into the target language.Either of these alternatives increase the risk of errors due to repetition of work. It would be really great to be able to talk to
liburingdirectly from non-C languages without relying on a hand-coded shim, or patch set that ends up being out of date.
Actually, @axboe, I can implement whatever changes you'd like here. I've been consistently wrapping all these liburing functions in my Rust code and it's easier to just fix it at the source.
Just do what will work for you, I suspect the other use cases are identical or very similar.
@cmazakas, are you suggesting that you will submit a PR to axboe/liburing that contains the rio_io_uring_*() functions from your rio/src/liburing/lib.c ?
This would be great!
(I assume the rio_ prefix will be changed to something else.)
If you are concerned about performance it would maybe make more sense to reimplement inline functions natively in Rust? However I'm not sure what the caveats would be with upgrading the library, and so you might need some additional automated testing here
@DylanZA, the problem I encountered when I started along the path of translating inline functions was that I quickly arrived at macro code that is all magical gcc attributes built-in functions (see below).
It might end up being worthwhile to translate this code at some point to avoid an extra C-function call. However, the primary goal is to get algorithmic level performance improvements by using io_uring's async notification and buffer sharing features.
https://github.com/axboe/liburing/blob/9bdeca7004ab10883437ed1a4bb016fa58fd60f6/src/include/liburing/barrier.h#L70-L72
https://github.com/gcc-mirror/gcc/blob/9a265c974cd85b8eae5ea607185e689f063db4a1/gcc/ginclude/stdatomic.h#L129-L135
#define atomic_store_explicit(PTR, VAL, MO) \
__extension__ \
({ \
__auto_type __atomic_store_ptr = (PTR); \
__typeof__ ((void)0, *__atomic_store_ptr) __atomic_store_tmp = (VAL); \
__atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \
})
I was more or less thinking about actually turning the static inline into a macro and then creating an extra archive file that contains all the symbols.
Basically, define the macro to be empty, include the liburing.h header in a source file and then compiling that and turning it into a library that'd live alongside liburing.a
To this end, existing liburing users aren't affected and "us" (the FFI folk) now have an archive that exports all the symbols we want.
I have yet to experiment with this though to test its viability.
Alright, I have a small branch going right now with a simple static archive being generated
https://github.com/cmazakas/liburing/tree/liburing-ffi
Seems like everything is able to link (haven't run any binaries yet) and objdump seems to confirm that everything is being exported.
I'll add support for shared objects next and then I think it should be good to go!