Skip to content

Commit b716e40

Browse files
committed
Linux: varhandle for array access
1 parent be72c50 commit b716e40

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

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

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,23 @@
2222

2323
@SuppressWarnings({"OptionalGetWithoutIsPresent", "SameParameterValue", "java:S100"})
2424
public class EPoll {
25+
// Memory layout for an array of epoll_event structs
26+
private static final SequenceLayout EVENT_ARRAY$LAYOUT = MemoryLayout.sequenceLayout(epoll_event.$LAYOUT());
27+
28+
// varhandle to access the "fd" field in an array of epoll_event structs
29+
static final VarHandle EVENT_ARRAY_DATA_FD$VH = EVENT_ARRAY$LAYOUT.varHandle(
30+
MemoryLayout.PathElement.sequenceElement(),
31+
MemoryLayout.PathElement.groupElement("data"),
32+
MemoryLayout.PathElement.groupElement("fd")
33+
);
34+
35+
// varhandle to access the "fd" field in an epoll_event struct
36+
static final VarHandle EVENT_DATA_FD$VH = epoll_event.$LAYOUT().varHandle(
37+
MemoryLayout.PathElement.groupElement("data"),
38+
MemoryLayout.PathElement.groupElement("fd")
39+
);
40+
41+
2542
private EPoll() {}
2643

2744
private static final Linker linker = Linker.nativeLinker();
@@ -38,11 +55,6 @@ private EPoll() {}
3855
private static final MethodHandle epoll_wait$MH = linker.downcallHandle(linker.defaultLookup().find(
3956
"epoll_wait").get(), epoll_wait$FUNC, Linux.ERRNO_STATE);
4057

41-
private static final VarHandle epoll_event_data_fd$VH = epoll_event.$LAYOUT().varHandle(
42-
MemoryLayout.PathElement.groupElement("data"),
43-
MemoryLayout.PathElement.groupElement("fd")
44-
);
45-
4658
static int epoll_create(int size, MemorySegment errno) {
4759
try {
4860
return (int) epoll_create$MH.invokeExact(errno, size);
@@ -73,7 +85,7 @@ static void addFileDescriptor(int epfd, int op, int fd) {
7385

7486
var event = arena.allocate(epoll_event.$LAYOUT());
7587
epoll_event.events$set(event, op);
76-
epoll_event_data_fd$VH.set(event, fd);
88+
EVENT_DATA_FD$VH.set(event, fd);
7789
var ret = epoll_ctl(epfd, EPOLL_CTL_ADD(), fd, event, errorState);
7890
if (ret < 0)
7991
throwLastError(errorState, "internal error (epoll_ctl_add)");
@@ -86,7 +98,7 @@ static void removeFileDescriptor(int epfd, int fd) {
8698

8799
var event = arena.allocate(epoll_event.$LAYOUT());
88100
epoll_event.events$set(event, 0);
89-
epoll_event_data_fd$VH.set(event, fd);
101+
EVENT_DATA_FD$VH.set(event, fd);
90102
var ret = epoll_ctl(epfd, EPOLL_CTL_DEL(), fd, event, errorState);
91103
if (ret < 0) {
92104
var err = Linux.getErrno(errorState);

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

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevfs_urb;
1414

1515
import java.lang.foreign.Arena;
16-
import java.lang.foreign.MemoryLayout;
1716
import java.lang.foreign.MemorySegment;
18-
import java.lang.invoke.VarHandle;
1917
import java.util.ArrayList;
2018
import java.util.LinkedHashMap;
2119
import java.util.List;
@@ -57,11 +55,6 @@ class LinuxAsyncTask {
5755

5856
private static final int NUM_EVENTS = 5;
5957

60-
private static final VarHandle epoll_event_data_fd$VH = epoll_event.$LAYOUT().varHandle(
61-
MemoryLayout.PathElement.groupElement("data"),
62-
MemoryLayout.PathElement.groupElement("fd")
63-
);
64-
6558
private final Arena urbArena = Arena.ofAuto();
6659
/// available URBs
6760
private final List<MemorySegment> availableURBs = new ArrayList<>();
@@ -87,16 +80,18 @@ private void asyncCompletionTask() {
8780

8881
while (true) {
8982

83+
// wait for file descriptor to be ready
9084
var res = epoll_wait(epollFd, events, NUM_EVENTS, -1, errorState);
9185
if (res < 0) {
9286
var err = Linux.getErrno(errorState);
9387
if (err == EINTR())
94-
continue;
88+
continue; // continue on interrupt
9589
throwException(err, "internal error (epoll_wait)");
9690
}
9791

92+
// for all ready file descriptors, reap URBs
9893
for (int i = 0; i < res; i++) {
99-
var fd = (int) epoll_event_data_fd$VH.get(events.asSlice(epoll_event.sizeof() * i, epoll_event.sizeof()));
94+
var fd = (int) EPoll.EVENT_ARRAY_DATA_FD$VH.get(events, i);
10095
reapURBs(fd, urbPointerHolder, errorState);
10196
}
10297
}
@@ -111,6 +106,7 @@ private void asyncCompletionTask() {
111106
* @param errorState native memory to receive the errno
112107
*/
113108
private void reapURBs(int fd, MemorySegment urbPointerHolder, MemorySegment errorState) {
109+
114110
while (true) {
115111
var res = IO.ioctl(fd, REAPURBNDELAY, urbPointerHolder, errorState);
116112
if (res < 0) {
@@ -119,7 +115,7 @@ private void reapURBs(int fd, MemorySegment urbPointerHolder, MemorySegment erro
119115
return; // no more pending URBs
120116
if (err == errno.ENODEV()) {
121117
// device might have been unplugged
122-
removeFdFromAsyncIOCompletion(fd);
118+
EPoll.removeFileDescriptor(epollFd, fd);
123119
return;
124120
}
125121
throwException(err, "internal error (reap URB)");
@@ -154,13 +150,9 @@ synchronized void removeFromAsyncIOCompletion(LinuxUsbDevice device) {
154150
EPoll.removeFileDescriptor(epollFd, device.fileDescriptor());
155151
}
156152

157-
private synchronized void removeFdFromAsyncIOCompletion(int fd) {
158-
EPoll.removeFileDescriptor(epollFd, fd);
159-
}
160-
161153
synchronized void submitTransfer(LinuxUsbDevice device, int endpointAddress, UsbTransferType transferType, LinuxTransfer transfer) {
162154

163-
addURB(transfer);
155+
linkToUrb(transfer);
164156
var urb = transfer.urb;
165157

166158
usbdevfs_urb.type$set(urb, (byte) urbTransferType(transferType));
@@ -188,7 +180,15 @@ private static int urbTransferType(UsbTransferType transferType) {
188180
};
189181
}
190182

191-
private void addURB(LinuxTransfer transfer) {
183+
/**
184+
* Links the specified transfer instance to a URB.
185+
* <p>
186+
* The transfer is assigned an URB instance, and a list
187+
* of associations from URB to transfer is maintained.
188+
* </p>
189+
* @param transfer the transfer to assign a URB.
190+
*/
191+
private void linkToUrb(LinuxTransfer transfer) {
192192
MemorySegment urb;
193193
var size = availableURBs.size();
194194
if (size > 0) {
@@ -201,6 +201,15 @@ private void addURB(LinuxTransfer transfer) {
201201
transfersByURB.put(urb, transfer);
202202
}
203203

204+
/**
205+
* Gets the transfer associated with the specified URB.
206+
* <p>
207+
* The URB is returned into the list of URBs available for further transfers.
208+
* </p>
209+
*
210+
* @param urb URB instance
211+
* @return transfer associated with the URB
212+
*/
204213
@SuppressWarnings("java:S2259")
205214
private synchronized LinuxTransfer getTransferResult(MemorySegment urb) {
206215
var transfer = transfersByURB.remove(urb);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class UsbDevFS {
1919
private UsbDevFS() {
2020
}
2121

22+
// constants that jextract cannot generate as they are built from function-like macros
2223
static final long CLAIMINTERFACE = 0x8004550FL;
2324
static final long RELEASEINTERFACE = 0x80045510L;
2425
static final long SETINTERFACE = 0x80085504L;

0 commit comments

Comments
 (0)