Skip to content

Commit ae9f7e2

Browse files
committed
Linux ARM64: fix incompatibility with epoll
1 parent f4ef64e commit ae9f7e2

File tree

7 files changed

+44
-495
lines changed

7 files changed

+44
-495
lines changed

java-does-usb/jextract/linux/gen_linux.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
JEXTRACT=../../../../jextract/bin/jextract
3+
JEXTRACT=../../../../jextract/build/jextract/bin/jextract
44

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

@@ -89,8 +89,6 @@ $JEXTRACT --output ../../src/main/java \
8989
$JEXTRACT --output ../../src/main/java \
9090
--header-class-name epoll \
9191
--target-package net.codecrete.usb.linux.gen.epoll \
92-
--include-struct epoll_event \
93-
--include-union epoll_data \
9492
--include-constant EPOLL_CTL_ADD \
9593
--include-constant EPOLL_CTL_DEL \
9694
--include-constant EPOLLIN \

java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,54 @@
77

88
package net.codecrete.usb.linux;
99

10-
import net.codecrete.usb.linux.gen.epoll.epoll_event;
1110
import net.codecrete.usb.linux.gen.errno.errno;
1211

1312
import java.lang.foreign.Arena;
1413
import java.lang.foreign.FunctionDescriptor;
14+
import java.lang.foreign.GroupLayout;
1515
import java.lang.foreign.Linker;
1616
import java.lang.foreign.MemoryLayout;
1717
import java.lang.foreign.MemorySegment;
1818
import java.lang.foreign.SequenceLayout;
19+
import java.lang.foreign.MemoryLayout.PathElement;
20+
import java.lang.foreign.ValueLayout.OfInt;
1921
import java.lang.invoke.MethodHandle;
2022
import java.lang.invoke.VarHandle;
2123

2224
import static java.lang.foreign.ValueLayout.ADDRESS;
25+
import static java.lang.foreign.ValueLayout.ADDRESS_UNALIGNED;
2326
import static java.lang.foreign.ValueLayout.JAVA_INT;
27+
import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED;
28+
import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
2429
import static net.codecrete.usb.linux.Linux.allocateErrorState;
2530
import static net.codecrete.usb.linux.LinuxUsbException.throwLastError;
2631
import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_ADD;
2732
import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_DEL;
2833

2934
@SuppressWarnings({"OptionalGetWithoutIsPresent", "SameParameterValue", "java:S100"})
3035
public class EPoll {
36+
private EPoll() {}
37+
38+
private static final boolean IS_AARCH64 = System.getProperty("os.arch").equals("aarch64");
39+
40+
private static final GroupLayout DATA$LAYOUT = MemoryLayout.unionLayout(
41+
ADDRESS_UNALIGNED.withName("ptr"),
42+
JAVA_INT_UNALIGNED.withName("fd"),
43+
JAVA_INT_UNALIGNED.withName("u32"),
44+
JAVA_LONG_UNALIGNED.withName("u64")
45+
).withName("epoll_data");
46+
47+
static final GroupLayout EVENT$LAYOUT = IS_AARCH64
48+
? MemoryLayout.structLayout(
49+
JAVA_INT.withName("events"),
50+
MemoryLayout.paddingLayout(4),
51+
DATA$LAYOUT.withName("data")).withName("epoll_event")
52+
: MemoryLayout.structLayout(
53+
JAVA_INT_UNALIGNED.withName("events"),
54+
DATA$LAYOUT.withName("data")).withName("epoll_event");
55+
3156
// Memory layout for an array of epoll_event structs
32-
private static final SequenceLayout EVENT_ARRAY$LAYOUT = MemoryLayout.sequenceLayout(1, epoll_event.layout());
57+
private static final SequenceLayout EVENT_ARRAY$LAYOUT = MemoryLayout.sequenceLayout(1, EVENT$LAYOUT);
3358

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

4166
// varhandle to access the "fd" field in an epoll_event struct
42-
static final VarHandle EVENT_DATA_FD$VH = epoll_event.layout().varHandle(
67+
static final VarHandle EVENT_DATA_FD$VH = EVENT$LAYOUT.varHandle(
4368
MemoryLayout.PathElement.groupElement("data"),
4469
MemoryLayout.PathElement.groupElement("fd")
4570
);
4671

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

48-
private EPoll() {}
74+
private static void event_events(MemorySegment struct, int fieldValue) {
75+
struct.set(EVENT_EVENTS$LAYOUT, 0, fieldValue);
76+
}
4977

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

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

92-
var event = arena.allocate(epoll_event.layout());
93-
epoll_event.events(event, op);
120+
var event = arena.allocate(EVENT$LAYOUT);
121+
event_events(event, op);
94122
EVENT_DATA_FD$VH.set(event, 0, fd);
95123
var ret = epoll_ctl(epfd, EPOLL_CTL_ADD(), fd, event, errorState);
96124
if (ret < 0)
@@ -102,8 +130,8 @@ static void removeFileDescriptor(int epfd, int fd) {
102130
try (var arena = Arena.ofConfined()) {
103131
var errorState = allocateErrorState(arena);
104132

105-
var event = arena.allocate(epoll_event.layout());
106-
epoll_event.events(event, 0);
133+
var event = arena.allocate(EVENT$LAYOUT);
134+
event_events(event, 0);
107135
EVENT_DATA_FD$VH.set(event, 0, fd);
108136
var ret = epoll_ctl(epfd, EPOLL_CTL_DEL(), fd, event, errorState);
109137
if (ret < 0) {

java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxAsyncTask.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
package net.codecrete.usb.linux;
99

1010
import net.codecrete.usb.UsbTransferType;
11-
import net.codecrete.usb.linux.gen.epoll.epoll_event;
1211
import net.codecrete.usb.linux.gen.errno.errno;
1312
import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevfs_urb;
1413

@@ -84,7 +83,7 @@ private void asyncCompletionTask() {
8483
try (var arena = Arena.ofConfined()) {
8584
var errorState = allocateErrorState(arena);
8685
var urbPointerHolder = arena.allocate(ADDRESS);
87-
var events = arena.allocate(epoll_event.layout(), NUM_EVENTS);
86+
var events = arena.allocate(EPoll.EVENT$LAYOUT, NUM_EVENTS);
8887

8988
while (true) {
9089

java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDeviceRegistry.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import net.codecrete.usb.UsbDevice;
1111
import net.codecrete.usb.common.ScopeCleanup;
1212
import net.codecrete.usb.common.UsbDeviceRegistry;
13-
import net.codecrete.usb.linux.gen.epoll.epoll_event;
1413
import net.codecrete.usb.linux.gen.udev.udev;
1514

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

113112
// allocate event (as output for epoll_wait)
114-
var event = arena.allocate(epoll_event.layout());
113+
var event = arena.allocate(EPoll.EVENT$LAYOUT);
115114

116115
// monitor device changes
117116
//noinspection InfiniteLoopStatement

0 commit comments

Comments
 (0)