Skip to content

Commit

Permalink
Linux: use epoll instead of poll
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelbl committed Dec 27, 2023
1 parent 2978e08 commit be72c50
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 422 deletions.
3 changes: 3 additions & 0 deletions java-does-usb/jextract/linux/epoll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
#include <sys/epoll.h>
30 changes: 11 additions & 19 deletions java-does-usb/jextract/linux/gen_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ $JEXTRACT --source --output ../../src/main/java \
--include-constant EAGAIN \
--include-constant EINVAL \
--include-constant ENODEV \
--include-constant EINTR \
--include-constant ENOENT \
/usr/include/errno.h

# string.h
Expand Down Expand Up @@ -45,16 +47,6 @@ $JEXTRACT --source --output ../../src/main/java \
--include-struct usbdevfs_urb \
--include-struct usbdevfs_disconnect_claim \
--include-struct usbdevfs_ioctl \
--include-constant USBDEVFS_CONTROL \
--include-constant USBDEVFS_BULK \
--include-constant USBDEVFS_CLAIMINTERFACE \
--include-constant USBDEVFS_RELEASEINTERFACE \
--include-constant USBDEVFS_SETINTERFACE \
--include-constant USBDEVFS_CLEAR_HALT \
--include-constant USBDEVFS_SUBMITURB \
--include-constant USBDEVFS_DISCARDURB \
--include-constant USBDEVFS_REAPURB \
--include-constant USBDEVFS_DISCONNECT_CLAIM \
--include-constant USBDEVFS_URB_TYPE_INTERRUPT \
--include-constant USBDEVFS_URB_TYPE_CONTROL \
--include-constant USBDEVFS_URB_TYPE_BULK \
Expand Down Expand Up @@ -89,14 +81,14 @@ $JEXTRACT --source --output ../../src/main/java \
--include-function udev_monitor_get_fd \
/usr/include/libudev.h

# poll.h
# epoll.h
$JEXTRACT --source --output ../../src/main/java \
--header-class-name poll \
--target-package net.codecrete.usb.linux.gen.poll \
--include-function poll \
--include-struct pollfd \
--include-constant POLLIN \
--include-constant POLLOUT \
--include-constant POLLERR \
/usr/include/poll.h
--header-class-name epoll \
--target-package net.codecrete.usb.linux.gen.epoll \
--include-struct epoll_event \
--include-constant EPOLL_CTL_ADD \
--include-constant EPOLL_CTL_DEL \
--include-constant EPOLLIN \
--include-constant EPOLLOUT \
epoll.h

98 changes: 98 additions & 0 deletions java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Java Does USB
// Copyright (c) 2022 Manuel Bleichenbacher
// Licensed under MIT License
// https://opensource.org/licenses/MIT
//

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.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;

import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_INT;
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.*;

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

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

private static final FunctionDescriptor epoll_create$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT);
private static final MethodHandle epoll_create$MH = linker.downcallHandle(linker.defaultLookup().find(
"epoll_create").get(), epoll_create$FUNC, Linux.ERRNO_STATE);

private static final FunctionDescriptor epoll_ctl$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS);
private static final MethodHandle epoll_ctl$MH = linker.downcallHandle(linker.defaultLookup().find(
"epoll_ctl").get(), epoll_ctl$FUNC, Linux.ERRNO_STATE);

private static final FunctionDescriptor epoll_wait$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT);
private static final MethodHandle epoll_wait$MH = linker.downcallHandle(linker.defaultLookup().find(
"epoll_wait").get(), epoll_wait$FUNC, Linux.ERRNO_STATE);

private static final VarHandle epoll_event_data_fd$VH = epoll_event.$LAYOUT().varHandle(
MemoryLayout.PathElement.groupElement("data"),
MemoryLayout.PathElement.groupElement("fd")
);

static int epoll_create(int size, MemorySegment errno) {
try {
return (int) epoll_create$MH.invokeExact(errno, size);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

private static int epoll_ctl(int epfd, int op, int fd, MemorySegment event, MemorySegment errno) {
try {
return (int) epoll_ctl$MH.invokeExact(errno, epfd, op, fd, event);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

static int epoll_wait(int epfd, MemorySegment events, int maxevent, int timeout, MemorySegment errno) {
try {
return (int) epoll_wait$MH.invokeExact(errno, epfd, events, maxevent, timeout);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

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$set(event, op);
epoll_event_data_fd$VH.set(event, fd);
var ret = epoll_ctl(epfd, EPOLL_CTL_ADD(), fd, event, errorState);
if (ret < 0)
throwLastError(errorState, "internal error (epoll_ctl_add)");
}
}

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$set(event, 0);
epoll_event_data_fd$VH.set(event, fd);
var ret = epoll_ctl(epfd, EPOLL_CTL_DEL(), fd, event, errorState);
if (ret < 0) {
var err = Linux.getErrno(errorState);
if (err != errno.ENOENT())
throwLastError(errorState, "internal error (epoll_ctl_del)");
}
}
}
}
34 changes: 0 additions & 34 deletions java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@ private IO() {
private static final FunctionDescriptor open$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT);
private static final MethodHandle open$MH = linker.downcallHandle(linker.defaultLookup().find("open").get(),
open$FUNC, Linux.ERRNO_STATE);
private static final FunctionDescriptor eventfd$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT);
private static final MethodHandle eventfd$MH = linker.downcallHandle(linker.defaultLookup().find("eventfd").get()
, eventfd$FUNC, Linux.ERRNO_STATE);
private static final FunctionDescriptor eventfd_read$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS);
private static final MethodHandle eventfd_read$MH = linker.downcallHandle(linker.defaultLookup().find(
"eventfd_read").get(), eventfd_read$FUNC, Linux.ERRNO_STATE);
private static final FunctionDescriptor eventfd_write$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_LONG);
private static final MethodHandle eventfd_write$MH = linker.downcallHandle(linker.defaultLookup().find(
"eventfd_write").get(), eventfd_write$FUNC, Linux.ERRNO_STATE);

static int ioctl(int fd, long request, MemorySegment segment, MemorySegment errno) {
try {
Expand All @@ -52,29 +43,4 @@ static int open(MemorySegment file, int oflag, MemorySegment errno) {
throw new AssertionError(ex);
}
}

static int eventfd(int count, int flags, MemorySegment errno) {
try {
return (int) eventfd$MH.invokeExact(errno, count, flags);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

static int eventfd_read(int fd, MemorySegment value, MemorySegment errno) {
try {
return (int) eventfd_read$MH.invokeExact(errno, fd, value);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

static int eventfd_write(int fd, long value, MemorySegment errno) {
try {
return (int) eventfd_write$MH.invokeExact(errno, fd, value);
} catch (Throwable ex) {
throw new AssertionError(ex);
}
}

}
Loading

0 comments on commit be72c50

Please sign in to comment.