Skip to content

Commit

Permalink
Linux ARM64: fix incompatibility with epoll
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelbl committed Mar 16, 2024
1 parent f4ef64e commit ae9f7e2
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 495 deletions.
4 changes: 1 addition & 3 deletions java-does-usb/jextract/linux/gen_linux.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

JEXTRACT=../../../../jextract/bin/jextract
JEXTRACT=../../../../jextract/build/jextract/bin/jextract

rm -rf ../../src/main/java/net/codecrete/usb/linux/gen

Expand Down Expand Up @@ -89,8 +89,6 @@ $JEXTRACT --output ../../src/main/java \
$JEXTRACT --output ../../src/main/java \
--header-class-name epoll \
--target-package net.codecrete.usb.linux.gen.epoll \
--include-struct epoll_event \
--include-union epoll_data \
--include-constant EPOLL_CTL_ADD \
--include-constant EPOLL_CTL_DEL \
--include-constant EPOLLIN \
Expand Down
44 changes: 36 additions & 8 deletions java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,54 @@

package net.codecrete.usb.linux;

import net.codecrete.usb.linux.gen.epoll.epoll_event;
import net.codecrete.usb.linux.gen.errno.errno;

import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.GroupLayout;
import java.lang.foreign.Linker;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SequenceLayout;
import java.lang.foreign.MemoryLayout.PathElement;
import java.lang.foreign.ValueLayout.OfInt;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;

import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.ADDRESS_UNALIGNED;
import static java.lang.foreign.ValueLayout.JAVA_INT;
import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED;
import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
import static net.codecrete.usb.linux.Linux.allocateErrorState;
import static net.codecrete.usb.linux.LinuxUsbException.throwLastError;
import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_ADD;
import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_DEL;

@SuppressWarnings({"OptionalGetWithoutIsPresent", "SameParameterValue", "java:S100"})
public class EPoll {
private EPoll() {}

private static final boolean IS_AARCH64 = System.getProperty("os.arch").equals("aarch64");

private static final GroupLayout DATA$LAYOUT = MemoryLayout.unionLayout(
ADDRESS_UNALIGNED.withName("ptr"),
JAVA_INT_UNALIGNED.withName("fd"),
JAVA_INT_UNALIGNED.withName("u32"),
JAVA_LONG_UNALIGNED.withName("u64")
).withName("epoll_data");

static final GroupLayout EVENT$LAYOUT = IS_AARCH64
? MemoryLayout.structLayout(
JAVA_INT.withName("events"),
MemoryLayout.paddingLayout(4),
DATA$LAYOUT.withName("data")).withName("epoll_event")
: MemoryLayout.structLayout(
JAVA_INT_UNALIGNED.withName("events"),
DATA$LAYOUT.withName("data")).withName("epoll_event");

// Memory layout for an array of epoll_event structs
private static final SequenceLayout EVENT_ARRAY$LAYOUT = MemoryLayout.sequenceLayout(1, epoll_event.layout());
private static final SequenceLayout EVENT_ARRAY$LAYOUT = MemoryLayout.sequenceLayout(1, EVENT$LAYOUT);

// varhandle to access the "fd" field in an array of epoll_event structs
static final VarHandle EVENT_ARRAY_DATA_FD$VH = EVENT_ARRAY$LAYOUT.varHandle(
Expand All @@ -39,13 +64,16 @@ public class EPoll {
);

// varhandle to access the "fd" field in an epoll_event struct
static final VarHandle EVENT_DATA_FD$VH = epoll_event.layout().varHandle(
static final VarHandle EVENT_DATA_FD$VH = EVENT$LAYOUT.varHandle(
MemoryLayout.PathElement.groupElement("data"),
MemoryLayout.PathElement.groupElement("fd")
);

private static final OfInt EVENT_EVENTS$LAYOUT = (OfInt)EVENT$LAYOUT.select(PathElement.groupElement("events"));

private EPoll() {}
private static void event_events(MemorySegment struct, int fieldValue) {
struct.set(EVENT_EVENTS$LAYOUT, 0, fieldValue);
}

private static final Linker linker = Linker.nativeLinker();

Expand Down Expand Up @@ -89,8 +117,8 @@ static void addFileDescriptor(int epfd, int op, int fd) {
try (var arena = Arena.ofConfined()) {
var errorState = allocateErrorState(arena);

var event = arena.allocate(epoll_event.layout());
epoll_event.events(event, op);
var event = arena.allocate(EVENT$LAYOUT);
event_events(event, op);
EVENT_DATA_FD$VH.set(event, 0, fd);
var ret = epoll_ctl(epfd, EPOLL_CTL_ADD(), fd, event, errorState);
if (ret < 0)
Expand All @@ -102,8 +130,8 @@ static void removeFileDescriptor(int epfd, int fd) {
try (var arena = Arena.ofConfined()) {
var errorState = allocateErrorState(arena);

var event = arena.allocate(epoll_event.layout());
epoll_event.events(event, 0);
var event = arena.allocate(EVENT$LAYOUT);
event_events(event, 0);
EVENT_DATA_FD$VH.set(event, 0, fd);
var ret = epoll_ctl(epfd, EPOLL_CTL_DEL(), fd, event, errorState);
if (ret < 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package net.codecrete.usb.linux;

import net.codecrete.usb.UsbTransferType;
import net.codecrete.usb.linux.gen.epoll.epoll_event;
import net.codecrete.usb.linux.gen.errno.errno;
import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevfs_urb;

Expand Down Expand Up @@ -84,7 +83,7 @@ private void asyncCompletionTask() {
try (var arena = Arena.ofConfined()) {
var errorState = allocateErrorState(arena);
var urbPointerHolder = arena.allocate(ADDRESS);
var events = arena.allocate(epoll_event.layout(), NUM_EVENTS);
var events = arena.allocate(EPoll.EVENT$LAYOUT, NUM_EVENTS);

while (true) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import net.codecrete.usb.UsbDevice;
import net.codecrete.usb.common.ScopeCleanup;
import net.codecrete.usb.common.UsbDeviceRegistry;
import net.codecrete.usb.linux.gen.epoll.epoll_event;
import net.codecrete.usb.linux.gen.udev.udev;

import java.lang.foreign.Arena;
Expand Down Expand Up @@ -111,7 +110,7 @@ protected void monitorDevices() {
EPoll.addFileDescriptor(epfd, EPOLLIN(), monitorFd);

// allocate event (as output for epoll_wait)
var event = arena.allocate(epoll_event.layout());
var event = arena.allocate(EPoll.EVENT$LAYOUT);

// monitor device changes
//noinspection InfiniteLoopStatement
Expand Down
Loading

0 comments on commit ae9f7e2

Please sign in to comment.