8286597: Implement PollerProvider on AIX
Reviewed-by: mdoerr, alanb, vtewari
This commit is contained in:
parent
e7edf8d145
commit
48d21bd089
@ -43,11 +43,11 @@ inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* p) {
|
|||||||
|
|
||||||
template<typename FKind>
|
template<typename FKind>
|
||||||
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
Unimplemented();
|
// Currently all registers are considered to be volatile and saved in the caller (java) frame if needed
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
Unimplemented();
|
// Currently all registers are considered to be volatile and saved in the caller (java) frame if needed
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ContinuationHelper::push_pd(const frame& f) {
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 SAP SE. All rights reserved.
|
* Copyright (c) 2012 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -27,6 +27,7 @@
|
|||||||
package sun.nio.ch;
|
package sun.nio.ch;
|
||||||
|
|
||||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||||
|
import sun.nio.ch.Pollset;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -34,7 +35,6 @@ import java.util.concurrent.ArrayBlockingQueue;
|
|||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import jdk.internal.misc.Unsafe;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AsynchronousChannelGroup implementation based on the AIX pollset framework.
|
* AsynchronousChannelGroup implementation based on the AIX pollset framework.
|
||||||
@ -42,33 +42,11 @@ import jdk.internal.misc.Unsafe;
|
|||||||
final class AixPollPort
|
final class AixPollPort
|
||||||
extends Port
|
extends Port
|
||||||
{
|
{
|
||||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
IOUtil.load();
|
IOUtil.load();
|
||||||
init();
|
Pollset.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* struct pollfd {
|
|
||||||
* int fd;
|
|
||||||
* short events;
|
|
||||||
* short revents;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
private static final int SIZEOF_POLLFD = eventSize();
|
|
||||||
private static final int OFFSETOF_EVENTS = eventsOffset();
|
|
||||||
private static final int OFFSETOF_REVENTS = reventsOffset();
|
|
||||||
private static final int OFFSETOF_FD = fdOffset();
|
|
||||||
|
|
||||||
// opcodes
|
|
||||||
private static final int PS_ADD = 0x0;
|
|
||||||
private static final int PS_MOD = 0x1;
|
|
||||||
private static final int PS_DELETE = 0x2;
|
|
||||||
|
|
||||||
// maximum number of events to poll at a time
|
|
||||||
private static final int MAX_POLL_EVENTS = 512;
|
|
||||||
|
|
||||||
// pollset ID
|
// pollset ID
|
||||||
private final int pollset;
|
private final int pollset;
|
||||||
|
|
||||||
@ -88,6 +66,9 @@ final class AixPollPort
|
|||||||
// address of the poll array passed to pollset_poll
|
// address of the poll array passed to pollset_poll
|
||||||
private final long address;
|
private final long address;
|
||||||
|
|
||||||
|
// maximum number of events to poll at a time
|
||||||
|
private static final int MAX_EVENTS_TO_POLL = 512;
|
||||||
|
|
||||||
// encapsulates an event for a channel
|
// encapsulates an event for a channel
|
||||||
static class Event {
|
static class Event {
|
||||||
final PollableChannel channel;
|
final PollableChannel channel;
|
||||||
@ -142,16 +123,16 @@ final class AixPollPort
|
|||||||
super(provider, pool);
|
super(provider, pool);
|
||||||
|
|
||||||
// open pollset
|
// open pollset
|
||||||
this.pollset = pollsetCreate();
|
this.pollset = Pollset.pollsetCreate();
|
||||||
|
|
||||||
// create socket pair for wakeup mechanism
|
// create socket pair for wakeup mechanism
|
||||||
int[] sv = new int[2];
|
int[] sv = new int[2];
|
||||||
try {
|
try {
|
||||||
socketpair(sv);
|
Pollset.socketpair(sv);
|
||||||
// register one end with pollset
|
// register one end with pollset
|
||||||
pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
|
Pollset.pollsetCtl(pollset, Pollset.PS_ADD, sv[0], Net.POLLIN);
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
pollsetDestroy(pollset);
|
Pollset.pollsetDestroy(pollset);
|
||||||
throw x;
|
throw x;
|
||||||
}
|
}
|
||||||
this.sp = sv;
|
this.sp = sv;
|
||||||
@ -159,21 +140,21 @@ final class AixPollPort
|
|||||||
// create socket pair for pollset control mechanism
|
// create socket pair for pollset control mechanism
|
||||||
sv = new int[2];
|
sv = new int[2];
|
||||||
try {
|
try {
|
||||||
socketpair(sv);
|
Pollset.socketpair(sv);
|
||||||
// register one end with pollset
|
// register one end with pollset
|
||||||
pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
|
Pollset.pollsetCtl(pollset, Pollset.PS_ADD, sv[0], Net.POLLIN);
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
pollsetDestroy(pollset);
|
Pollset.pollsetDestroy(pollset);
|
||||||
throw x;
|
throw x;
|
||||||
}
|
}
|
||||||
this.ctlSp = sv;
|
this.ctlSp = sv;
|
||||||
|
|
||||||
// allocate the poll array
|
// allocate the poll array
|
||||||
this.address = allocatePollArray(MAX_POLL_EVENTS);
|
this.address = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
|
||||||
|
|
||||||
// create the queue and offer the special event to ensure that the first
|
// create the queue and offer the special event to ensure that the first
|
||||||
// threads polls
|
// threads polls
|
||||||
this.queue = new ArrayBlockingQueue<Event>(MAX_POLL_EVENTS);
|
this.queue = new ArrayBlockingQueue<Event>(MAX_EVENTS_TO_POLL);
|
||||||
this.queue.offer(NEED_TO_POLL);
|
this.queue.offer(NEED_TO_POLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,19 +172,19 @@ final class AixPollPort
|
|||||||
return;
|
return;
|
||||||
closed = true;
|
closed = true;
|
||||||
}
|
}
|
||||||
freePollArray(address);
|
Pollset.freePollArray(address);
|
||||||
close0(sp[0]);
|
Pollset.close0(sp[0]);
|
||||||
close0(sp[1]);
|
Pollset.close0(sp[1]);
|
||||||
close0(ctlSp[0]);
|
Pollset.close0(ctlSp[0]);
|
||||||
close0(ctlSp[1]);
|
Pollset.close0(ctlSp[1]);
|
||||||
pollsetDestroy(pollset);
|
Pollset.pollsetDestroy(pollset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void wakeup() {
|
void wakeup() {
|
||||||
if (wakeupCount.incrementAndGet() == 1) {
|
if (wakeupCount.incrementAndGet() == 1) {
|
||||||
// write byte to socketpair to force wakeup
|
// write byte to socketpair to force wakeup
|
||||||
try {
|
try {
|
||||||
interrupt(sp[1]);
|
Pollset.interrupt(sp[1]);
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
throw new AssertionError(x);
|
throw new AssertionError(x);
|
||||||
}
|
}
|
||||||
@ -258,7 +239,7 @@ final class AixPollPort
|
|||||||
controlQueue.add(ev);
|
controlQueue.add(ev);
|
||||||
// write byte to socketpair to force wakeup
|
// write byte to socketpair to force wakeup
|
||||||
try {
|
try {
|
||||||
interrupt(ctlSp[1]);
|
Pollset.interrupt(ctlSp[1]);
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
throw new AssertionError(x);
|
throw new AssertionError(x);
|
||||||
}
|
}
|
||||||
@ -299,9 +280,9 @@ final class AixPollPort
|
|||||||
Iterator<ControlEvent> iter = controlQueue.iterator();
|
Iterator<ControlEvent> iter = controlQueue.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
ControlEvent ev = iter.next();
|
ControlEvent ev = iter.next();
|
||||||
pollsetCtl(pollset, PS_DELETE, ev.fd(), 0);
|
Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, ev.fd(), 0);
|
||||||
if (!ev.removeOnly()) {
|
if (!ev.removeOnly()) {
|
||||||
ev.setError(pollsetCtl(pollset, PS_MOD, ev.fd(), ev.events()));
|
ev.setError(Pollset.pollsetCtl(pollset, Pollset.PS_MOD, ev.fd(), ev.events()));
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
@ -325,7 +306,8 @@ final class AixPollPort
|
|||||||
int n;
|
int n;
|
||||||
controlLock.lock();
|
controlLock.lock();
|
||||||
try {
|
try {
|
||||||
n = pollsetPoll(pollset, address, MAX_POLL_EVENTS);
|
n = Pollset.pollsetPoll(pollset, address,
|
||||||
|
MAX_EVENTS_TO_POLL, Pollset.PS_NO_TIMEOUT);
|
||||||
} finally {
|
} finally {
|
||||||
controlLock.unlock();
|
controlLock.unlock();
|
||||||
}
|
}
|
||||||
@ -338,14 +320,14 @@ final class AixPollPort
|
|||||||
fdToChannelLock.readLock().lock();
|
fdToChannelLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
while (n-- > 0) {
|
while (n-- > 0) {
|
||||||
long eventAddress = getEvent(address, n);
|
long eventAddress = Pollset.getEvent(address, n);
|
||||||
int fd = getDescriptor(eventAddress);
|
int fd = Pollset.getDescriptor(eventAddress);
|
||||||
|
|
||||||
// To emulate one shot semantic we need to remove
|
// To emulate one shot semantic we need to remove
|
||||||
// the file descriptor here.
|
// the file descriptor here.
|
||||||
if (fd != sp[0] && fd != ctlSp[0]) {
|
if (fd != sp[0] && fd != ctlSp[0]) {
|
||||||
synchronized (controlQueue) {
|
synchronized (controlQueue) {
|
||||||
pollsetCtl(pollset, PS_DELETE, fd, 0);
|
Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, fd, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +335,7 @@ final class AixPollPort
|
|||||||
if (fd == sp[0]) {
|
if (fd == sp[0]) {
|
||||||
if (wakeupCount.decrementAndGet() == 0) {
|
if (wakeupCount.decrementAndGet() == 0) {
|
||||||
// no more wakeups so drain pipe
|
// no more wakeups so drain pipe
|
||||||
drain1(sp[0]);
|
Pollset.drain1(sp[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// queue special event if there are more events
|
// queue special event if there are more events
|
||||||
@ -368,7 +350,7 @@ final class AixPollPort
|
|||||||
// wakeup to process control event
|
// wakeup to process control event
|
||||||
if (fd == ctlSp[0]) {
|
if (fd == ctlSp[0]) {
|
||||||
synchronized (controlQueue) {
|
synchronized (controlQueue) {
|
||||||
drain1(ctlSp[0]);
|
Pollset.drain1(ctlSp[0]);
|
||||||
processControlQueue();
|
processControlQueue();
|
||||||
}
|
}
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
@ -379,7 +361,7 @@ final class AixPollPort
|
|||||||
|
|
||||||
PollableChannel channel = fdToChannel.get(fd);
|
PollableChannel channel = fdToChannel.get(fd);
|
||||||
if (channel != null) {
|
if (channel != null) {
|
||||||
int events = getRevents(eventAddress);
|
int events = Pollset.getRevents(eventAddress);
|
||||||
Event ev = new Event(channel, events);
|
Event ev = new Event(channel, events);
|
||||||
|
|
||||||
// n-1 events are queued; This thread handles
|
// n-1 events are queued; This thread handles
|
||||||
@ -467,75 +449,4 @@ final class AixPollPort
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a poll array to handle up to {@code count} events.
|
|
||||||
*/
|
|
||||||
private static long allocatePollArray(int count) {
|
|
||||||
return unsafe.allocateMemory(count * SIZEOF_POLLFD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free a poll array
|
|
||||||
*/
|
|
||||||
private static void freePollArray(long address) {
|
|
||||||
unsafe.freeMemory(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns event[i];
|
|
||||||
*/
|
|
||||||
private static long getEvent(long address, int i) {
|
|
||||||
return address + (SIZEOF_POLLFD*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns event->fd
|
|
||||||
*/
|
|
||||||
private static int getDescriptor(long eventAddress) {
|
|
||||||
return unsafe.getInt(eventAddress + OFFSETOF_FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns event->events
|
|
||||||
*/
|
|
||||||
private static int getEvents(long eventAddress) {
|
|
||||||
return unsafe.getChar(eventAddress + OFFSETOF_EVENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns event->revents
|
|
||||||
*/
|
|
||||||
private static int getRevents(long eventAddress) {
|
|
||||||
return unsafe.getChar(eventAddress + OFFSETOF_REVENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Native methods --
|
|
||||||
|
|
||||||
private static native void init();
|
|
||||||
|
|
||||||
private static native int eventSize();
|
|
||||||
|
|
||||||
private static native int eventsOffset();
|
|
||||||
|
|
||||||
private static native int reventsOffset();
|
|
||||||
|
|
||||||
private static native int fdOffset();
|
|
||||||
|
|
||||||
private static native int pollsetCreate() throws IOException;
|
|
||||||
|
|
||||||
private static native int pollsetCtl(int pollset, int opcode, int fd, int events);
|
|
||||||
|
|
||||||
private static native int pollsetPoll(int pollset, long pollAddress, int numfds)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
private static native void pollsetDestroy(int pollset);
|
|
||||||
|
|
||||||
private static native void socketpair(int[] sv) throws IOException;
|
|
||||||
|
|
||||||
private static native void interrupt(int fd) throws IOException;
|
|
||||||
|
|
||||||
private static native void drain1(int fd) throws IOException;
|
|
||||||
|
|
||||||
private static native void close0(int fd);
|
|
||||||
}
|
}
|
||||||
|
124
src/java.base/aix/classes/sun/nio/ch/Pollset.java
Normal file
124
src/java.base/aix/classes/sun/nio/ch/Pollset.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2023, IBM Corp.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.nio.ch;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
|
||||||
|
public class Pollset {
|
||||||
|
|
||||||
|
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pollfd {
|
||||||
|
* int fd;
|
||||||
|
* short events;
|
||||||
|
* short revents;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public static final int SIZEOF_POLLFD = eventSize();
|
||||||
|
public static final int OFFSETOF_EVENTS = eventsOffset();
|
||||||
|
public static final int OFFSETOF_REVENTS = reventsOffset();
|
||||||
|
public static final int OFFSETOF_FD = fdOffset();
|
||||||
|
|
||||||
|
// opcodes
|
||||||
|
public static final int PS_ADD = 0x0;
|
||||||
|
public static final int PS_MOD = 0x1;
|
||||||
|
public static final int PS_DELETE = 0x2;
|
||||||
|
|
||||||
|
// event
|
||||||
|
public static final int PS_POLLPRI = 0x4;
|
||||||
|
|
||||||
|
// revent errcodes
|
||||||
|
public static final char PS_POLLNVAL = 0x8000;
|
||||||
|
public static final char PS_POLLERR = 0x4000;
|
||||||
|
|
||||||
|
public static final int PS_NO_TIMEOUT = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a poll array to handle up to {@code count} events.
|
||||||
|
*/
|
||||||
|
public static long allocatePollArray(int count) {
|
||||||
|
return unsafe.allocateMemory(count * SIZEOF_POLLFD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a poll array
|
||||||
|
*/
|
||||||
|
public static void freePollArray(long address) {
|
||||||
|
unsafe.freeMemory(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns event[i];
|
||||||
|
*/
|
||||||
|
public static long getEvent(long address, int i) {
|
||||||
|
return address + (SIZEOF_POLLFD * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns event->fd
|
||||||
|
*/
|
||||||
|
public static int getDescriptor(long eventAddress) {
|
||||||
|
return unsafe.getInt(eventAddress + OFFSETOF_FD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns event->events
|
||||||
|
*/
|
||||||
|
public static int getEvents(long eventAddress) {
|
||||||
|
return unsafe.getChar(eventAddress + OFFSETOF_EVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns event->revents
|
||||||
|
*/
|
||||||
|
public static char getRevents(long eventAddress) {
|
||||||
|
return unsafe.getChar(eventAddress + OFFSETOF_REVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isReventsError(long eventAddress) {
|
||||||
|
char revents = getRevents(eventAddress);
|
||||||
|
return (revents & PS_POLLNVAL) != 0 || (revents & PS_POLLERR) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Native methods --
|
||||||
|
public static native int pollsetCreate() throws IOException;
|
||||||
|
public static native int pollsetCtl(int pollset, int opcode, int fd, int events);
|
||||||
|
public static native int pollsetPoll(int pollset, long pollAddress, int numfds, int timeout)
|
||||||
|
throws IOException;
|
||||||
|
public static native void pollsetDestroy(int pollset);
|
||||||
|
public static native void init();
|
||||||
|
public static native int eventSize();
|
||||||
|
public static native int eventsOffset();
|
||||||
|
public static native int reventsOffset();
|
||||||
|
public static native int fdOffset();
|
||||||
|
public static native void socketpair(int[] sv) throws IOException;
|
||||||
|
public static native void interrupt(int fd) throws IOException;
|
||||||
|
public static native void drain1(int fd) throws IOException;
|
||||||
|
public static native void close0(int fd);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2023, IBM Corp.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,6 +26,8 @@
|
|||||||
package sun.nio.ch;
|
package sun.nio.ch;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import sun.nio.ch.Pollset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poller implementation based on the AIX Pollset library.
|
* Poller implementation based on the AIX Pollset library.
|
||||||
@ -32,32 +35,74 @@ import java.io.IOException;
|
|||||||
|
|
||||||
class PollsetPoller extends Poller {
|
class PollsetPoller extends Poller {
|
||||||
|
|
||||||
|
private static final int MAX_EVENTS_TO_POLL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Pollset.init(); /* Dynamically loads pollset C functions */
|
||||||
|
MAX_EVENTS_TO_POLL = 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int setid;
|
||||||
|
private final long pollBuffer;
|
||||||
|
|
||||||
PollsetPoller(boolean read) throws IOException {
|
PollsetPoller(boolean read) throws IOException {
|
||||||
super(read);
|
super(read);
|
||||||
|
this.setid = Pollset.pollsetCreate();
|
||||||
|
this.pollBuffer = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int fdVal() {
|
int fdVal() {
|
||||||
// Stub
|
return setid;
|
||||||
throw new UnsupportedOperationException("Unimplemented on AIX");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void implRegister(int fdVal) throws IOException {
|
void implRegister(int fd) throws IOException {
|
||||||
// Stub
|
int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd,
|
||||||
throw new UnsupportedOperationException("Unimplemented on AIX");
|
Pollset.PS_POLLPRI | (this.reading() ? Net.POLLIN : Net.POLLOUT));
|
||||||
|
if (ret != 0) {
|
||||||
|
throw new IOException("Unable to register fd " + fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void implDeregister(int fdVal) {
|
void implDeregister(int fd) {
|
||||||
// Stub
|
int ret = Pollset.pollsetCtl(setid, Pollset.PS_DELETE, fd, 0);
|
||||||
throw new UnsupportedOperationException("Unimplemented on AIX");
|
assert ret == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main poll method. The AIX Pollset library does not appear to pick up changes to the pollset
|
||||||
|
* (the set of fds being polled) while blocked on a call to this method. These changes happen
|
||||||
|
* regularly in the poll-loop thread and update thread from Poller.java.
|
||||||
|
* To address this difficulty, we break poll calls into 100ms sub-calls and emulate the timout.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
int poll(int timeout) throws IOException {
|
int poll(int timeout) throws IOException {
|
||||||
// Stub
|
int n;
|
||||||
throw new UnsupportedOperationException("Unimplemented on AIX");
|
switch (timeout) {
|
||||||
|
case 0:
|
||||||
|
n = pollInner(0);
|
||||||
|
break;
|
||||||
|
case Pollset.PS_NO_TIMEOUT:
|
||||||
|
do { n = pollInner(100); } while (n == 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Instant end = Instant.now().plusMillis(timeout);
|
||||||
|
do { n = pollInner(100); } while (n == 0 && Instant.now().isBefore(end));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pollInner(int subInterval) throws IOException {
|
||||||
|
int n = Pollset.pollsetPoll(setid, pollBuffer, MAX_EVENTS_TO_POLL, subInterval);
|
||||||
|
for (int i=0; i<n; i++) {
|
||||||
|
long eventAddress = Pollset.getEvent(pollBuffer, i);
|
||||||
|
int fd = Pollset.getDescriptor(eventAddress);
|
||||||
|
polled(fd);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,17 +29,16 @@
|
|||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "jlong.h"
|
#include "jlong.h"
|
||||||
|
|
||||||
#include "sun_nio_ch_AixPollPort.h"
|
#include "sun_nio_ch_Pollset.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <sys/pollset.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/pollset.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/* Initially copied from src/solaris/native/sun/nio/ch/nio_util.h */
|
/* Initially copied from src/solaris/native/sun/nio/ch/nio_util.h */
|
||||||
#define RESTARTABLE(_cmd, _result) do { \
|
#define RESTARTABLE(_cmd, _result) do { \
|
||||||
@ -58,7 +57,7 @@ static pollset_ctl_func* _pollset_ctl = NULL;
|
|||||||
static pollset_poll_func* _pollset_poll = NULL;
|
static pollset_poll_func* _pollset_poll = NULL;
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) {
|
Java_sun_nio_ch_Pollset_init(JNIEnv* env, jclass this) {
|
||||||
_pollset_create = (pollset_create_func*) dlsym(RTLD_DEFAULT, "pollset_create");
|
_pollset_create = (pollset_create_func*) dlsym(RTLD_DEFAULT, "pollset_create");
|
||||||
_pollset_destroy = (pollset_destroy_func*) dlsym(RTLD_DEFAULT, "pollset_destroy");
|
_pollset_destroy = (pollset_destroy_func*) dlsym(RTLD_DEFAULT, "pollset_destroy");
|
||||||
_pollset_ctl = (pollset_ctl_func*) dlsym(RTLD_DEFAULT, "pollset_ctl");
|
_pollset_ctl = (pollset_ctl_func*) dlsym(RTLD_DEFAULT, "pollset_ctl");
|
||||||
@ -70,27 +69,27 @@ Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_eventSize(JNIEnv* env, jclass this) {
|
Java_sun_nio_ch_Pollset_eventSize(JNIEnv* env, jclass this) {
|
||||||
return sizeof(struct pollfd);
|
return sizeof(struct pollfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_eventsOffset(JNIEnv* env, jclass this) {
|
Java_sun_nio_ch_Pollset_eventsOffset(JNIEnv* env, jclass this) {
|
||||||
return offsetof(struct pollfd, events);
|
return offsetof(struct pollfd, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_reventsOffset(JNIEnv* env, jclass this) {
|
Java_sun_nio_ch_Pollset_reventsOffset(JNIEnv* env, jclass this) {
|
||||||
return offsetof(struct pollfd, revents);
|
return offsetof(struct pollfd, revents);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_fdOffset(JNIEnv* env, jclass this) {
|
Java_sun_nio_ch_Pollset_fdOffset(JNIEnv* env, jclass this) {
|
||||||
return offsetof(struct pollfd, fd);
|
return offsetof(struct pollfd, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) {
|
Java_sun_nio_ch_Pollset_pollsetCreate(JNIEnv *env, jclass c) {
|
||||||
/* pollset_create can take the maximum number of fds, but we
|
/* pollset_create can take the maximum number of fds, but we
|
||||||
* cannot predict this number so we leave it at OPEN_MAX. */
|
* cannot predict this number so we leave it at OPEN_MAX. */
|
||||||
pollset_t ps = _pollset_create(-1);
|
pollset_t ps = _pollset_create(-1);
|
||||||
@ -101,7 +100,7 @@ Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps,
|
Java_sun_nio_ch_Pollset_pollsetCtl(JNIEnv *env, jclass c, jint ps,
|
||||||
jint opcode, jint fd, jint events) {
|
jint opcode, jint fd, jint events) {
|
||||||
struct poll_ctl event;
|
struct poll_ctl event;
|
||||||
int res;
|
int res;
|
||||||
@ -116,26 +115,27 @@ Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_pollsetPoll(JNIEnv *env, jclass c,
|
Java_sun_nio_ch_Pollset_pollsetPoll(JNIEnv *env, jclass c,
|
||||||
jint ps, jlong address, jint numfds) {
|
jint ps, jlong address, jint numfds, jint timeout) {
|
||||||
struct pollfd *events = jlong_to_ptr(address);
|
struct pollfd *events = jlong_to_ptr(address);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
RESTARTABLE(_pollset_poll(ps, events, numfds, -1), res);
|
RESTARTABLE(_pollset_poll(ps, events, numfds, timeout), res);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
perror("pollset_poll failed");
|
||||||
JNU_ThrowIOExceptionWithLastError(env, "pollset_poll failed");
|
JNU_ThrowIOExceptionWithLastError(env, "pollset_poll failed");
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_pollsetDestroy(JNIEnv *env, jclass c, jint ps) {
|
Java_sun_nio_ch_Pollset_pollsetDestroy(JNIEnv *env, jclass c, jint ps) {
|
||||||
int res;
|
int res;
|
||||||
RESTARTABLE(_pollset_destroy((pollset_t)ps), res);
|
RESTARTABLE(_pollset_destroy((pollset_t)ps), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
|
Java_sun_nio_ch_Pollset_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
|
||||||
int sp[2];
|
int sp[2];
|
||||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
|
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
|
||||||
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
|
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
|
||||||
@ -148,7 +148,7 @@ Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
|
Java_sun_nio_ch_Pollset_interrupt(JNIEnv *env, jclass c, jint fd) {
|
||||||
int res;
|
int res;
|
||||||
int buf[1];
|
int buf[1];
|
||||||
buf[0] = 1;
|
buf[0] = 1;
|
||||||
@ -159,7 +159,7 @@ Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
|
Java_sun_nio_ch_Pollset_drain1(JNIEnv *env, jclass cl, jint fd) {
|
||||||
int res;
|
int res;
|
||||||
char buf[1];
|
char buf[1];
|
||||||
RESTARTABLE(read(fd, buf, 1), res);
|
RESTARTABLE(read(fd, buf, 1), res);
|
||||||
@ -169,7 +169,7 @@ Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_ch_AixPollPort_close0(JNIEnv *env, jclass c, jint fd) {
|
Java_sun_nio_ch_Pollset_close0(JNIEnv *env, jclass c, jint fd) {
|
||||||
int res;
|
int res;
|
||||||
RESTARTABLE(close(fd), res);
|
RESTARTABLE(close(fd), res);
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -97,9 +97,9 @@ public abstract class Poller {
|
|||||||
*/
|
*/
|
||||||
private void poll(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
|
private void poll(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
|
||||||
if (USE_DIRECT_REGISTER) {
|
if (USE_DIRECT_REGISTER) {
|
||||||
poll1(fdVal, nanos, supplier);
|
pollDirect(fdVal, nanos, supplier);
|
||||||
} else {
|
} else {
|
||||||
poll2(fdVal, nanos, supplier);
|
pollIndirect(fdVal, nanos, supplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ public abstract class Poller {
|
|||||||
* Parks the current thread until a file descriptor is ready. This implementation
|
* Parks the current thread until a file descriptor is ready. This implementation
|
||||||
* registers the file descriptor, then parks until the file descriptor is polled.
|
* registers the file descriptor, then parks until the file descriptor is polled.
|
||||||
*/
|
*/
|
||||||
private void poll1(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
|
private void pollDirect(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
|
||||||
register(fdVal);
|
register(fdVal);
|
||||||
try {
|
try {
|
||||||
boolean isOpen = supplier.getAsBoolean();
|
boolean isOpen = supplier.getAsBoolean();
|
||||||
@ -128,7 +128,7 @@ public abstract class Poller {
|
|||||||
* queues the file descriptor to the update thread, then parks until the file
|
* queues the file descriptor to the update thread, then parks until the file
|
||||||
* descriptor is polled.
|
* descriptor is polled.
|
||||||
*/
|
*/
|
||||||
private void poll2(int fdVal, long nanos, BooleanSupplier supplier) {
|
private void pollIndirect(int fdVal, long nanos, BooleanSupplier supplier) {
|
||||||
Request request = registerAsync(fdVal);
|
Request request = registerAsync(fdVal);
|
||||||
try {
|
try {
|
||||||
boolean isOpen = supplier.getAsBoolean();
|
boolean isOpen = supplier.getAsBoolean();
|
||||||
|
Loading…
Reference in New Issue
Block a user