EPollSelectorImpl.java 7.1 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6
 * 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
7
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
8
 * particular file as subject to the "Classpath" exception as provided
9
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
10 11 12 13 14 15 16 17 18 19 20
 *
 * 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.
 *
21 22 23
 * 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.
D
duke 已提交
24 25 26 27 28 29 30 31
 */

package sun.nio.ch;

import java.io.IOException;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
Y
yunyao.zxl 已提交
32 33

import com.alibaba.wisp.engine.WispEngine;
D
duke 已提交
34 35 36 37 38 39 40 41 42
import sun.misc.*;

/**
 * An implementation of Selector for Linux 2.6+ kernels that uses
 * the epoll event notification facility.
 */
class EPollSelectorImpl
    extends SelectorImpl
{
Y
yunyao.zxl 已提交
43
    private static final WispEngineAccess WEA = SharedSecrets.getWispEngineAccess();
D
duke 已提交
44 45 46 47 48 49 50 51 52

    // File descriptors used for interrupt
    protected int fd0;
    protected int fd1;

    // The poll object
    EPollArrayWrapper pollWrapper;

    // Maps from file descriptors to keys
A
alanb 已提交
53
    private Map<Integer,SelectionKeyImpl> fdToKey;
D
duke 已提交
54 55

    // True if this Selector has been closed
56
    private volatile boolean closed = false;
D
duke 已提交
57 58

    // Lock for interrupt triggering and clearing
59
    private final Object interruptLock = new Object();
D
duke 已提交
60 61 62 63 64 65
    private boolean interruptTriggered = false;

    /**
     * Package private constructor called by factory method in
     * the abstract superclass Selector.
     */
66
    EPollSelectorImpl(SelectorProvider sp) throws IOException {
D
duke 已提交
67
        super(sp);
68 69 70
        long pipeFds = IOUtil.makePipe(false);
        fd0 = (int) (pipeFds >>> 32);
        fd1 = (int) pipeFds;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
        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;
        }
D
duke 已提交
88 89
    }

90
    protected int doSelect(long timeout) throws IOException {
D
duke 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
        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();
Y
yunyao.zxl 已提交
107 108 109 110 111 112
                if (WispEngine.transparentWispSwitch()
                        && WEA.useDirectSelectorWakeup() && WEA.isAllThreadAsWisp()) {
                    // skip
                } else {
                    IOUtil.drain(fd0);
                }
D
duke 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
                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);
A
alanb 已提交
128
            SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
D
duke 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
            // 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 {
149 150 151
        if (closed)
            return;
        closed = true;
D
duke 已提交
152

153 154 155 156
        // prevent further wakeup
        synchronized (interruptLock) {
            interruptTriggered = true;
        }
D
duke 已提交
157

158 159
        FileDispatcherImpl.closeIntFD(fd0);
        FileDispatcherImpl.closeIntFD(fd1);
160 161 162 163 164 165

        pollWrapper.closeEPollFD();
        // it is possible
        selectedKeys = null;

        // Deregister channels
166
        Iterator<SelectionKey> i = keys.iterator();
167 168 169 170 171 172 173
        while (i.hasNext()) {
            SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
            deregister(ski);
            SelectableChannel selch = ski.channel();
            if (!selch.isOpen() && !selch.isRegistered())
                ((SelChImpl)selch).kill();
            i.remove();
D
duke 已提交
174
        }
175 176 177

        fd0 = -1;
        fd1 = -1;
D
duke 已提交
178 179 180
    }

    protected void implRegister(SelectionKeyImpl ski) {
181 182
        if (closed)
            throw new ClosedSelectorException();
183
        SelChImpl ch = ski.channel;
184 185 186
        int fd = Integer.valueOf(ch.getFDVal());
        fdToKey.put(fd, ski);
        pollWrapper.add(fd);
D
duke 已提交
187 188 189 190 191
        keys.add(ski);
    }

    protected void implDereg(SelectionKeyImpl ski) throws IOException {
        assert (ski.getIndex() >= 0);
192 193
        SelChImpl ch = ski.channel;
        int fd = ch.getFDVal();
A
alanb 已提交
194
        fdToKey.remove(Integer.valueOf(fd));
195
        pollWrapper.remove(fd);
D
duke 已提交
196 197 198 199 200 201 202 203 204
        ski.setIndex(-1);
        keys.remove(ski);
        selectedKeys.remove(ski);
        deregister((AbstractSelectionKey)ski);
        SelectableChannel selch = ski.channel();
        if (!selch.isOpen() && !selch.isRegistered())
            ((SelChImpl)selch).kill();
    }

205
    public void putEventOps(SelectionKeyImpl ski, int ops) {
206 207
        if (closed)
            throw new ClosedSelectorException();
208 209
        SelChImpl ch = ski.channel;
        pollWrapper.setInterest(ch.getFDVal(), ops);
D
duke 已提交
210 211 212 213 214 215 216 217 218 219 220 221
    }

    public Selector wakeup() {
        synchronized (interruptLock) {
            if (!interruptTriggered) {
                pollWrapper.interrupt();
                interruptTriggered = true;
            }
        }
        return this;
    }
}