Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
38829 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* KQueueArrayWrapper.java27* Implementation of Selector using FreeBSD / Mac OS X kqueues28* Derived from Sun's DevPollArrayWrapper29*/3031package sun.nio.ch;3233import sun.misc.*;34import java.io.IOException;35import java.io.FileDescriptor;36import java.util.Iterator;37import java.util.LinkedList;3839/*40* struct kevent { // 32-bit 64-bit41* uintptr_t ident; // 4 842* short filter; // 2 243* u_short flags; // 2 244* u_int fflags; // 4 445* intptr_t data; // 4 846* void *udata; // 4 847* } // Total: 20 3248*49* The implementation works in 32-bit and 64-bit world. We do this by calling a50* native function that actually sets the sizes and offsets of the fields based51* on which mode we're in.52*/5354class KQueueArrayWrapper {55// kevent filters56static short EVFILT_READ;57static short EVFILT_WRITE;5859// kevent struct60// These fields are now set by initStructSizes in the static initializer.61static short SIZEOF_KEVENT;62static short FD_OFFSET;63static short FILTER_OFFSET;6465// kevent array size66static final int NUM_KEVENTS = 128;6768// Are we in a 64-bit VM?69static boolean is64bit = false;7071// The kevent array (used for outcoming events only)72private AllocatedNativeObject keventArray = null;73private long keventArrayAddress;7475// The kqueue fd76private int kq = -1;7778// The fd of the interrupt line going out79private int outgoingInterruptFD;8081// The fd of the interrupt line coming in82private int incomingInterruptFD;8384static {85IOUtil.load();86initStructSizes();87String datamodel = java.security.AccessController.doPrivileged(88new sun.security.action.GetPropertyAction("sun.arch.data.model")89);90is64bit = datamodel.equals("64");91}9293KQueueArrayWrapper() {94int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;95keventArray = new AllocatedNativeObject(allocationSize, true);96keventArrayAddress = keventArray.address();97kq = init();98}99100// Used to update file description registrations101private static class Update {102SelChImpl channel;103int events;104Update(SelChImpl channel, int events) {105this.channel = channel;106this.events = events;107}108}109110private LinkedList<Update> updateList = new LinkedList<Update>();111112void initInterrupt(int fd0, int fd1) {113outgoingInterruptFD = fd1;114incomingInterruptFD = fd0;115register0(kq, fd0, 1, 0);116}117118int getReventOps(int index) {119int result = 0;120int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;121short filter = keventArray.getShort(offset);122123// This is all that's necessary based on inspection of usage:124// SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,125// ServerSocketChannelImpl, SocketChannelImpl126if (filter == EVFILT_READ) {127result |= Net.POLLIN;128} else if (filter == EVFILT_WRITE) {129result |= Net.POLLOUT;130}131132return result;133}134135int getDescriptor(int index) {136int offset = SIZEOF_KEVENT*index + FD_OFFSET;137/* The ident field is 8 bytes in 64-bit world, however the API wants us138* to return an int. Hence read the 8 bytes but return as an int.139*/140if (is64bit) {141long fd = keventArray.getLong(offset);142assert fd <= Integer.MAX_VALUE;143return (int) fd;144} else {145return keventArray.getInt(offset);146}147}148149void setInterest(SelChImpl channel, int events) {150synchronized (updateList) {151// update existing registration152updateList.add(new Update(channel, events));153}154}155156void release(SelChImpl channel) {157synchronized (updateList) {158// flush any pending updates159for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {160if (it.next().channel == channel) {161it.remove();162}163}164165// remove166register0(kq, channel.getFDVal(), 0, 0);167}168}169170void updateRegistrations() {171synchronized (updateList) {172Update u = null;173while ((u = updateList.poll()) != null) {174SelChImpl ch = u.channel;175if (!ch.isOpen())176continue;177178register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);179}180}181}182183184void close() throws IOException {185if (keventArray != null) {186keventArray.free();187keventArray = null;188}189if (kq >= 0) {190FileDispatcherImpl.closeIntFD(kq);191kq = -1;192}193}194195int poll(long timeout) {196updateRegistrations();197int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);198return updated;199}200201void interrupt() {202interrupt(outgoingInterruptFD);203}204205private native int init();206private static native void initStructSizes();207208private native void register0(int kq, int fd, int read, int write);209private native int kevent0(int kq, long keventAddress, int keventCount,210long timeout);211private static native void interrupt(int fd);212}213214215