Skip to content
Snippets Groups Projects
Commit 780a1343 authored by Jonathan Lu's avatar Jonathan Lu Committed by Volker Simonis
Browse files

8024854: PPC64: Basic changes and files to build the class library on AIX


Co-authored-by: default avatarSteve Poole <spoole@linux.vnet.ibm.com>
Co-authored-by: default avatarThomas Stuefe <thomas.stuefe@sap.com>
Reviewed-by: alanb, prr, sla, chegar, michaelm, mullan, art
parent 23c97aca
Branches
Tags
No related merge requests found
Showing
with 2711 additions and 5 deletions
......@@ -210,9 +210,12 @@ define SetupJVMTIDemo
# Param 5 = libs for posix
# Param 6 = libs for windows
# Param 7 = libs for solaris
# Param 8 = libs for linux
# Param 9 = extra directories with required sources
BUILD_DEMO_JVMTI_$1_EXTRA_SRC := \
$$(wildcard $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/demo/jvmti/$1) \
$$(wildcard $$(addprefix $(JDK_TOPDIR)/src/share/demo/jvmti/, $2))
$$(wildcard $$(addprefix $(JDK_TOPDIR)/src/share/demo/jvmti/, $2)) \
$9
BUILD_DEMO_JVMTI_$1_EXTRA_SRC_EXCLUDE := \
$$(wildcard $$(addprefix $(JDK_TOPDIR)/src/share/demo/jvmti/, $2)/README.txt) \
$$(wildcard $$(addprefix $(JDK_TOPDIR)/src/share/demo/jvmti/, $2)/sample.makefile.txt)
......@@ -304,9 +307,19 @@ $(eval $(call SetupJVMTIDemo,compiledMethodLoad, agent_util))
$(eval $(call SetupJVMTIDemo,gctest, agent_util))
$(eval $(call SetupJVMTIDemo,heapTracker, agent_util java_crw_demo))
$(eval $(call SetupJVMTIDemo,heapViewer, agent_util))
# On AIX, hprof requires 'dladdr' from src/aix/porting/porting_aix.cpp
BUILD_LIBHPROF_AIX_EXTRA_SRC :=
BUILD_LIBHPROF_AIX_EXTRA_CFLAGS :=
ifeq ($(OPENJDK_TARGET_OS), aix)
BUILD_LIBHPROF_AIX_EXTRA_SRC += $(JDK_TOPDIR)/src/aix/porting
BUILD_LIBHPROF_AIX_EXTRA_CFLAGS += -I$(JDK_TOPDIR)/src/aix/porting
endif
$(eval $(call SetupJVMTIDemo,hprof, java_crw_demo, \
-I$(JDK_TOPDIR)/src/share/npt -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/npt, C, \
-ldl, ws2_32.lib winmm.lib, -lsocket -lnsl, -lpthread))
-I$(JDK_TOPDIR)/src/share/npt -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/npt \
$(BUILD_LIBHPROF_AIX_EXTRA_CFLAGS), C, \
-ldl, ws2_32.lib winmm.lib, -lsocket -lnsl, -lpthread, $(BUILD_LIBHPROF_AIX_EXTRA_SRC)))
$(eval $(call SetupJVMTIDemo,minst, agent_util java_crw_demo))
$(eval $(call SetupJVMTIDemo,mtrace, agent_util java_crw_demo))
......
......@@ -231,6 +231,10 @@ else ifneq ($(OPENJDK_TARGET_OS), macosx)
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/x11
endif
ifeq ($(OPENJDK_TARGET_OS), aix)
LIBAWT_DIRS += $(JDK_TOPDIR)/src/aix/porting
endif
LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \
$(X_CFLAGS) \
$(foreach dir, $(LIBAWT_DIRS), -I$(dir))
......@@ -309,6 +313,10 @@ ifneq (, $(filter $(OPENJDK_TARGET_OS), solaris linux aix))
LIBAWT_FILES += awt_LoadLibrary.c initIDs.c img_colors.c
endif
ifeq ($(OPENJDK_TARGET_OS), aix)
LIBAWT_FILES += porting_aix.c
endif
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBAWT_FILES += awt_LoadLibrary.c img_colors.c
LIBAWT_CFLAGS += -F/System/Library/Frameworks/JavaVM.framework/Frameworks
......
......@@ -37,7 +37,7 @@ endif
LIBNET_CFLAGS := $(foreach dir, $(LIBNET_SRC_DIRS), -I$(dir))
LIBNET_EXCLUDE_FILES :=
ifeq (, $(filter $(OPENJDK_TARGET_OS), linux aix))
ifneq ($(OPENJDK_TARGET_OS), linux)
LIBNET_EXCLUDE_FILES += linux_close.c
endif
......@@ -45,6 +45,10 @@ ifneq ($(OPENJDK_TARGET_OS), macosx)
LIBNET_EXCLUDE_FILES += bsd_close.c
endif
ifeq ($(OPENJDK_TARGET_OS), aix)
LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/aix/native/java/net/
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBNET_EXCLUDE_FILES += PlainSocketImpl.c PlainDatagramSocketImpl.c SdpSupport.c
else
......
......@@ -114,7 +114,9 @@ endif
ifeq ($(OPENJDK_TARGET_OS), aix)
BUILD_LIBNIO_MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libnio/mapfile-$(OPENJDK_TARGET_OS)
BUILD_LIBNIO_SRC += $(JDK_TOPDIR)/src/aix/native/sun/nio/ch
BUILD_LIBNIO_SRC += \
$(JDK_TOPDIR)/src/aix/native/sun/nio/ch \
$(JDK_TOPDIR)/src/aix/native/sun/nio/fs
BUILD_LIBNIO_FILES += \
AixPollPort.c \
InheritedChannel.c \
......
......@@ -344,6 +344,11 @@ BUILD_LIBHPROF_CFLAGS := -I$(JDK_TOPDIR)/src/share/demo/jvmti/hprof \
-I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/npt \
-I$(JDK_TOPDIR)/src/share/demo/jvmti/java_crw_demo
ifeq ($(OPENJDK_TARGET_OS), aix)
BUILD_LIBHPROF_SRC += $(JDK_TOPDIR)/src/aix/porting
BUILD_LIBHPROF_CFLAGS += -I$(JDK_TOPDIR)/src/aix/porting
endif
BUILD_LIBHPROF_LDFLAGS :=
LIBHPROF_OPTIMIZATION := HIGHEST
......
#
#
# Copyright 2013 SAP AG. 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.
#
# Minimal version for AIX using the standard Latin Type1 Fonts from the
# package X11.fnt.iso_T1. These fonts are installed by default into
# "/usr/lpp/X11/lib/X11/fonts/Type1" and sym-linked to "/usr/lib/X11/fonts/Type1"
# Version
version=1
# Component Font Mappings
dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1
dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1
dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1
dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1
dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1
dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1
dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1
dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1
sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1
sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1
sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1
sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1
serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1
serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1
serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1
serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1
monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1
monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1
monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1
monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1
# Search Sequences
sequence.allfonts=latin-1
filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa
filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa
filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa
filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa
filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa
filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa
filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa
filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa
filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa
filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa
filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa
filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 SAP AG. 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.nio.channels.*;
import java.nio.channels.spi.AsynchronousChannelProvider;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.io.IOException;
public class AixAsynchronousChannelProvider
extends AsynchronousChannelProvider
{
private static volatile AixPollPort defaultPort;
private AixPollPort defaultEventPort() throws IOException {
if (defaultPort == null) {
synchronized (AixAsynchronousChannelProvider.class) {
if (defaultPort == null) {
defaultPort = new AixPollPort(this, ThreadPool.getDefault()).start();
}
}
}
return defaultPort;
}
public AixAsynchronousChannelProvider() {
}
@Override
public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
throws IOException
{
return new AixPollPort(this, ThreadPool.create(nThreads, factory)).start();
}
@Override
public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
throws IOException
{
return new AixPollPort(this, ThreadPool.wrap(executor, initialSize)).start();
}
private Port toPort(AsynchronousChannelGroup group) throws IOException {
if (group == null) {
return defaultEventPort();
} else {
if (!(group instanceof AixPollPort))
throw new IllegalChannelGroupException();
return (Port)group;
}
}
@Override
public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
throws IOException
{
return new UnixAsynchronousServerSocketChannelImpl(toPort(group));
}
@Override
public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
throws IOException
{
return new UnixAsynchronousSocketChannelImpl(toPort(group));
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 SAP AG. 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.nio.channels.spi.AsynchronousChannelProvider;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import sun.misc.Unsafe;
/**
* AsynchronousChannelGroup implementation based on the AIX pollset framework.
*/
final class AixPollPort
extends Port
{
private static final Unsafe unsafe = Unsafe.getUnsafe();
static {
IOUtil.load();
init();
}
/**
* struct pollfd {
* int fd;
* short events;
* short revents;
* }
*/
private static final int SIZEOF_POLLFD = eventSize();
private static final int OFFSETOF_EVENTS = eventsOffset();
private static final int OFFSETOF_REVENTS = reventsOffset();
private static final int OFFSETOF_FD = fdOffset();
// opcodes
private static final int PS_ADD = 0x0;
private static final int PS_MOD = 0x1;
private static final int PS_DELETE = 0x2;
// maximum number of events to poll at a time
private static final int MAX_POLL_EVENTS = 512;
// pollset ID
private final int pollset;
// true if port is closed
private boolean closed;
// socket pair used for wakeup
private final int sp[];
// socket pair used to indicate pending pollsetCtl calls
// Background info: pollsetCtl blocks when another thread is in a pollsetPoll call.
private final int ctlSp[];
// number of wakeups pending
private final AtomicInteger wakeupCount = new AtomicInteger();
// address of the poll array passed to pollset_poll
private final long address;
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
final int events;
Event(PollableChannel channel, int events) {
this.channel = channel;
this.events = events;
}
PollableChannel channel() { return channel; }
int events() { return events; }
}
// queue of events for cases that a polling thread dequeues more than one
// event
private final ArrayBlockingQueue<Event> queue;
private final Event NEED_TO_POLL = new Event(null, 0);
private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
// encapsulates a pollset control event for a file descriptor
static class ControlEvent {
final int fd;
final int events;
final boolean removeOnly;
int error = 0;
ControlEvent(int fd, int events, boolean removeOnly) {
this.fd = fd;
this.events = events;
this.removeOnly = removeOnly;
}
int fd() { return fd; }
int events() { return events; }
boolean removeOnly() { return removeOnly; }
int error() { return error; }
void setError(int error) { this.error = error; }
}
// queue of control events that need to be processed
// (this object is also used for synchronization)
private final HashSet<ControlEvent> controlQueue = new HashSet<ControlEvent>();
// lock used to check whether a poll operation is ongoing
private final ReentrantLock controlLock = new ReentrantLock();
AixPollPort(AsynchronousChannelProvider provider, ThreadPool pool)
throws IOException
{
super(provider, pool);
// open pollset
this.pollset = pollsetCreate();
// create socket pair for wakeup mechanism
int[] sv = new int[2];
try {
socketpair(sv);
// register one end with pollset
pollsetCtl(pollset, PS_ADD, sv[0], POLLIN);
} catch (IOException x) {
pollsetDestroy(pollset);
throw x;
}
this.sp = sv;
// create socket pair for pollset control mechanism
sv = new int[2];
try {
socketpair(sv);
// register one end with pollset
pollsetCtl(pollset, PS_ADD, sv[0], POLLIN);
} catch (IOException x) {
pollsetDestroy(pollset);
throw x;
}
this.ctlSp = sv;
// allocate the poll array
this.address = allocatePollArray(MAX_POLL_EVENTS);
// create the queue and offer the special event to ensure that the first
// threads polls
this.queue = new ArrayBlockingQueue<Event>(MAX_POLL_EVENTS);
this.queue.offer(NEED_TO_POLL);
}
AixPollPort start() {
startThreads(new EventHandlerTask());
return this;
}
/**
* Release all resources
*/
private void implClose() {
synchronized (this) {
if (closed)
return;
closed = true;
}
freePollArray(address);
close0(sp[0]);
close0(sp[1]);
close0(ctlSp[0]);
close0(ctlSp[1]);
pollsetDestroy(pollset);
}
private void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
interrupt(sp[1]);
} catch (IOException x) {
throw new AssertionError(x);
}
}
}
@Override
void executeOnHandlerTask(Runnable task) {
synchronized (this) {
if (closed)
throw new RejectedExecutionException();
offerTask(task);
wakeup();
}
}
@Override
void shutdownHandlerTasks() {
/*
* If no tasks are running then just release resources; otherwise
* write to the one end of the socketpair to wakeup any polling threads.
*/
int nThreads = threadCount();
if (nThreads == 0) {
implClose();
} else {
// send interrupt to each thread
while (nThreads-- > 0) {
wakeup();
}
}
}
// invoke by clients to register a file descriptor
@Override
void startPoll(int fd, int events) {
queueControlEvent(new ControlEvent(fd, events, false));
}
// Callback method for implementations that need special handling when fd is removed
@Override
protected void preUnregister(int fd) {
queueControlEvent(new ControlEvent(fd, 0, true));
}
// Add control event into queue and wait for completion.
// In case the control lock is free, this method also tries to apply the control change directly.
private void queueControlEvent(ControlEvent ev) {
// pollsetCtl blocks when a poll call is ongoing. This is very probable.
// Therefore we let the polling thread do the pollsetCtl call.
synchronized (controlQueue) {
controlQueue.add(ev);
// write byte to socketpair to force wakeup
try {
interrupt(ctlSp[1]);
} catch (IOException x) {
throw new AssertionError(x);
}
do {
// Directly empty queue if no poll call is ongoing.
if (controlLock.tryLock()) {
try {
processControlQueue();
} finally {
controlLock.unlock();
}
} else {
try {
// Do not starve in case the polling thread returned before
// we could write to ctlSp[1] but the polling thread did not
// release the control lock until we checked. Therefore, use
// a timed wait for the time being.
controlQueue.wait(100);
} catch (InterruptedException e) {
// ignore exception and try again
}
}
} while (controlQueue.contains(ev));
}
if (ev.error() != 0) {
throw new AssertionError();
}
}
// Process all events currently stored in the control queue.
private void processControlQueue() {
synchronized (controlQueue) {
// On Aix it is only possible to set the event
// bits on the first call of pollsetCtl. Later
// calls only add bits, but cannot remove them.
// Therefore, we always remove the file
// descriptor ignoring the error and then add it.
Iterator<ControlEvent> iter = controlQueue.iterator();
while (iter.hasNext()) {
ControlEvent ev = iter.next();
pollsetCtl(pollset, PS_DELETE, ev.fd(), 0);
if (!ev.removeOnly()) {
ev.setError(pollsetCtl(pollset, PS_MOD, ev.fd(), ev.events()));
}
iter.remove();
}
controlQueue.notifyAll();
}
}
/*
* Task to process events from pollset and dispatch to the channel's
* onEvent handler.
*
* Events are retreived from pollset in batch and offered to a BlockingQueue
* where they are consumed by handler threads. A special "NEED_TO_POLL"
* event is used to signal one consumer to re-poll when all events have
* been consumed.
*/
private class EventHandlerTask implements Runnable {
private Event poll() throws IOException {
try {
for (;;) {
int n;
controlLock.lock();
try {
n = pollsetPoll(pollset, address, MAX_POLL_EVENTS);
} finally {
controlLock.unlock();
}
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
* they can be handled by other handler threads. The last
* event is handled by this thread (and so is not queued).
*/
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
long eventAddress = getEvent(address, n);
int fd = getDescriptor(eventAddress);
// To emulate one shot semantic we need to remove
// the file descriptor here.
pollsetCtl(pollset, PS_DELETE, fd, 0);
// wakeup
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
drain1(sp[0]);
}
// This is the only file descriptor without
// one shot semantic => register it again.
pollsetCtl(pollset, PS_ADD, sp[0], POLLIN);
// queue special event if there are more events
// to handle.
if (n > 0) {
queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
continue;
}
return EXECUTE_TASK_OR_SHUTDOWN;
}
// wakeup to process control event
if (fd == ctlSp[0]) {
synchronized (controlQueue) {
drain1(ctlSp[0]);
// This file descriptor does not have
// one shot semantic => register it again.
pollsetCtl(pollset, PS_ADD, ctlSp[0], POLLIN);
processControlQueue();
}
continue;
}
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
int events = getRevents(eventAddress);
Event ev = new Event(channel, events);
// n-1 events are queued; This thread handles
// the last one except for the wakeup
if (n > 0) {
queue.offer(ev);
} else {
return ev;
}
}
}
} finally {
fdToChannelLock.readLock().unlock();
}
}
} finally {
// to ensure that some thread will poll when all events have
// been consumed
queue.offer(NEED_TO_POLL);
}
}
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
final boolean isPooledThread = (myGroupAndInvokeCount != null);
boolean replaceMe = false;
Event ev;
try {
for (;;) {
// reset invoke count
if (isPooledThread)
myGroupAndInvokeCount.resetInvokeCount();
try {
replaceMe = false;
ev = queue.take();
// no events and this thread has been "selected" to
// poll for more.
if (ev == NEED_TO_POLL) {
try {
ev = poll();
} catch (IOException x) {
x.printStackTrace();
return;
}
}
} catch (InterruptedException x) {
continue;
}
// handle wakeup to execute task or shutdown
if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
Runnable task = pollTask();
if (task == null) {
// shutdown request
return;
}
// run task (may throw error/exception)
replaceMe = true;
task.run();
continue;
}
// process event
try {
ev.channel().onEvent(ev.events(), isPooledThread);
} catch (Error x) {
replaceMe = true; throw x;
} catch (RuntimeException x) {
replaceMe = true; throw x;
}
}
} finally {
// last handler to exit when shutdown releases resources
int remaining = threadExit(this, replaceMe);
if (remaining == 0 && isShutdown()) {
implClose();
}
}
}
}
/**
* Allocates a poll array to handle up to {@code count} events.
*/
private static long allocatePollArray(int count) {
return unsafe.allocateMemory(count * SIZEOF_POLLFD);
}
/**
* Free a poll array
*/
private static void freePollArray(long address) {
unsafe.freeMemory(address);
}
/**
* Returns event[i];
*/
private static long getEvent(long address, int i) {
return address + (SIZEOF_POLLFD*i);
}
/**
* Returns event->fd
*/
private static int getDescriptor(long eventAddress) {
return unsafe.getInt(eventAddress + OFFSETOF_FD);
}
/**
* Returns event->events
*/
private static int getEvents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_EVENTS);
}
/**
* Returns event->revents
*/
private static int getRevents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_REVENTS);
}
// -- Native methods --
private static native void init();
private static native int eventSize();
private static native int eventsOffset();
private static native int reventsOffset();
private static native int fdOffset();
private static native int pollsetCreate() throws IOException;
private static native int pollsetCtl(int pollset, int opcode, int fd, int events);
private static native int pollsetPoll(int pollset, long pollAddress, int numfds)
throws IOException;
private static native void pollsetDestroy(int pollset);
private static native void socketpair(int[] sv) throws IOException;
private static native void interrupt(int fd) throws IOException;
private static native void drain1(int fd) throws IOException;
private static native void close0(int fd);
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.fs;
import java.nio.file.attribute.*;
import java.util.*;
import java.io.IOException;
/**
* AIX implementation of FileStore
*/
class AixFileStore
extends UnixFileStore
{
AixFileStore(UnixPath file) throws IOException {
super(file);
}
AixFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
super(fs, entry);
}
/**
* Finds, and returns, the mount entry for the file system where the file
* resides.
*/
@Override
UnixMountEntry findMountEntry() throws IOException {
AixFileSystem fs = (AixFileSystem)file().getFileSystem();
// step 1: get realpath
UnixPath path = null;
try {
byte[] rp = UnixNativeDispatcher.realpath(file());
path = new UnixPath(fs, rp);
} catch (UnixException x) {
x.rethrowAsIOException(file());
}
// step 2: find mount point
UnixPath parent = path.getParent();
while (parent != null) {
UnixFileAttributes attrs = null;
try {
attrs = UnixFileAttributes.get(parent, true);
} catch (UnixException x) {
x.rethrowAsIOException(parent);
}
if (attrs.dev() != dev())
break;
path = parent;
parent = parent.getParent();
}
// step 3: lookup mounted file systems
byte[] dir = path.asByteArray();
for (UnixMountEntry entry: fs.getMountEntries()) {
if (Arrays.equals(dir, entry.dir()))
return entry;
}
throw new IOException("Mount point not found");
}
// returns true if extended attributes enabled on file system where given
// file resides, returns false if disabled or unable to determine.
private boolean isExtendedAttributesEnabled(UnixPath path) {
return false;
}
@Override
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
return super.supportsFileAttributeView(type);
}
@Override
public boolean supportsFileAttributeView(String name) {
return super.supportsFileAttributeView(name);
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.fs;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
import java.util.*;
import static sun.nio.fs.AixNativeDispatcher.*;
/**
* AIX implementation of FileSystem
*/
class AixFileSystem extends UnixFileSystem {
AixFileSystem(UnixFileSystemProvider provider, String dir) {
super(provider, dir);
}
@Override
public WatchService newWatchService()
throws IOException
{
return new PollingWatchService();
}
// lazy initialization of the list of supported attribute views
private static class SupportedFileFileAttributeViewsHolder {
static final Set<String> supportedFileAttributeViews =
supportedFileAttributeViews();
private static Set<String> supportedFileAttributeViews() {
Set<String> result = new HashSet<String>();
result.addAll(UnixFileSystem.standardFileAttributeViews());
return Collections.unmodifiableSet(result);
}
}
@Override
public Set<String> supportedFileAttributeViews() {
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
}
@Override
void copyNonPosixAttributes(int ofd, int nfd) {
// TODO: Implement if needed.
}
/**
* Returns object to iterate over the mount entries returned by mntctl
*/
@Override
Iterable<UnixMountEntry> getMountEntries() {
UnixMountEntry[] entries = null;
try {
entries = getmntctl();
} catch (UnixException x) {
// nothing we can do
}
if (entries == null) {
return Collections.emptyList();
}
return Arrays.asList(entries);
}
@Override
FileStore getFileStore(UnixMountEntry entry) throws IOException {
return new AixFileStore(this, entry);
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.fs;
import java.io.IOException;
/**
* AIX implementation of FileSystemProvider
*/
public class AixFileSystemProvider extends UnixFileSystemProvider {
public AixFileSystemProvider() {
super();
}
@Override
AixFileSystem newFileSystem(String dir) {
return new AixFileSystem(this, dir);
}
/**
* @see sun.nio.fs.UnixFileSystemProvider#getFileStore(sun.nio.fs.UnixPath)
*/
@Override
AixFileStore getFileStore(UnixPath path) throws IOException {
return new AixFileStore(path);
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.fs;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* AIX specific system calls.
*/
class AixNativeDispatcher extends UnixNativeDispatcher {
private AixNativeDispatcher() { }
/**
* Special implementation of 'getextmntent' (see SolarisNativeDispatcher)
* that returns all entries at once.
*/
static native UnixMountEntry[] getmntctl() throws UnixException;
// initialize
private static native int init();
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("nio");
return null;
}});
init();
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.tools.attach;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
import java.io.IOException;
// Based on 'LinuxAttachProvider.java'. All occurrences of the string
// "Linux" have been textually replaced by "Aix" to avoid confusion.
/*
* An AttachProvider implementation for Aix that uses a UNIX domain
* socket.
*/
public class AixAttachProvider extends HotSpotAttachProvider {
// perf counter for the JVM version
private static final String JVM_VERSION = "java.property.java.vm.version";
public AixAttachProvider() {
}
public String name() {
return "sun";
}
public String type() {
return "socket";
}
public VirtualMachine attachVirtualMachine(String vmid)
throws AttachNotSupportedException, IOException
{
checkAttachPermission();
// AttachNotSupportedException will be thrown if the target VM can be determined
// to be not attachable.
testAttachable(vmid);
return new AixVirtualMachine(this, vmid);
}
public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)
throws AttachNotSupportedException, IOException
{
if (vmd.provider() != this) {
throw new AttachNotSupportedException("provider mismatch");
}
// To avoid re-checking if the VM if attachable, we check if the descriptor
// is for a hotspot VM - these descriptors are created by the listVirtualMachines
// implementation which only returns a list of attachable VMs.
if (vmd instanceof HotSpotVirtualMachineDescriptor) {
assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable();
checkAttachPermission();
return new AixVirtualMachine(this, vmd.id());
} else {
return attachVirtualMachine(vmd.id());
}
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.tools.attach;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.util.Properties;
// Based on 'LinuxVirtualMachine.java'. All occurrences of the string
// "Linux" have been textually replaced by "Aix" to avoid confusion.
/*
* Aix implementation of HotSpotVirtualMachine
*/
public class AixVirtualMachine extends HotSpotVirtualMachine {
// "/tmp" is used as a global well-known location for the files
// .java_pid<pid>. and .attach_pid<pid>. It is important that this
// location is the same for all processes, otherwise the tools
// will not be able to find all Hotspot processes.
// Any changes to this needs to be synchronized with HotSpot.
private static final String tmpdir = "/tmp";
// The patch to the socket file created by the target VM
String path;
/**
* Attaches to the target VM
*/
AixVirtualMachine(AttachProvider provider, String vmid)
throws AttachNotSupportedException, IOException
{
super(provider, vmid);
// This provider only understands pids
int pid;
try {
pid = Integer.parseInt(vmid);
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier");
}
// Find the socket file. If not found then we attempt to start the
// attach mechanism in the target VM by sending it a QUIT signal.
// Then we attempt to find the socket file again.
path = findSocketFile(pid);
if (path == null) {
File f = createAttachFile(pid);
try {
sendQuitTo(pid);
// give the target VM time to start the attach mechanism
int i = 0;
long delay = 200;
int retries = (int)(attachTimeout() / delay);
do {
try {
Thread.sleep(delay);
} catch (InterruptedException x) { }
path = findSocketFile(pid);
i++;
} while (i <= retries && path == null);
if (path == null) {
throw new AttachNotSupportedException(
"Unable to open socket file: target process not responding " +
"or HotSpot VM not loaded");
}
} finally {
f.delete();
}
}
// Check that the file owner/permission to avoid attaching to
// bogus process
checkPermissions(path);
// Check that we can connect to the process
// - this ensures we throw the permission denied error now rather than
// later when we attempt to enqueue a command.
int s = socket();
try {
connect(s, path);
} finally {
close(s);
}
}
/**
* Detach from the target VM
*/
public void detach() throws IOException {
synchronized (this) {
if (this.path != null) {
this.path = null;
}
}
}
// protocol version
private final static String PROTOCOL_VERSION = "1";
// known errors
private final static int ATTACH_ERROR_BADVERSION = 101;
/**
* Execute the given command in the target VM.
*/
InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
assert args.length <= 3; // includes null
// did we detach?
String p;
synchronized (this) {
if (this.path == null) {
throw new IOException("Detached from target VM");
}
p = this.path;
}
// create UNIX socket
int s = socket();
// connect to target VM
try {
connect(s, p);
} catch (IOException x) {
close(s);
throw x;
}
IOException ioe = null;
// connected - write request
// <ver> <cmd> <args...>
try {
writeString(s, PROTOCOL_VERSION);
writeString(s, cmd);
for (int i=0; i<3; i++) {
if (i < args.length && args[i] != null) {
writeString(s, (String)args[i]);
} else {
writeString(s, "");
}
}
} catch (IOException x) {
ioe = x;
}
// Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s);
// Read the command completion status
int completionStatus;
try {
completionStatus = readInt(sis);
} catch (IOException x) {
sis.close();
if (ioe != null) {
throw ioe;
} else {
throw x;
}
}
if (completionStatus != 0) {
sis.close();
// In the event of a protocol mismatch then the target VM
// returns a known error so that we can throw a reasonable
// error.
if (completionStatus == ATTACH_ERROR_BADVERSION) {
throw new IOException("Protocol mismatch with target VM");
}
// Special-case the "load" command so that the right exception is
// thrown.
if (cmd.equals("load")) {
throw new AgentLoadException("Failed to load agent library");
} else {
throw new IOException("Command failed in target VM");
}
}
// Return the input stream so that the command output can be read
return sis;
}
/*
* InputStream for the socket connection to get target VM
*/
private class SocketInputStream extends InputStream {
int s;
public SocketInputStream(int s) {
this.s = s;
}
public synchronized int read() throws IOException {
byte b[] = new byte[1];
int n = this.read(b, 0, 1);
if (n == 1) {
return b[0] & 0xff;
} else {
return -1;
}
}
public synchronized int read(byte[] bs, int off, int len) throws IOException {
if ((off < 0) || (off > bs.length) || (len < 0) ||
((off + len) > bs.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0)
return 0;
return AixVirtualMachine.read(s, bs, off, len);
}
public void close() throws IOException {
AixVirtualMachine.close(s);
}
}
// Return the socket file for the given process.
private String findSocketFile(int pid) {
File f = new File(tmpdir, ".java_pid" + pid);
if (!f.exists()) {
return null;
}
return f.getPath();
}
// On Solaris/Linux/Aix a simple handshake is used to start the attach mechanism
// if not already started. The client creates a .attach_pid<pid> file in the
// target VM's working directory (or temp directory), and the SIGQUIT handler
// checks for the file.
private File createAttachFile(int pid) throws IOException {
String fn = ".attach_pid" + pid;
String path = "/proc/" + pid + "/cwd/" + fn;
File f = new File(path);
try {
f.createNewFile();
} catch (IOException x) {
f = new File(tmpdir, fn);
f.createNewFile();
}
return f;
}
/*
* Write/sends the given to the target VM. String is transmitted in
* UTF-8 encoding.
*/
private void writeString(int fd, String s) throws IOException {
if (s.length() > 0) {
byte b[];
try {
b = s.getBytes("UTF-8");
} catch (java.io.UnsupportedEncodingException x) {
throw new InternalError(x);
}
AixVirtualMachine.write(fd, b, 0, b.length);
}
byte b[] = new byte[1];
b[0] = 0;
write(fd, b, 0, 1);
}
//-- native methods
static native void sendQuitTo(int pid) throws IOException;
static native void checkPermissions(String path) throws IOException;
static native int socket() throws IOException;
static native void connect(int fd, String path) throws IOException;
static native void close(int fd) throws IOException;
static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
static {
System.loadLibrary("attach");
}
}
/*
* Copyright (c) 2001, 2013, 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.
*/
/*
* This file contains implementations of NET_... functions. The NET_.. functions are
* wrappers for common file- and socket functions plus provisions for non-blocking IO.
*
* (basically, the layers remember all file descriptors waiting for a particular fd;
* all threads waiting on a certain fd can be woken up by sending them a signal; this
* is done e.g. when the fd is closed.)
*
* This was originally copied from the linux_close.c implementation.
*
* Side Note: This coding needs initialization. Under Linux this is done
* automatically via __attribute((constructor)), on AIX this is done manually
* (see aix_close_init).
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
/*
* Stack allocated by thread when doing blocking operation
*/
typedef struct threadEntry {
pthread_t thr; /* this thread */
struct threadEntry *next; /* next thread */
int intr; /* interrupted */
} threadEntry_t;
/*
* Heap allocated during initialized - one entry per fd
*/
typedef struct {
pthread_mutex_t lock; /* fd lock */
threadEntry_t *threads; /* threads blocked on fd */
} fdEntry_t;
/*
* Signal to unblock thread
*/
static int sigWakeup = (SIGRTMAX - 1);
/*
* The fd table and the number of file descriptors
*/
static fdEntry_t *fdTable = NULL;
static int fdCount = 0;
/*
* Null signal handler
*/
static void sig_wakeup(int sig) {
}
/*
* Initialization routine (executed when library is loaded)
* Allocate fd tables and sets up signal handler.
*
* On AIX we don't have __attribute((constructor)) so we need to initialize
* manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
*/
void aix_close_init() {
struct rlimit nbr_files;
sigset_t sigset;
struct sigaction sa;
/* Check already initialized */
if (fdCount > 0 && fdTable != NULL) {
return;
}
/*
* Allocate table based on the maximum number of
* file descriptors.
*/
if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
fprintf(stderr, "library initialization failed - "
"unable to get max # of allocated fds\n");
abort();
}
fdCount = nbr_files.rlim_max;
/*
* We have a conceptual problem here, when the number of files is
* unlimited. As a kind of workaround, we ensure the table is big
* enough for handle even a large number of files. Since SAP itself
* recommends a limit of 32000 files, we just use 64000 as 'infinity'.
*/
if (nbr_files.rlim_max == RLIM_INFINITY) {
fdCount = 64000;
}
fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
if (fdTable == NULL) {
fprintf(stderr, "library initialization failed - "
"unable to allocate file descriptor table - out of memory");
abort();
}
{
int i;
for (i=0; i < fdCount; i++) {
pthread_mutex_init(&fdTable[i].lock, NULL);
}
}
/*
* Setup the signal handler
*/
sa.sa_handler = sig_wakeup;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(sigWakeup, &sa, NULL);
sigemptyset(&sigset);
sigaddset(&sigset, sigWakeup);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
}
/*
* Return the fd table for this fd or NULL is fd out
* of range.
*/
static inline fdEntry_t *getFdEntry(int fd)
{
if (fd < 0 || fd >= fdCount) {
return NULL;
}
return &fdTable[fd];
}
/*
* Start a blocking operation :-
* Insert thread onto thread list for the fd.
*/
static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
{
self->thr = pthread_self();
self->intr = 0;
pthread_mutex_lock(&(fdEntry->lock));
{
self->next = fdEntry->threads;
fdEntry->threads = self;
}
pthread_mutex_unlock(&(fdEntry->lock));
}
/*
* End a blocking operation :-
* Remove thread from thread list for the fd
* If fd has been interrupted then set errno to EBADF
*/
static inline void endOp
(fdEntry_t *fdEntry, threadEntry_t *self)
{
int orig_errno = errno;
pthread_mutex_lock(&(fdEntry->lock));
{
threadEntry_t *curr, *prev=NULL;
curr = fdEntry->threads;
while (curr != NULL) {
if (curr == self) {
if (curr->intr) {
orig_errno = EBADF;
}
if (prev == NULL) {
fdEntry->threads = curr->next;
} else {
prev->next = curr->next;
}
break;
}
prev = curr;
curr = curr->next;
}
}
pthread_mutex_unlock(&(fdEntry->lock));
errno = orig_errno;
}
/*
* Close or dup2 a file descriptor ensuring that all threads blocked on
* the file descriptor are notified via a wakeup signal.
*
* fd1 < 0 => close(fd2)
* fd1 >= 0 => dup2(fd1, fd2)
*
* Returns -1 with errno set if operation fails.
*/
static int closefd(int fd1, int fd2) {
int rv, orig_errno;
fdEntry_t *fdEntry = getFdEntry(fd2);
if (fdEntry == NULL) {
errno = EBADF;
return -1;
}
/*
* Lock the fd to hold-off additional I/O on this fd.
*/
pthread_mutex_lock(&(fdEntry->lock));
{
/*
* And close/dup the file descriptor
* (restart if interrupted by signal)
*/
do {
if (fd1 < 0) {
rv = close(fd2);
} else {
rv = dup2(fd1, fd2);
}
} while (rv == -1 && errno == EINTR);
/*
* Send a wakeup signal to all threads blocked on this
* file descriptor.
*/
threadEntry_t *curr = fdEntry->threads;
while (curr != NULL) {
curr->intr = 1;
pthread_kill( curr->thr, sigWakeup );
curr = curr->next;
}
}
/*
* Unlock without destroying errno
*/
orig_errno = errno;
pthread_mutex_unlock(&(fdEntry->lock));
errno = orig_errno;
return rv;
}
/*
* Wrapper for dup2 - same semantics as dup2 system call except
* that any threads blocked in an I/O system call on fd2 will be
* preempted and return -1/EBADF;
*/
int NET_Dup2(int fd, int fd2) {
if (fd < 0) {
errno = EBADF;
return -1;
}
return closefd(fd, fd2);
}
/*
* Wrapper for close - same semantics as close system call
* except that any threads blocked in an I/O on fd will be
* preempted and the I/O system call will return -1/EBADF.
*/
int NET_SocketClose(int fd) {
return closefd(-1, fd);
}
/************** Basic I/O operations here ***************/
/*
* Macro to perform a blocking IO operation. Restarts
* automatically if interrupted by signal (other than
* our wakeup signal)
*/
#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
int ret; \
threadEntry_t self; \
fdEntry_t *fdEntry = getFdEntry(FD); \
if (fdEntry == NULL) { \
errno = EBADF; \
return -1; \
} \
do { \
startOp(fdEntry, &self); \
ret = FUNC; \
endOp(fdEntry, &self); \
} while (ret == -1 && errno == EINTR); \
return ret; \
}
int NET_Read(int s, void* buf, size_t len) {
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
}
int NET_ReadV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
}
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, int *fromlen) {
socklen_t socklen = *fromlen;
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
*fromlen = socklen;
}
int NET_Send(int s, void *msg, int len, unsigned int flags) {
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
}
int NET_WriteV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
}
int NET_SendTo(int s, const void *msg, int len, unsigned int
flags, const struct sockaddr *to, int tolen) {
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
}
int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
socklen_t socklen = *addrlen;
BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
*addrlen = socklen;
}
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
}
#ifndef USE_SELECT
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
}
#else
int NET_Select(int s, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
BLOCKING_IO_RETURN_INT( s-1,
select(s, readfds, writefds, exceptfds, timeout) );
}
#endif
/*
* Wrapper for poll(s, timeout).
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
int NET_Timeout(int s, long timeout) {
long prevtime = 0, newtime;
struct timeval t;
fdEntry_t *fdEntry = getFdEntry(s);
/*
* Check that fd hasn't been closed.
*/
if (fdEntry == NULL) {
errno = EBADF;
return -1;
}
/*
* Pick up current time as may need to adjust timeout
*/
if (timeout > 0) {
gettimeofday(&t, NULL);
prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
}
for(;;) {
struct pollfd pfd;
int rv;
threadEntry_t self;
/*
* Poll the fd. If interrupted by our wakeup signal
* errno will be set to EBADF.
*/
pfd.fd = s;
pfd.events = POLLIN | POLLERR;
startOp(fdEntry, &self);
rv = poll(&pfd, 1, timeout);
endOp(fdEntry, &self);
/*
* If interrupted then adjust timeout. If timeout
* has expired return 0 (indicating timeout expired).
*/
if (rv < 0 && errno == EINTR) {
if (timeout > 0) {
gettimeofday(&t, NULL);
newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
timeout -= newtime - prevtime;
if (timeout <= 0) {
return 0;
}
prevtime = newtime;
}
} else {
return rv;
}
}
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 SAP AG. 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.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "sun_nio_ch_AixPollPort.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/pollset.h>
#include <fcntl.h>
#include <stddef.h>
#include <dlfcn.h>
#include <errno.h>
/* Initially copied from src/solaris/native/sun/nio/ch/nio_util.h */
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \
} while(0)
typedef pollset_t pollset_create_func(int maxfd);
typedef int pollset_destroy_func(pollset_t ps);
typedef int pollset_ctl_func(pollset_t ps, struct poll_ctl *pollctl_array, int array_length);
typedef int pollset_poll_func(pollset_t ps, struct pollfd *polldata_array, int array_length, int timeout);
static pollset_create_func* _pollset_create = NULL;
static pollset_destroy_func* _pollset_destroy = NULL;
static pollset_ctl_func* _pollset_ctl = NULL;
static pollset_poll_func* _pollset_poll = NULL;
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) {
_pollset_create = (pollset_create_func*) dlsym(RTLD_DEFAULT, "pollset_create");
_pollset_destroy = (pollset_destroy_func*) dlsym(RTLD_DEFAULT, "pollset_destroy");
_pollset_ctl = (pollset_ctl_func*) dlsym(RTLD_DEFAULT, "pollset_ctl");
_pollset_poll = (pollset_poll_func*) dlsym(RTLD_DEFAULT, "pollset_poll");
if (_pollset_create == NULL || _pollset_destroy == NULL ||
_pollset_ctl == NULL || _pollset_poll == NULL) {
JNU_ThrowInternalError(env, "unable to get address of pollset functions");
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_eventSize(JNIEnv* env, jclass this) {
return sizeof(struct pollfd);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_eventsOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, events);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_reventsOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, revents);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_fdOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, fd);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) {
/* pollset_create can take the maximum number of fds, but we
* cannot predict this number so we leave it at OPEN_MAX. */
pollset_t ps = _pollset_create(-1);
if (ps < 0) {
JNU_ThrowIOExceptionWithLastError(env, "pollset_create failed");
}
return (int)ps;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps,
jint opcode, jint fd, jint events) {
struct poll_ctl event;
int res;
event.cmd = opcode;
event.events = events;
event.fd = fd;
RESTARTABLE(_pollset_ctl((pollset_t)ps, &event, 1 /* length */), res);
return (res == 0) ? 0 : errno;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetPoll(JNIEnv *env, jclass c,
jint ps, jlong address, jint numfds) {
struct pollfd *events = jlong_to_ptr(address);
int res;
RESTARTABLE(_pollset_poll(ps, events, numfds, -1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "pollset_poll failed");
}
return res;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_pollsetDestroy(JNIEnv *env, jclass c, jint ps) {
int res;
RESTARTABLE(_pollset_destroy((pollset_t)ps), res);
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
int sp[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
} else {
jint res[2];
res[0] = (jint)sp[0];
res[1] = (jint)sp[1];
(*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
int res;
int buf[1];
buf[0] = 1;
RESTARTABLE(write(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "write failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
int res;
char buf[1];
RESTARTABLE(read(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_close0(JNIEnv *env, jclass c, jint fd) {
int res;
RESTARTABLE(close(fd), res);
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mntctl.h>
#include "jni.h"
#include "jni_util.h"
#include "sun_nio_fs_AixNativeDispatcher.h"
static jfieldID entry_name;
static jfieldID entry_dir;
static jfieldID entry_fstype;
static jfieldID entry_options;
static jclass entry_cls;
/**
* Call this to throw an internal UnixException when a system/library
* call fails
*/
static void throwUnixException(JNIEnv* env, int errnum) {
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
"(I)V", errnum);
if (x != NULL) {
(*env)->Throw(env, x);
}
}
/**
* Initialization
*/
JNIEXPORT jint JNICALL
Java_sun_nio_fs_AixNativeDispatcher_init(JNIEnv* env, jclass this)
{
jint flags = 0;
jclass clazz;
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
if (clazz == NULL) {
return 0;
}
entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
entry_cls = (*env)->NewGlobalRef(env, clazz);
return 0;
}
/**
* Special implementation of getextmntent (see SolarisNativeDispatcher.c)
* that returns all entries at once.
*/
JNIEXPORT jobjectArray JNICALL
Java_sun_nio_fs_AixNativeDispatcher_getmntctl(JNIEnv* env, jclass this)
{
int must_free_buf = 0;
char stack_buf[1024];
char* buffer = stack_buf;
size_t buffer_size = 1024;
int num_entries;
int i;
jobjectArray ret;
struct vmount * vm;
for (i = 0; i < 5; i++) {
num_entries = mntctl(MCTL_QUERY, buffer_size, buffer);
if (num_entries != 0) {
break;
}
if (must_free_buf) {
free(buffer);
}
buffer_size *= 8;
buffer = malloc(buffer_size);
must_free_buf = 1;
}
/* Treat zero entries like errors. */
if (num_entries <= 0) {
if (must_free_buf) {
free(buffer);
}
throwUnixException(env, errno);
return NULL;
}
ret = (*env)->NewObjectArray(env, num_entries, entry_cls, NULL);
if (ret == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
vm = (struct vmount*)buffer;
for (i = 0; i < num_entries; i++) {
jsize len;
jbyteArray bytes;
const char* fstype;
/* We set all relevant attributes so there is no need to call constructor. */
jobject entry = (*env)->AllocObject(env, entry_cls);
if (entry == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
(*env)->SetObjectArrayElement(env, ret, i, entry);
/* vm->vmt_data[...].vmt_size is 32 bit aligned and also includes NULL byte. */
/* Since we only need the characters, it is necessary to check string size manually. */
len = strlen((char*)vm + vm->vmt_data[VMT_OBJECT].vmt_off);
bytes = (*env)->NewByteArray(env, len);
if (bytes == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_OBJECT].vmt_off));
(*env)->SetObjectField(env, entry, entry_name, bytes);
len = strlen((char*)vm + vm->vmt_data[VMT_STUB].vmt_off);
bytes = (*env)->NewByteArray(env, len);
if (bytes == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_STUB].vmt_off));
(*env)->SetObjectField(env, entry, entry_dir, bytes);
switch (vm->vmt_gfstype) {
case MNT_J2:
fstype = "jfs2";
break;
case MNT_NAMEFS:
fstype = "namefs";
break;
case MNT_NFS:
fstype = "nfs";
break;
case MNT_JFS:
fstype = "jfs";
break;
case MNT_CDROM:
fstype = "cdrom";
break;
case MNT_PROCFS:
fstype = "procfs";
break;
case MNT_NFS3:
fstype = "nfs3";
break;
case MNT_AUTOFS:
fstype = "autofs";
break;
case MNT_UDF:
fstype = "udfs";
break;
case MNT_NFS4:
fstype = "nfs4";
break;
case MNT_CIFS:
fstype = "smbfs";
break;
default:
fstype = "unknown";
}
len = strlen(fstype);
bytes = (*env)->NewByteArray(env, len);
if (bytes == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
(*env)->SetObjectField(env, entry, entry_fstype, bytes);
len = strlen((char*)vm + vm->vmt_data[VMT_ARGS].vmt_off);
bytes = (*env)->NewByteArray(env, len);
if (bytes == NULL) {
if (must_free_buf) {
free(buffer);
}
return NULL;
}
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_ARGS].vmt_off));
(*env)->SetObjectField(env, entry, entry_options, bytes);
/* goto the next vmount structure: */
vm = (struct vmount *)((char *)vm + vm->vmt_length);
}
if (must_free_buf) {
free(buffer);
}
return ret;
}
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 SAP AG. 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.
*/
#include "jni.h"
#include "jni_util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
/*
* Based on 'LinuxVirtualMachine.c'. Non-relevant code has been removed and all
* occurrences of the string "Linux" have been replaced by "Aix".
*/
#include "sun_tools_attach_AixVirtualMachine.h"
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \
} while(0)
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: socket
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_socket
(JNIEnv *env, jclass cls)
{
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
JNU_ThrowIOExceptionWithLastError(env, "socket");
}
/* added time out values */
else {
struct timeval tv;
tv.tv_sec = 2 * 60;
tv.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
}
return (jint)fd;
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: connect
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_connect
(JNIEnv *env, jclass cls, jint fd, jstring path)
{
jboolean isCopy;
const char* p = GetStringPlatformChars(env, path, &isCopy);
if (p != NULL) {
struct sockaddr_un addr;
int err = 0;
/* added missing structure initialization */
memset(&addr,0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, p);
/* We must call bind with the actual socketaddr length. This is obligatory for AS400. */
if (connect(fd, (struct sockaddr*)&addr, SUN_LEN(&addr)) == -1) {
err = errno;
}
if (isCopy) {
JNU_ReleaseStringPlatformChars(env, path, p);
}
/*
* If the connect failed then we throw the appropriate exception
* here (can't throw it before releasing the string as can't call
* JNI with pending exception)
*/
if (err != 0) {
if (err == ENOENT) {
JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
} else {
char* msg = strdup(strerror(err));
JNU_ThrowIOException(env, msg);
if (msg != NULL) {
free(msg);
}
}
}
}
}
/*
* Structure and callback function used to send a QUIT signal to all
* children of a given process
*/
typedef struct {
pid_t ppid;
} SendQuitContext;
static void SendQuitCallback(const pid_t pid, void* user_data) {
SendQuitContext* context = (SendQuitContext*)user_data;
pid_t parent = getParent(pid);
if (parent == context->ppid) {
kill(pid, SIGQUIT);
}
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: sendQuitTo
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_sendQuitTo
(JNIEnv *env, jclass cls, jint pid)
{
if (kill((pid_t)pid, SIGQUIT)) {
JNU_ThrowIOExceptionWithLastError(env, "kill");
}
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: checkPermissions
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_checkPermissions
(JNIEnv *env, jclass cls, jstring path)
{
jboolean isCopy;
const char* p = GetStringPlatformChars(env, path, &isCopy);
if (p != NULL) {
struct stat64 sb;
uid_t uid, gid;
int res;
/* added missing initialization of the stat64 buffer */
memset(&sb, 0, sizeof(struct stat64));
/*
* Check that the path is owned by the effective uid/gid of this
* process. Also check that group/other access is not allowed.
*/
uid = geteuid();
gid = getegid();
res = stat64(p, &sb);
if (res != 0) {
/* save errno */
res = errno;
}
/* release p here before we throw an I/O exception */
if (isCopy) {
JNU_ReleaseStringPlatformChars(env, path, p);
}
if (res == 0) {
if ( (sb.st_uid != uid) || (sb.st_gid != gid) ||
((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) ) {
JNU_ThrowIOException(env, "well-known file is not secure");
}
} else {
char* msg = strdup(strerror(res));
JNU_ThrowIOException(env, msg);
if (msg != NULL) {
free(msg);
}
}
}
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: close
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_close
(JNIEnv *env, jclass cls, jint fd)
{
int res;
/* Fixed deadlock when this call of close by the client is not seen by the attach server
* which has accepted the (very short) connection already and is waiting for the request. But read don't get a byte,
* because the close is lost without shutdown.
*/
shutdown(fd, 2);
RESTARTABLE(close(fd), res);
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: read
* Signature: (I[BI)I
*/
JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_read
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
{
unsigned char buf[128];
size_t len = sizeof(buf);
ssize_t n;
size_t remaining = (size_t)(baLen - off);
if (len > remaining) {
len = remaining;
}
RESTARTABLE(read(fd, buf+off, len), n);
if (n == -1) {
JNU_ThrowIOExceptionWithLastError(env, "read");
} else {
if (n == 0) {
n = -1; // EOF
} else {
(*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off));
}
}
return n;
}
/*
* Class: sun_tools_attach_AixVirtualMachine
* Method: write
* Signature: (I[B)V
*/
JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_write
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen)
{
size_t remaining = bufLen;
do {
unsigned char buf[128];
size_t len = sizeof(buf);
int n;
if (len > remaining) {
len = remaining;
}
(*env)->GetByteArrayRegion(env, ba, off, len, (jbyte *)buf);
RESTARTABLE(write(fd, buf, len), n);
if (n > 0) {
off += n;
remaining -= n;
} else {
JNU_ThrowIOExceptionWithLastError(env, "write");
return;
}
} while (remaining > 0);
}
/*
* Copyright 2012, 2013 SAP AG. 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.
*
*/
#include <stdio.h>
#include <sys/ldr.h>
#include <errno.h>
#include "porting_aix.h"
static unsigned char dladdr_buffer[0x4000];
static void fill_dll_info(void) {
int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer));
if (rc == -1) {
fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
fflush(stderr);
}
}
static int dladdr_dont_reload(void* addr, Dl_info* info) {
const struct ld_info* p = (struct ld_info*) dladdr_buffer;
info->dli_fbase = 0; info->dli_fname = 0;
info->dli_sname = 0; info->dli_saddr = 0;
for (;;) {
if (addr >= p->ldinfo_textorg &&
addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
info->dli_fname = p->ldinfo_filename;
info->dli_fbase = p->ldinfo_textorg;
return 1; /* [sic] */
}
if (!p->ldinfo_next) {
break;
}
p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
}
return 0; /* [sic] */
}
#ifdef __cplusplus
extern "C"
#endif
int dladdr(void *addr, Dl_info *info) {
static int loaded = 0;
if (!loaded) {
fill_dll_info();
loaded = 1;
}
if (!addr) {
return 0; /* [sic] */
}
/* Address could be AIX function descriptor? */
void* const addr0 = *( (void**) addr );
int rc = dladdr_dont_reload(addr, info);
if (rc == 0) {
rc = dladdr_dont_reload(addr0, info);
if (rc == 0) { /* [sic] */
fill_dll_info(); /* refill, maybe loadquery info is outdated */
rc = dladdr_dont_reload(addr, info);
if (rc == 0) {
rc = dladdr_dont_reload(addr0, info);
}
}
}
return rc;
}
/*
* Copyright 2012, 2013 SAP AG. 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.
*
*/
/*
* Header file to contain porting-relevant code which does not have a
* home anywhere else.
* This is intially based on hotspot/src/os/aix/vm/{loadlib,porting}_aix.{hpp,cpp}
*/
/*
* Aix' own version of dladdr().
* This function tries to mimick dladdr(3) on Linux
* (see http://linux.die.net/man/3/dladdr)
* dladdr(3) is not POSIX but a GNU extension, and is not available on AIX.
*
* Differences between AIX dladdr and Linux dladdr:
*
* 1) Dl_info.dli_fbase: can never work, is disabled.
* A loaded image on AIX is divided in multiple segments, at least two
* (text and data) but potentially also far more. This is because the loader may
* load each member into an own segment, as for instance happens with the libC.a
* 2) Dl_info.dli_sname: This only works for code symbols (functions); for data, a
* zero-length string is returned ("").
* 3) Dl_info.dli_saddr: For code, this will return the entry point of the function,
* not the function descriptor.
*/
typedef struct {
const char *dli_fname; /* file path of loaded library */
void *dli_fbase; /* doesn't make sence on AIX */
const char *dli_sname; /* symbol name; "" if not known */
void *dli_saddr; /* address of *entry* of function; not function descriptor; */
} Dl_info;
#ifdef __cplusplus
extern "C"
#endif
int dladdr(void *addr, Dl_info *info);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment