7113349: Initial changeset for Macosx port to jdk
Reviewed-by: jjh, alanb, dholmes, anthony, ohrstrom, ksrini, jrose, weijun, smarks
Contributed-by: Alan Bateman <alan.bateman@oracle.com>, Alexander Potochkin <alexander.potochkin@oracle.com>, Alexander Zuev <alexander.zuev@oracle.com>, Andrew Brygin <andrew.brygin@oracle.com>, Artem Ananiev <artem.ananiev@oracle.com>, Alex Strange <astrange@apple.com>, Bino George <bino@apple.com>, Christine Lu <christine.lu@oracle.com>, David Katleman <david.katleman@oracle.com>, David Durrence <david_durrence@apple.com>, Dmitry Cherepanov <dmitry.cherepanov@oracle.com>, Greg Lewis <glewis@eyesbeyond.com>, Kevin Miller <kevin_m_miller@apple.com>, Kurt Miller <kurt@intricatesoftware.com>, Landon Fuller <landonf@plausiblelabs.com>, Leonid Romanov <leonid.romanov@oracle.com>, Loefty Walkowiak <loefty@apple.com>, Mark Reinhold <mark.reinhold@oracle.com>, Naoto Sato <naoto.sato@oracle.com>, Philip Race <philip.race@oracle.com>, Roger Hoover <rhoover@apple.com>, Scott Kovatch <scott.kovatch@oracle.com>, Sergey ByloKhov <sergey.bylokhov@oracle.com>, Mike Swingler <swingler@apple.com>, Tomas Hurka <tomas.hurka@oracle.com>
/*
* Copyright (c) 2011, 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.
*
* 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.
*/
/*
* KQueueArrayWrapper.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollArrayWrapper
*/
package sun.nio.ch;
import sun.misc.*;
import java.io.IOException;
import java.io.FileDescriptor;
/*
* struct kevent { // 32-bit 64-bit
* uintptr_t ident; // 4 8
* short filter; // 2 2
* u_short flags; // 2 2
* u_int fflags; // 4 4
* intptr_t data; // 4 8
* void *udata; // 4 8
* } // Total: 20 32
*
* The implementation works in 32-bit and 64-bit world. We do this by calling a
* native function that actually sets the sizes and offsets of the fields based
* on which mode we're in.
*/
class KQueueArrayWrapper {
// Event masks
static final short POLLIN = AbstractPollArrayWrapper.POLLIN;
static final short POLLOUT = AbstractPollArrayWrapper.POLLOUT;
// kevent filters
static short EVFILT_READ;
static short EVFILT_WRITE;
// kevent struct
// These fields are now set by initStructSizes in the static initializer.
static short SIZEOF_KEVENT;
static short FD_OFFSET;
static short FILTER_OFFSET;
// kevent array size (just under 1K bytes)
static final int NUM_KEVENTS = 50;
// Are we in a 64-bit VM?
static boolean is64bit = false;
// The kevent array (used for outcoming events only)
private AllocatedNativeObject keventArray = null;
private long keventArrayAddress;
// The kqueue fd
private int kq = -1;
// The fd of the interrupt line going out
private int outgoingInterruptFD;
// The fd of the interrupt line coming in
private int incomingInterruptFD;
static {
initStructSizes();
String datamodel = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.arch.data.model")
);
is64bit = datamodel.equals("64");
}
KQueueArrayWrapper() {
int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
keventArray = new AllocatedNativeObject(allocationSize, true);
keventArrayAddress = keventArray.address();
kq = init();
}
void initInterrupt(int fd0, int fd1) {
outgoingInterruptFD = fd1;
incomingInterruptFD = fd0;
register0(kq, fd0, 1, 0);
}
int getReventOps(int index) {
int result = 0;
int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
short filter = keventArray.getShort(offset);
// This is all that's necessary based on inspection of usage:
// SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
// ServerSocketChannelImpl, SocketChannelImpl
if (filter == EVFILT_READ) {
result |= POLLIN;
} else if (filter == EVFILT_WRITE) {
result |= POLLOUT;
}
return result;
}
int getDescriptor(int index) {
int offset = SIZEOF_KEVENT*index + FD_OFFSET;
/* The ident field is 8 bytes in 64-bit world, however the API wants us
* to return an int. Hence read the 8 bytes but return as an int.
*/
if (is64bit) {
long fd = keventArray.getLong(offset);
assert fd <= Integer.MAX_VALUE;
return (int) fd;
} else {
return keventArray.getInt(offset);
}
}
void setInterest(int fd, int events) {
register0(kq, fd, events & POLLIN, events & POLLOUT);
}
void release(int fd) {
register0(kq, fd, 0, 0);
}
void close() throws IOException {
if (keventArray != null) {
keventArray.free();
keventArray = null;
}
if (kq >= 0) {
FileDispatcherImpl.closeIntFD(kq);
kq = -1;
}
}
int poll(long timeout) {
int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
return updated;
}
void interrupt() {
interrupt(outgoingInterruptFD);
}
private native int init();
private static native void initStructSizes();
private native void register0(int kq, int fd, int read, int write);
private native int kevent0(int kq, long keventAddress, int keventCount,
long timeout);
private static native void interrupt(int fd);
}