0N/A/*
3261N/A * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.nio.ch;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.nio.channels.*;
0N/Aimport java.nio.channels.spi.*;
0N/Aimport java.util.*;
0N/Aimport sun.misc.*;
0N/A
0N/A/**
0N/A * An implementation of Selector for Linux 2.6+ kernels that uses
0N/A * the epoll event notification facility.
0N/A */
0N/Aclass EPollSelectorImpl
0N/A extends SelectorImpl
0N/A{
0N/A
0N/A // File descriptors used for interrupt
0N/A protected int fd0;
0N/A protected int fd1;
0N/A
0N/A // The poll object
0N/A EPollArrayWrapper pollWrapper;
0N/A
0N/A // Maps from file descriptors to keys
438N/A private Map<Integer,SelectionKeyImpl> fdToKey;
0N/A
0N/A // True if this Selector has been closed
673N/A private volatile boolean closed = false;
0N/A
0N/A // Lock for interrupt triggering and clearing
6090N/A private final Object interruptLock = new Object();
0N/A private boolean interruptTriggered = false;
0N/A
0N/A /**
0N/A * Package private constructor called by factory method in
0N/A * the abstract superclass Selector.
0N/A */
6090N/A EPollSelectorImpl(SelectorProvider sp) throws IOException {
0N/A super(sp);
2731N/A long pipeFds = IOUtil.makePipe(false);
2731N/A fd0 = (int) (pipeFds >>> 32);
2731N/A fd1 = (int) pipeFds;
0N/A pollWrapper = new EPollArrayWrapper();
0N/A pollWrapper.initInterrupt(fd0, fd1);
6090N/A fdToKey = new HashMap<>();
0N/A }
0N/A
6090N/A protected int doSelect(long timeout) throws IOException {
0N/A if (closed)
0N/A throw new ClosedSelectorException();
0N/A processDeregisterQueue();
0N/A try {
0N/A begin();
0N/A pollWrapper.poll(timeout);
0N/A } finally {
0N/A end();
0N/A }
0N/A processDeregisterQueue();
0N/A int numKeysUpdated = updateSelectedKeys();
0N/A if (pollWrapper.interrupted()) {
0N/A // Clear the wakeup pipe
0N/A pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
0N/A synchronized (interruptLock) {
0N/A pollWrapper.clearInterrupted();
0N/A IOUtil.drain(fd0);
0N/A interruptTriggered = false;
0N/A }
0N/A }
0N/A return numKeysUpdated;
0N/A }
0N/A
0N/A /**
0N/A * Update the keys whose fd's have been selected by the epoll.
0N/A * Add the ready keys to the ready queue.
0N/A */
0N/A private int updateSelectedKeys() {
0N/A int entries = pollWrapper.updated;
0N/A int numKeysUpdated = 0;
0N/A for (int i=0; i<entries; i++) {
0N/A int nextFD = pollWrapper.getDescriptor(i);
438N/A SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
0N/A // ski is null in the case of an interrupt
0N/A if (ski != null) {
0N/A int rOps = pollWrapper.getEventOps(i);
0N/A if (selectedKeys.contains(ski)) {
0N/A if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
0N/A numKeysUpdated++;
0N/A }
0N/A } else {
0N/A ski.channel.translateAndSetReadyOps(rOps, ski);
0N/A if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
0N/A selectedKeys.add(ski);
0N/A numKeysUpdated++;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A return numKeysUpdated;
0N/A }
0N/A
0N/A protected void implClose() throws IOException {
673N/A if (closed)
673N/A return;
673N/A closed = true;
0N/A
673N/A // prevent further wakeup
673N/A synchronized (interruptLock) {
673N/A interruptTriggered = true;
673N/A }
0N/A
893N/A FileDispatcherImpl.closeIntFD(fd0);
893N/A FileDispatcherImpl.closeIntFD(fd1);
0N/A
673N/A pollWrapper.closeEPollFD();
673N/A // it is possible
673N/A selectedKeys = null;
0N/A
673N/A // Deregister channels
2731N/A Iterator<SelectionKey> i = keys.iterator();
673N/A while (i.hasNext()) {
673N/A SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
673N/A deregister(ski);
673N/A SelectableChannel selch = ski.channel();
673N/A if (!selch.isOpen() && !selch.isRegistered())
673N/A ((SelChImpl)selch).kill();
673N/A i.remove();
0N/A }
673N/A
673N/A fd0 = -1;
673N/A fd1 = -1;
0N/A }
0N/A
0N/A protected void implRegister(SelectionKeyImpl ski) {
673N/A if (closed)
673N/A throw new ClosedSelectorException();
1027N/A SelChImpl ch = ski.channel;
6090N/A int fd = Integer.valueOf(ch.getFDVal());
6090N/A fdToKey.put(fd, ski);
6090N/A pollWrapper.add(fd);
0N/A keys.add(ski);
0N/A }
0N/A
0N/A protected void implDereg(SelectionKeyImpl ski) throws IOException {
0N/A assert (ski.getIndex() >= 0);
1027N/A SelChImpl ch = ski.channel;
1027N/A int fd = ch.getFDVal();
438N/A fdToKey.remove(Integer.valueOf(fd));
6090N/A pollWrapper.remove(fd);
0N/A ski.setIndex(-1);
0N/A keys.remove(ski);
0N/A selectedKeys.remove(ski);
0N/A deregister((AbstractSelectionKey)ski);
0N/A SelectableChannel selch = ski.channel();
0N/A if (!selch.isOpen() && !selch.isRegistered())
0N/A ((SelChImpl)selch).kill();
0N/A }
0N/A
6090N/A void putEventOps(SelectionKeyImpl ski, int ops) {
673N/A if (closed)
673N/A throw new ClosedSelectorException();
6090N/A SelChImpl ch = ski.channel;
6090N/A pollWrapper.setInterest(ch.getFDVal(), ops);
0N/A }
0N/A
0N/A public Selector wakeup() {
0N/A synchronized (interruptLock) {
0N/A if (!interruptTriggered) {
0N/A pollWrapper.interrupt();
0N/A interruptTriggered = true;
0N/A }
0N/A }
0N/A return this;
0N/A }
0N/A
0N/A static {
0N/A Util.load();
0N/A }
0N/A}