src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java
changeset 49316 73da889306b7
parent 49315 2d4964bc055d
parent 49313 49e0f711bb2b
child 49412 2c3b9dbba7bc
child 49495 f46bfa7a2956
child 56346 514c68575523
--- a/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2005, 2018, 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.security.AccessController;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-import sun.security.action.GetIntegerAction;
-
-/**
- * Manipulates a native array of epoll_event structs on Linux:
- *
- * typedef union epoll_data {
- *     void *ptr;
- *     int fd;
- *     __uint32_t u32;
- *     __uint64_t u64;
- *  } epoll_data_t;
- *
- * struct epoll_event {
- *     __uint32_t events;
- *     epoll_data_t data;
- * };
- *
- * The system call to wait for I/O events is epoll_wait(2). It populates an
- * array of epoll_event structures that are passed to the call. The data
- * member of the epoll_event structure contains the same data as was set
- * when the file descriptor was registered to epoll via epoll_ctl(2). In
- * this implementation we set data.fd to be the file descriptor that we
- * register. That way, we have the file descriptor available when we
- * process the events.
- */
-
-class EPollArrayWrapper {
-    // EPOLL_EVENTS
-    private static final int EPOLLIN      = 0x001;
-
-    // opcodes
-    private static final int EPOLL_CTL_ADD      = 1;
-    private static final int EPOLL_CTL_DEL      = 2;
-    private static final int EPOLL_CTL_MOD      = 3;
-
-    // Miscellaneous constants
-    private static final int SIZE_EPOLLEVENT  = sizeofEPollEvent();
-    private static final int EVENT_OFFSET     = 0;
-    private static final int DATA_OFFSET      = offsetofData();
-    private static final int FD_OFFSET        = DATA_OFFSET;
-    private static final int OPEN_MAX         = IOUtil.fdLimit();
-    private static final int NUM_EPOLLEVENTS  = Math.min(OPEN_MAX, 8192);
-
-    // Special value to indicate that an update should be ignored
-    private static final byte  KILLED = (byte)-1;
-
-    // Initial size of arrays for fd registration changes
-    private static final int INITIAL_PENDING_UPDATE_SIZE = 64;
-
-    // maximum size of updatesLow
-    private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
-        new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
-
-    // The fd of the epoll driver
-    private final int epfd;
-
-     // The epoll_event array for results from epoll_wait
-    private final AllocatedNativeObject pollArray;
-
-    // Base address of the epoll_event array
-    private final long pollArrayAddress;
-
-    // The fd of the interrupt line going out
-    private final int outgoingInterruptFD;
-
-    // Number of updated pollfd entries
-    private int updated;
-
-    // object to synchronize fd registration changes
-    private final Object updateLock = new Object();
-
-    // number of file descriptors with registration changes pending
-    private int updateCount;
-
-    // file descriptors with registration changes pending
-    private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
-
-    // events for file descriptors with registration changes pending, indexed
-    // by file descriptor and stored as bytes for efficiency reasons. For
-    // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
-    // least) then the update is stored in a map.
-    private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
-    private final Map<Integer,Byte> eventsHigh = new HashMap<>();
-
-    // Used by release and updateRegistrations to track whether a file
-    // descriptor is registered with epoll.
-    private final BitSet registered = new BitSet();
-
-
-    EPollArrayWrapper(int fd0, int fd1) throws IOException {
-        // creates the epoll file descriptor
-        epfd = epollCreate();
-
-        // the epoll_event array passed to epoll_wait
-        int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT;
-        pollArray = new AllocatedNativeObject(allocationSize, true);
-        pollArrayAddress = pollArray.address();
-
-        outgoingInterruptFD = fd1;
-        epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
-    }
-
-    void putEventOps(int i, int event) {
-        int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
-        pollArray.putInt(offset, event);
-    }
-
-    void putDescriptor(int i, int fd) {
-        int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
-        pollArray.putInt(offset, fd);
-    }
-
-    int getEventOps(int i) {
-        int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
-        return pollArray.getInt(offset);
-    }
-
-    int getDescriptor(int i) {
-        int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
-        return pollArray.getInt(offset);
-    }
-
-    /**
-     * Returns {@code true} if updates for the given key (file
-     * descriptor) are killed.
-     */
-    private boolean isEventsHighKilled(Integer key) {
-        assert key >= MAX_UPDATE_ARRAY_SIZE;
-        Byte value = eventsHigh.get(key);
-        return (value != null && value == KILLED);
-    }
-
-    /**
-     * Sets the pending update events for the given file descriptor. This
-     * method has no effect if the update events is already set to KILLED,
-     * unless {@code force} is {@code true}.
-     */
-    private void setUpdateEvents(int fd, byte events, boolean force) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            if ((eventsLow[fd] != KILLED) || force) {
-                eventsLow[fd] = events;
-            }
-        } else {
-            Integer key = Integer.valueOf(fd);
-            if (!isEventsHighKilled(key) || force) {
-                eventsHigh.put(key, Byte.valueOf(events));
-            }
-        }
-    }
-
-    /**
-     * Returns the pending update events for the given file descriptor.
-     */
-    private byte getUpdateEvents(int fd) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            return eventsLow[fd];
-        } else {
-            Byte result = eventsHigh.get(Integer.valueOf(fd));
-            // result should never be null
-            return result.byteValue();
-        }
-    }
-
-    /**
-     * Update the events for a given file descriptor
-     */
-    void setInterest(int fd, int mask) {
-        synchronized (updateLock) {
-            // record the file descriptor and events
-            int oldCapacity = updateDescriptors.length;
-            if (updateCount == oldCapacity) {
-                int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
-                int[] newDescriptors = new int[newCapacity];
-                System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
-                updateDescriptors = newDescriptors;
-            }
-            updateDescriptors[updateCount++] = fd;
-
-            // events are stored as bytes for efficiency reasons
-            byte b = (byte)mask;
-            assert (b == mask) && (b != KILLED);
-            setUpdateEvents(fd, b, false);
-        }
-    }
-
-    /**
-     * Add a file descriptor
-     */
-    void add(int fd) {
-        // force the initial update events to 0 as it may be KILLED by a
-        // previous registration.
-        synchronized (updateLock) {
-            assert !registered.get(fd);
-            setUpdateEvents(fd, (byte)0, true);
-        }
-    }
-
-    /**
-     * Remove a file descriptor
-     */
-    void remove(int fd) {
-        synchronized (updateLock) {
-            // kill pending and future update for this file descriptor
-            setUpdateEvents(fd, KILLED, false);
-
-            // remove from epoll
-            if (registered.get(fd)) {
-                epollCtl(epfd, EPOLL_CTL_DEL, fd, 0);
-                registered.clear(fd);
-            }
-        }
-    }
-
-    /**
-     * Close epoll file descriptor and free poll array
-     */
-    void close() throws IOException {
-        FileDispatcherImpl.closeIntFD(epfd);
-        pollArray.free();
-    }
-
-    int poll(long timeout) throws IOException {
-        updateRegistrations();
-        return epollWait(pollArrayAddress, NUM_EPOLLEVENTS, timeout, epfd);
-    }
-
-    /**
-     * Update the pending registrations.
-     */
-    private void updateRegistrations() {
-        synchronized (updateLock) {
-            int j = 0;
-            while (j < updateCount) {
-                int fd = updateDescriptors[j];
-                short events = getUpdateEvents(fd);
-                boolean isRegistered = registered.get(fd);
-                int opcode = 0;
-
-                if (events != KILLED) {
-                    if (isRegistered) {
-                        opcode = (events != 0) ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
-                    } else {
-                        opcode = (events != 0) ? EPOLL_CTL_ADD : 0;
-                    }
-                    if (opcode != 0) {
-                        epollCtl(epfd, opcode, fd, events);
-                        if (opcode == EPOLL_CTL_ADD) {
-                            registered.set(fd);
-                        } else if (opcode == EPOLL_CTL_DEL) {
-                            registered.clear(fd);
-                        }
-                    }
-                }
-                j++;
-            }
-            updateCount = 0;
-        }
-    }
-
-    public void interrupt() {
-        interrupt(outgoingInterruptFD);
-    }
-
-    static {
-        IOUtil.load();
-        init();
-    }
-
-    private native int epollCreate();
-    private native void epollCtl(int epfd, int opcode, int fd, int events);
-    private native int epollWait(long pollAddress, int numfds, long timeout,
-                                 int epfd) throws IOException;
-    private static native int sizeofEPollEvent();
-    private static native int offsetofData();
-    private static native void interrupt(int fd);
-    private static native void init();
-}