Getting "UnsatisfiedLinkError" in io_uring for methods that were defined as "static inline" in the header

Sundararajan Athijegannathan sundararajan.athijegannathan at oracle.com
Mon Oct 3 03:11:47 UTC 2022


Cool! Thanks for the sharing the sample with us.

-Sundar
________________________________
From: panama-dev <panama-dev-retn at openjdk.org> on behalf of Gavin Ray <ray.gavin97 at gmail.com>
Sent: 02 October 2022 09:07
To: Jorn Vernee <jorn.vernee at oracle.com>
Cc: Maurizio Cimadamore <maurizio.cimadamore at oracle.com>; panama-dev at openjdk.org <panama-dev at openjdk.org>
Subject: Re: Getting "UnsatisfiedLinkError" in io_uring for methods that were defined as "static inline" in the header

Just wanted to update anyone interested/following here

I've been on a work trip the past week so had very little free time
Tonight, I managed to get a "cat" like program working, that reads a file using io_uring

The code is here:
https://github.com/GavinRay97/panama-liburing/blob/6a80673e73cfcf773212ee068b808f2b9d628df6/lib/src/test/java/panama/liburing/LibraryTest.java#L40-L137

It's not much, but it's a great start IMO
The test tries to read the file here:

https://github.com/GavinRay97/panama-liburing/blob/master/lib/src/test/resources/test.txt#L1

[image.png]

On Sat, Sep 24, 2022 at 8:37 AM Gavin Ray <ray.gavin97 at gmail.com<mailto:ray.gavin97 at gmail.com>> wrote:
Jorn, thank you so much, a small oversight but it broke everything
Your suggestion worked, I wish I could kiss you!

How cool is this?!
Now, to polish it up, write tests + examples, and document it so it can be published for public use as Maven library:
[image.png]

On Sat, Sep 24, 2022 at 8:26 AM Jorn Vernee <jorn.vernee at oracle.com<mailto:jorn.vernee at oracle.com>> wrote:

It looks like io_uring_wait_cqe [1] takes as second argument a pointer to a pointer, but you pass it an pointer to a struct.

I think it should be:

    // struct io_uring_cqe **cqeRef = malloc(sizeof *cqeRef);
    MemorySegment cqeRef = MemorySegment.allocateNative(C_POINTER, session);
    io_uring_wait_cqe(ring, cqeRef);
    // struct io_uring_cqe *cqe = *cqeRef;
    MemoryAddress cqe = cqeRef.get(C_POINTER, 0);

    MemoryAddress user_data = io_uring_cqe_get_data(cqe);
    MemorySegment user_data_segment = MemorySegment.ofAddress(user_data, myStructLayout.byteSize(), session);

Note that MemorySegment::asSlice doesn't perform any dereference, so it is not equivalent to `cqes[0]`.

Jorn

[1]: https://man.archlinux.org/man/extra/liburing/io_uring_wait_cqe.3.en

On 23/09/2022 22:15, Gavin Ray wrote:
Okay, it seems I've gotten the "hello world" almost working

The only problem left is that trying to read the "user_data" pointer returned gives garbage.
When I submit the event, I attach a struct to it, like this:

        MemorySegment myStruct = MemorySegment.allocateNative(myStructLayout, session);
        myStruct$foo.set(myStruct, 1);
        myStruct$bar.set(myStruct, 2);
        io_uring_sqe_set_data(sqePtr, myStruct);

Then when the results come back, I am doing this to read the userdata pointer:

        MemorySegment cqes = io_uring_cqe.allocateArray(1, allocator);
        io_uring_wait_cqe(ring, cqes);
        // cqes[0]
        MemorySegment cqe = cqes.asSlice(0, io_uring_cqe.$LAYOUT().byteSize());
        // cqes[0]->user_data
        MemoryAddress user_data = MemoryAddress.ofLong(io_uring_cqe.user_data$get(cqe));
        MemorySegment user_data_segment = MemorySegment.ofAddress(user_data, myStructLayout.byteSize(), session);

I try to print it out, comparing the "foo" and "bar" field against the original values of "1" and "2"

        user_data->foo=1480561120
        user_data->bar=32545

Does anyone know/see what I am doing wrong here? 🤔
https://gist.github.com/GavinRay97/8ea0997693c00f8df61968a98ba30135#file-io_uring-java-L48-L55

On Wed, Sep 21, 2022 at 8:18 PM Gavin Ray <ray.gavin97 at gmail.com<mailto:ray.gavin97 at gmail.com>> wrote:
@Daniel, I didn't know the lwjgl folks were looking into this area, I've had a brief look but it's definitely something I want to check out more!

@Maurizio, the idea about defining a second library that depends on it is pretty clever.

It turns out that you can pull liburing in with CMake without so much effort
To set that scenario up was just the below code, this should work decently 👍

=============================
ExternalProject_Add(
        liburing_git
        GIT_REPOSITORY http://github.com/axboe/liburing.git
        GIT_TAG liburing-2.2
        BUILD_IN_SOURCE 1
        BUILD_BYPRODUCTS "<SOURCE_DIR>/src/liburing.a"
        BUILD_COMMAND make
)
ExternalProject_Get_Property(liburing_git SOURCE_DIR)
add_library(liburing INTERFACE)
add_dependencies(liburing liburing_git)
target_include_directories(liburing INTERFACE ${SOURCE_DIR}/src/include)
target_link_libraries(liburing INTERFACE ${SOURCE_DIR}/src/liburing.a)

# NOW LINK IT TO SECOND LIBRARY
add_library(liburing_extras SHARED liburing_extras/main.c)
target_link_libraries(liburing_extras liburing)
add_dependencies(liburing_extras liburing)


On Wed, Sep 21, 2022 at 7:24 PM Maurizio Cimadamore <maurizio.cimadamore at oracle.com<mailto:maurizio.cimadamore at oracle.com>> wrote:

On 21/09/2022 23:39, Gavin Ray wrote:
> That makes sense -- I will look at patching liburing with a dirty
> one-liner that strips "static inline" from the definitions that have
> them then, ty =)

Sorry, hit send too fast, and forgot to reply to this.

There are few approaches that can be tried.

First, you could define another shared library that depends on io_uring
- e.g. a C file which includes the io_uring header. This new file would
contain _new_ exported symbols for all the static inline functions,
whose implementation just delegates to the underlying static inline
functions (in the included io_uring header). Then you load up the
library with Panama and, if you have set up things correctly, you will
see both the static inlines and the exported symbols in IO uring. (in
fact, we do a similar trick to expose system library symbols like
"printf" on Windows, which implements them as macros).

Another (more fun?) option would be to just keep the original library,
and implement the static inline functions in Java directly, using the
FFM API. Most of the functions I see have only 2-3 lines in them, so it
shouldn't be hard.

Maurizio

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20221003/2adbe333/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 133056 bytes
Desc: image.png
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20221003/2adbe333/image-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 23844 bytes
Desc: image.png
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20221003/2adbe333/image-0003.png>


More information about the panama-dev mailing list