--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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 java.nio.channels.*;
+import java.nio.channels.spi.*;
+import java.util.*;
+
+/**
+ * An implementation of Selector for Linux 2.6+ kernels that uses
+ * the epoll event notification facility.
+ */
+class EPollSelectorImpl
+ extends SelectorImpl
+{
+
+ // File descriptors used for interrupt
+ protected int fd0;
+ protected int fd1;
+
+ // The poll object
+ EPollArrayWrapper pollWrapper;
+
+ // Maps from file descriptors to keys
+ private Map<Integer,SelectionKeyImpl> fdToKey;
+
+ // True if this Selector has been closed
+ private volatile boolean closed;
+
+ // Lock for interrupt triggering and clearing
+ private final Object interruptLock = new Object();
+ private boolean interruptTriggered = false;
+
+ /**
+ * Package private constructor called by factory method in
+ * the abstract superclass Selector.
+ */
+ EPollSelectorImpl(SelectorProvider sp) throws IOException {
+ super(sp);
+ long pipeFds = IOUtil.makePipe(false);
+ fd0 = (int) (pipeFds >>> 32);
+ fd1 = (int) pipeFds;
+ try {
+ pollWrapper = new EPollArrayWrapper();
+ pollWrapper.initInterrupt(fd0, fd1);
+ fdToKey = new HashMap<>();
+ } catch (Throwable t) {
+ try {
+ FileDispatcherImpl.closeIntFD(fd0);
+ } catch (IOException ioe0) {
+ t.addSuppressed(ioe0);
+ }
+ try {
+ FileDispatcherImpl.closeIntFD(fd1);
+ } catch (IOException ioe1) {
+ t.addSuppressed(ioe1);
+ }
+ throw t;
+ }
+ }
+
+ protected int doSelect(long timeout) throws IOException {
+ if (closed)
+ throw new ClosedSelectorException();
+ processDeregisterQueue();
+ try {
+ begin();
+ pollWrapper.poll(timeout);
+ } finally {
+ end();
+ }
+ processDeregisterQueue();
+ int numKeysUpdated = updateSelectedKeys();
+ if (pollWrapper.interrupted()) {
+ // Clear the wakeup pipe
+ pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
+ synchronized (interruptLock) {
+ pollWrapper.clearInterrupted();
+ IOUtil.drain(fd0);
+ interruptTriggered = false;
+ }
+ }
+ return numKeysUpdated;
+ }
+
+ /**
+ * Update the keys whose fd's have been selected by the epoll.
+ * Add the ready keys to the ready queue.
+ */
+ private int updateSelectedKeys() {
+ int entries = pollWrapper.updated;
+ int numKeysUpdated = 0;
+ for (int i=0; i<entries; i++) {
+ int nextFD = pollWrapper.getDescriptor(i);
+ SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
+ // ski is null in the case of an interrupt
+ if (ski != null) {
+ int rOps = pollWrapper.getEventOps(i);
+ if (selectedKeys.contains(ski)) {
+ if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
+ numKeysUpdated++;
+ }
+ } else {
+ ski.channel.translateAndSetReadyOps(rOps, ski);
+ if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
+ selectedKeys.add(ski);
+ numKeysUpdated++;
+ }
+ }
+ }
+ }
+ return numKeysUpdated;
+ }
+
+ protected void implClose() throws IOException {
+ if (closed)
+ return;
+ closed = true;
+
+ // prevent further wakeup
+ synchronized (interruptLock) {
+ interruptTriggered = true;
+ }
+
+ FileDispatcherImpl.closeIntFD(fd0);
+ FileDispatcherImpl.closeIntFD(fd1);
+
+ pollWrapper.closeEPollFD();
+ // it is possible
+ selectedKeys = null;
+
+ // Deregister channels
+ Iterator<SelectionKey> i = keys.iterator();
+ while (i.hasNext()) {
+ SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+ deregister(ski);
+ SelectableChannel selch = ski.channel();
+ if (!selch.isOpen() && !selch.isRegistered())
+ ((SelChImpl)selch).kill();
+ i.remove();
+ }
+
+ fd0 = -1;
+ fd1 = -1;
+ }
+
+ protected void implRegister(SelectionKeyImpl ski) {
+ if (closed)
+ throw new ClosedSelectorException();
+ SelChImpl ch = ski.channel;
+ int fd = Integer.valueOf(ch.getFDVal());
+ fdToKey.put(fd, ski);
+ pollWrapper.add(fd);
+ keys.add(ski);
+ }
+
+ protected void implDereg(SelectionKeyImpl ski) throws IOException {
+ assert (ski.getIndex() >= 0);
+ SelChImpl ch = ski.channel;
+ int fd = ch.getFDVal();
+ fdToKey.remove(Integer.valueOf(fd));
+ pollWrapper.remove(fd);
+ ski.setIndex(-1);
+ keys.remove(ski);
+ selectedKeys.remove(ski);
+ deregister((AbstractSelectionKey)ski);
+ SelectableChannel selch = ski.channel();
+ if (!selch.isOpen() && !selch.isRegistered())
+ ((SelChImpl)selch).kill();
+ }
+
+ public void putEventOps(SelectionKeyImpl ski, int ops) {
+ if (closed)
+ throw new ClosedSelectorException();
+ SelChImpl ch = ski.channel;
+ pollWrapper.setInterest(ch.getFDVal(), ops);
+ }
+
+ public Selector wakeup() {
+ synchronized (interruptLock) {
+ if (!interruptTriggered) {
+ pollWrapper.interrupt();
+ interruptTriggered = true;
+ }
+ }
+ return this;
+ }
+}