8023038: PPC64 (part 15): Platform files for AIX/PPC64 support

Reviewed-by: kvn
This commit is contained in:
Volker Simonis 2013-09-06 20:16:09 +02:00
parent 56654216c4
commit 2af861eed1
37 changed files with 11288 additions and 0 deletions

View File

@ -0,0 +1,574 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* 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 "precompiled.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp"
#include "services/attachListener.hpp"
#include "services/dtraceAttacher.hpp"
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path)
#endif
// The attach mechanism on Linux uses a UNIX domain socket. An attach listener
// thread is created at startup or is created on-demand via a signal from
// the client tool. The attach listener creates a socket and binds it to a file
// in the filesystem. The attach listener then acts as a simple (single-
// threaded) server - it waits for a client to connect, reads the request,
// executes it, and returns the response to the client via the socket
// connection.
//
// As the socket is a UNIX domain socket it means that only clients on the
// local machine can connect. In addition there are two other aspects to
// the security:
// 1. The well known file that the socket is bound to has permission 400
// 2. When a client connect, the SO_PEERID socket option is used to
// obtain the credentials of client. We check that the effective uid
// of the client matches this process.
// forward reference
class AixAttachOperation;
class AixAttachListener: AllStatic {
private:
// the path to which we bind the UNIX domain socket
static char _path[UNIX_PATH_MAX];
static bool _has_path;
// Shutdown marker to prevent accept blocking during clean-up.
static bool _shutdown;
// the file descriptor for the listening socket
static int _listener;
static void set_path(char* path) {
if (path == NULL) {
_has_path = false;
} else {
strncpy(_path, path, UNIX_PATH_MAX);
_path[UNIX_PATH_MAX-1] = '\0';
_has_path = true;
}
}
static void set_listener(int s) { _listener = s; }
// reads a request from the given connected socket
static AixAttachOperation* read_request(int s);
public:
enum {
ATTACH_PROTOCOL_VER = 1 // protocol version
};
enum {
ATTACH_ERROR_BADVERSION = 101 // error codes
};
// initialize the listener, returns 0 if okay
static int init();
static char* path() { return _path; }
static bool has_path() { return _has_path; }
static int listener() { return _listener; }
// Shutdown marker to prevent accept blocking during clean-up
static void set_shutdown(bool shutdown) { _shutdown = shutdown; }
static bool is_shutdown() { return _shutdown; }
// write the given buffer to a socket
static int write_fully(int s, char* buf, int len);
static AixAttachOperation* dequeue();
};
class AixAttachOperation: public AttachOperation {
private:
// the connection to the client
int _socket;
public:
void complete(jint res, bufferedStream* st);
void set_socket(int s) { _socket = s; }
int socket() const { return _socket; }
AixAttachOperation(char* name) : AttachOperation(name) {
set_socket(-1);
}
};
// statics
char AixAttachListener::_path[UNIX_PATH_MAX];
bool AixAttachListener::_has_path;
int AixAttachListener::_listener = -1;
// Shutdown marker to prevent accept blocking during clean-up
bool AixAttachListener::_shutdown = false;
// Supporting class to help split a buffer into individual components
class ArgumentIterator : public StackObj {
private:
char* _pos;
char* _end;
public:
ArgumentIterator(char* arg_buffer, size_t arg_size) {
_pos = arg_buffer;
_end = _pos + arg_size - 1;
}
char* next() {
if (*_pos == '\0') {
return NULL;
}
char* res = _pos;
char* next_pos = strchr(_pos, '\0');
if (next_pos < _end) {
next_pos++;
}
_pos = next_pos;
return res;
}
};
// On AIX if sockets block until all data has been transmitted
// successfully in some communication domains a socket "close" may
// never complete. We have to take care that after the socket shutdown
// the listener never enters accept state.
// atexit hook to stop listener and unlink the file that it is
// bound too.
// Some modifications to the listener logic to prevent deadlocks on exit.
// 1. We Shutdown the socket here instead. AixAttachOperation::complete() is not the right place
// since more than one agent in a sequence in JPLIS live tests wouldn't work (Listener thread
// would be dead after the first operation completion).
// 2. close(s) may never return if the listener thread is in socket accept(). Unlinking the file
// should be sufficient for cleanup.
extern "C" {
static void listener_cleanup() {
static int cleanup_done;
if (!cleanup_done) {
cleanup_done = 1;
AixAttachListener::set_shutdown(true);
int s = AixAttachListener::listener();
if (s != -1) {
::shutdown(s, 2);
}
if (AixAttachListener::has_path()) {
::unlink(AixAttachListener::path());
}
}
}
}
// Initialization - create a listener socket and bind it to a file
int AixAttachListener::init() {
char path[UNIX_PATH_MAX]; // socket file
char initial_path[UNIX_PATH_MAX]; // socket file during setup
int listener; // listener socket (file descriptor)
// register function to cleanup
::atexit(listener_cleanup);
int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
if (n < (int)UNIX_PATH_MAX) {
n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
}
if (n >= (int)UNIX_PATH_MAX) {
return -1;
}
// create the listener socket
listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
if (listener == -1) {
return -1;
}
// bind socket
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, initial_path);
::unlink(initial_path);
// We must call bind with the actual socketaddr length. This is obligatory for AS400.
int res = ::bind(listener, (struct sockaddr*)&addr, SUN_LEN(&addr));
if (res == -1) {
RESTARTABLE(::close(listener), res);
return -1;
}
// put in listen mode, set permissions, and rename into place
res = ::listen(listener, 5);
if (res == 0) {
RESTARTABLE(::chmod(initial_path, (S_IREAD|S_IWRITE) & ~(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)), res);
if (res == 0) {
res = ::rename(initial_path, path);
}
}
if (res == -1) {
RESTARTABLE(::close(listener), res);
::unlink(initial_path);
return -1;
}
set_path(path);
set_listener(listener);
set_shutdown(false);
return 0;
}
// Given a socket that is connected to a peer we read the request and
// create an AttachOperation. As the socket is blocking there is potential
// for a denial-of-service if the peer does not response. However this happens
// after the peer credentials have been checked and in the worst case it just
// means that the attach listener thread is blocked.
//
AixAttachOperation* AixAttachListener::read_request(int s) {
char ver_str[8];
sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
// The request is a sequence of strings so we first figure out the
// expected count and the maximum possible length of the request.
// The request is:
// <ver>0<cmd>0<arg>0<arg>0<arg>0
// where <ver> is the protocol version (1), <cmd> is the command
// name ("load", "datadump", ...), and <arg> is an argument
int expected_str_count = 2 + AttachOperation::arg_count_max;
const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
char buf[max_len];
int str_count = 0;
// Read until all (expected) strings have been read, the buffer is
// full, or EOF.
int off = 0;
int left = max_len;
do {
int n;
// Don't block on interrupts because this will
// hang in the clean-up when shutting down.
n = read(s, buf+off, left);
if (n == -1) {
return NULL; // reset by peer or other error
}
if (n == 0) { // end of file reached
break;
}
for (int i=0; i<n; i++) {
if (buf[off+i] == 0) {
// EOS found
str_count++;
// The first string is <ver> so check it now to
// check for protocol mis-match
if (str_count == 1) {
if ((strlen(buf) != strlen(ver_str)) ||
(atoi(buf) != ATTACH_PROTOCOL_VER)) {
char msg[32];
sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
write_fully(s, msg, strlen(msg));
return NULL;
}
}
}
}
off += n;
left -= n;
} while (left > 0 && str_count < expected_str_count);
if (str_count != expected_str_count) {
return NULL; // incomplete request
}
// parse request
ArgumentIterator args(buf, (max_len)-left);
// version already checked
char* v = args.next();
char* name = args.next();
if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
return NULL;
}
AixAttachOperation* op = new AixAttachOperation(name);
for (int i=0; i<AttachOperation::arg_count_max; i++) {
char* arg = args.next();
if (arg == NULL) {
op->set_arg(i, NULL);
} else {
if (strlen(arg) > AttachOperation::arg_length_max) {
delete op;
return NULL;
}
op->set_arg(i, arg);
}
}
op->set_socket(s);
return op;
}
// Dequeue an operation
//
// In the Linux implementation there is only a single operation and clients
// cannot queue commands (except at the socket level).
//
AixAttachOperation* AixAttachListener::dequeue() {
for (;;) {
int s;
// wait for client to connect
struct sockaddr addr;
socklen_t len = sizeof(addr);
memset(&addr, 0, len);
// We must prevent accept blocking on the socket if it has been shut down.
// Therefore we allow interrups and check whether we have been shut down already.
if (AixAttachListener::is_shutdown()) {
return NULL;
}
s=::accept(listener(), &addr, &len);
if (s == -1) {
return NULL; // log a warning?
}
// Added timeouts for read and write. If we get no request within the
// next AttachListenerTimeout milliseconds we just finish the connection.
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = AttachListenerTimeout * 1000;
::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
// get the credentials of the peer and check the effective uid/guid
// - check with jeff on this.
struct peercred_struct cred_info;
socklen_t optlen = sizeof(cred_info);
if (::getsockopt(s, SOL_SOCKET, SO_PEERID, (void*)&cred_info, &optlen) == -1) {
int res;
RESTARTABLE(::close(s), res);
continue;
}
uid_t euid = geteuid();
gid_t egid = getegid();
if (cred_info.euid != euid || cred_info.egid != egid) {
int res;
RESTARTABLE(::close(s), res);
continue;
}
// peer credential look okay so we read the request
AixAttachOperation* op = read_request(s);
if (op == NULL) {
int res;
RESTARTABLE(::close(s), res);
continue;
} else {
return op;
}
}
}
// write the given buffer to the socket
int AixAttachListener::write_fully(int s, char* buf, int len) {
do {
int n = ::write(s, buf, len);
if (n == -1) {
if (errno != EINTR) return -1;
} else {
buf += n;
len -= n;
}
}
while (len > 0);
return 0;
}
// Complete an operation by sending the operation result and any result
// output to the client. At this time the socket is in blocking mode so
// potentially we can block if there is a lot of data and the client is
// non-responsive. For most operations this is a non-issue because the
// default send buffer is sufficient to buffer everything. In the future
// if there are operations that involves a very big reply then it the
// socket could be made non-blocking and a timeout could be used.
void AixAttachOperation::complete(jint result, bufferedStream* st) {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self() via check_and_wait_while_suspended()
// write operation result
char msg[32];
sprintf(msg, "%d\n", result);
int rc = AixAttachListener::write_fully(this->socket(), msg, strlen(msg));
// write any result data
if (rc == 0) {
// Shutdown the socket in the cleanup function to enable more than
// one agent attach in a sequence (see comments to listener_cleanup()).
AixAttachListener::write_fully(this->socket(), (char*) st->base(), st->size());
}
// done
RESTARTABLE(::close(this->socket()), rc);
// were we externally suspended while we were waiting?
thread->check_and_wait_while_suspended();
delete this;
}
// AttachListener functions
AttachOperation* AttachListener::dequeue() {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self() via check_and_wait_while_suspended()
AttachOperation* op = AixAttachListener::dequeue();
// were we externally suspended while we were waiting?
thread->check_and_wait_while_suspended();
return op;
}
// Performs initialization at vm startup
// For AIX we remove any stale .java_pid file which could cause
// an attaching process to think we are ready to receive on the
// domain socket before we are properly initialized
void AttachListener::vm_start() {
char fn[UNIX_PATH_MAX];
struct stat64 st;
int ret;
int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
debug_only(warning("failed to remove stale attach pid file at %s", fn));
}
}
}
int AttachListener::pd_init() {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self() via check_and_wait_while_suspended()
int ret_code = AixAttachListener::init();
// were we externally suspended while we were waiting?
thread->check_and_wait_while_suspended();
return ret_code;
}
// Attach Listener is started lazily except in the case when
// +ReduseSignalUsage is used
bool AttachListener::init_at_startup() {
if (ReduceSignalUsage) {
return true;
} else {
return false;
}
}
// If the file .attach_pid<pid> exists in the working directory
// or /tmp then this is the trigger to start the attach mechanism
bool AttachListener::is_init_trigger() {
if (init_at_startup() || is_initialized()) {
return false; // initialized at startup or already initialized
}
char fn[PATH_MAX+1];
sprintf(fn, ".attach_pid%d", os::current_process_id());
int ret;
struct stat64 st;
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == -1) {
snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
os::get_temp_directory(), os::current_process_id());
RESTARTABLE(::stat64(fn, &st), ret);
}
if (ret == 0) {
// simple check to avoid starting the attach mechanism when
// a bogus user creates the file
if (st.st_uid == geteuid()) {
init();
return true;
}
}
return false;
}
// if VM aborts then remove listener
void AttachListener::abort() {
listener_cleanup();
}
void AttachListener::pd_data_dump() {
os::signal_notify(SIGQUIT);
}
AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
return NULL;
}
jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
out->print_cr("flag '%s' cannot be changed", op->arg(0));
return JNI_ERR;
}
void AttachListener::pd_detachall() {
// Cleanup server socket to detach clients.
listener_cleanup();
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_C2_GLOBALS_AIX_HPP
#define OS_AIX_VM_C2_GLOBALS_AIX_HPP
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
//
// Sets the default values for operating system dependent flags used by the
// server compiler. (see c2_globals.hpp)
//
#endif // OS_AIX_VM_C2_GLOBALS_AIX_HPP

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2011, 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.
*
* 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 "utilities/decoder.hpp"
#include "porting_aix.hpp"
// Provide simple AIXDecoder which enables decoding of C frames in VM.
class AIXDecoder: public AbstractDecoder {
public:
AIXDecoder() {
_decoder_status = no_error;
}
~AIXDecoder() {}
virtual bool can_decode_C_frame_in_vm() const { return true; }
virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName
virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0) == 0);
}
virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
ShouldNotReachHere();
return false;
}
};

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_GLOBALS_AIX_HPP
#define OS_AIX_VM_GLOBALS_AIX_HPP
//
// Defines Aix specific flags. They are not available on other platforms.
//
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
\
/* If UseLargePages == true allow or deny usage of 16M pages. 16M pages are */ \
/* a scarce resource and there may be situations where we do not want the VM */ \
/* to run with 16M pages. (Will fall back to 64K pages). */ \
product_pd(bool, Use16MPages, \
"Use 16M pages if available.") \
\
/* use optimized addresses for the polling page, */ \
/* e.g. map it to a special 32-bit address. */ \
product_pd(bool, OptimizePollingPageLocation, \
"Optimize the location of the polling page used for Safepoints") \
\
product_pd(intx, AttachListenerTimeout, \
"Timeout in ms the attach listener waits for a request") \
\
// Per default, do not allow 16M pages. 16M pages have to be switched on specifically.
define_pd_global(bool, Use16MPages, false);
define_pd_global(bool, OptimizePollingPageLocation, true);
define_pd_global(intx, AttachListenerTimeout, 1000);
//
// Defines Aix-specific default values. The flags are available on all
// platforms, but they may have different default values on other platforms.
//
define_pd_global(bool, UseLargePages, true);
define_pd_global(bool, UseLargePagesIndividualAllocation, false);
define_pd_global(bool, UseOSErrorReporting, false);
define_pd_global(bool, UseThreadPriorities, true) ;
#endif // OS_AIX_VM_GLOBALS_AIX_HPP

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP
#define OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP
// Contains inlined functions for class InterfaceSupport
static inline void serialize_memory(JavaThread *thread) {
os::write_memory_serialize_page(thread);
}
#endif // OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
/* CopyrightVersion 1.2 */
/* This is a special library that should be loaded before libc &
* libthread to interpose the signal handler installation functions:
* sigaction(), signal(), sigset().
* Used for signal-chaining. See RFE 4381843.
*/
#include <signal.h>
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define bool int
#define true 1
#define false 0
// Highest so far on AIX 5.2 is SIGSAK (63)
#define MAXSIGNUM 63
#define MASK(sig) ((unsigned int)1 << sig)
static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
static unsigned int jvmsigs = 0; /* signals used by jvm */
/* used to synchronize the installation of signal handlers */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_t tid = 0;
typedef void (*sa_handler_t)(int);
typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
// signal_t is already defined on AIX
typedef sa_handler_t (*signal_like_function_t)(int, sa_handler_t);
typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
static signal_like_function_t os_signal = 0; /* os's version of signal()/sigset() */
static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
static bool jvm_signal_installing = false;
static bool jvm_signal_installed = false;
static void signal_lock() {
pthread_mutex_lock(&mutex);
/* When the jvm is installing its set of signal handlers, threads
* other than the jvm thread should wait */
if (jvm_signal_installing) {
if (tid != pthread_self()) {
pthread_cond_wait(&cond, &mutex);
}
}
}
static void signal_unlock() {
pthread_mutex_unlock(&mutex);
}
static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
bool is_sigset) {
if (os_signal == NULL) {
if (!is_sigset) {
// Aix: call functions directly instead of dlsym'ing them
os_signal = signal;
} else {
// Aix: call functions directly instead of dlsym'ing them
os_signal = sigset;
}
if (os_signal == NULL) {
printf("%s\n", dlerror());
exit(0);
}
}
return (*os_signal)(sig, disp);
}
static void save_signal_handler(int sig, sa_handler_t disp) {
sigset_t set;
sact[sig].sa_handler = disp;
sigemptyset(&set);
sact[sig].sa_mask = set;
sact[sig].sa_flags = 0;
}
static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
sa_handler_t oldhandler;
bool sigused;
signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0;
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
oldhandler = sact[sig].sa_handler;
save_signal_handler(sig, disp);
signal_unlock();
return oldhandler;
} else if (jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. jvm uses sigaction().
* Leave the piece here just in case. */
oldhandler = call_os_signal(sig, disp, is_sigset);
save_signal_handler(sig, oldhandler);
/* Record the signals used by jvm */
jvmsigs |= MASK(sig);
signal_unlock();
return oldhandler;
} else {
/* jvm has no relation with this signal (yet). Install the
* the handler. */
oldhandler = call_os_signal(sig, disp, is_sigset);
signal_unlock();
return oldhandler;
}
}
sa_handler_t signal(int sig, sa_handler_t disp) {
return set_signal(sig, disp, false);
}
sa_handler_t sigset(int sig, sa_handler_t disp) {
return set_signal(sig, disp, true);
}
static int call_os_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact) {
if (os_sigaction == NULL) {
// Aix: call functions directly instead of dlsym'ing them
os_sigaction = sigaction;
if (os_sigaction == NULL) {
printf("%s\n", dlerror());
exit(0);
}
}
return (*os_sigaction)(sig, act, oact);
}
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
int res;
bool sigused;
struct sigaction oldAct;
signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0;
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
if (oact != NULL) {
*oact = sact[sig];
}
if (act != NULL) {
sact[sig] = *act;
}
signal_unlock();
return 0;
} else if (jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. */
res = call_os_sigaction(sig, act, &oldAct);
sact[sig] = oldAct;
if (oact != NULL) {
*oact = oldAct;
}
/* Record the signals used by jvm */
jvmsigs |= MASK(sig);
signal_unlock();
return res;
} else {
/* jvm has no relation with this signal (yet). Install the
* the handler. */
res = call_os_sigaction(sig, act, oact);
signal_unlock();
return res;
}
}
/* The three functions for the jvm to call into */
void JVM_begin_signal_setting() {
signal_lock();
jvm_signal_installing = true;
tid = pthread_self();
signal_unlock();
}
void JVM_end_signal_setting() {
signal_lock();
jvm_signal_installed = true;
jvm_signal_installing = false;
pthread_cond_broadcast(&cond);
signal_unlock();
}
struct sigaction *JVM_get_signal_action(int sig) {
/* Does race condition make sense here? */
if ((MASK(sig) & jvmsigs) != 0) {
return &sact[sig];
}
return NULL;
}

View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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 "precompiled.hpp"
#include "prims/jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
#include <signal.h>
// sun.misc.Signal ///////////////////////////////////////////////////////////
// Signal code is mostly copied from classic vm, signals_md.c 1.4 98/08/23
/*
* This function is included primarily as a debugging aid. If Java is
* running in a console window, then pressing <CTRL-\\> will cause
* the current state of all active threads and monitors to be written
* to the console window.
*/
JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler))
// Copied from classic vm
// signals_md.c 1.4 98/08/23
void* newHandler = handler == (void *)2
? os::user_handler()
: handler;
switch (sig) {
/* The following are already used by the VM. */
case INTERRUPT_SIGNAL:
case SIGFPE:
case SIGILL:
case SIGSEGV:
/* The following signal is used by the VM to dump thread stacks unless
ReduceSignalUsage is set, in which case the user is allowed to set
his own _native_ handler for this signal; thus, in either case,
we do not allow JVM_RegisterSignal to change the handler. */
case BREAK_SIGNAL:
return (void *)-1;
/* The following signals are used for Shutdown Hooks support. However, if
ReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked via
System.exit(), Java is not allowed to use these signals, and the the
user is allowed to set his own _native_ handler for these signals and
invoke System.exit() as needed. Terminator.setup() is avoiding
registration of these signals when -Xrs is present.
- If the HUP signal is ignored (from the nohup) command, then Java
is not allowed to use this signal.
*/
case SHUTDOWN1_SIGNAL:
case SHUTDOWN2_SIGNAL:
case SHUTDOWN3_SIGNAL:
if (ReduceSignalUsage) return (void*)-1;
if (os::Aix::is_sig_ignored(sig)) return (void*)1;
}
void* oldHandler = os::signal(sig, newHandler);
if (oldHandler == os::user_handler()) {
return (void *)2;
} else {
return oldHandler;
}
JVM_END
JVM_ENTRY_NO_ENV(jboolean, JVM_RaiseSignal(jint sig))
if (ReduceSignalUsage) {
// do not allow SHUTDOWN1_SIGNAL,SHUTDOWN2_SIGNAL,SHUTDOWN3_SIGNAL,
// BREAK_SIGNAL to be raised when ReduceSignalUsage is set, since
// no handler for them is actually registered in JVM or via
// JVM_RegisterSignal.
if (sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL ||
sig == SHUTDOWN3_SIGNAL || sig == BREAK_SIGNAL) {
return JNI_FALSE;
}
}
else if ((sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL ||
sig == SHUTDOWN3_SIGNAL) && os::Aix::is_sig_ignored(sig)) {
// do not allow SHUTDOWN1_SIGNAL to be raised when SHUTDOWN1_SIGNAL
// is ignored, since no handler for them is actually registered in JVM
// or via JVM_RegisterSignal.
// This also applies for SHUTDOWN2_SIGNAL and SHUTDOWN3_SIGNAL
return JNI_FALSE;
}
os::signal_raise(sig);
return JNI_TRUE;
JVM_END
/*
All the defined signal names for Linux.
NOTE that not all of these names are accepted by our Java implementation
Via an existing claim by the VM, sigaction restrictions, or
the "rules of Unix" some of these names will be rejected at runtime.
For example the VM sets up to handle USR1, sigaction returns EINVAL for
STOP, and Linux simply doesn't allow catching of KILL.
Here are the names currently accepted by a user of sun.misc.Signal with
1.4.1 (ignoring potential interaction with use of chaining, etc):
HUP, INT, TRAP, ABRT, IOT, BUS, USR2, PIPE, ALRM, TERM, STKFLT,
CLD, CHLD, CONT, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF,
WINCH, POLL, IO, PWR, SYS
*/
struct siglabel {
const char *name;
int number;
};
struct siglabel siglabels[] = {
/* derived from /usr/include/bits/signum.h on RH7.2 */
"HUP", SIGHUP, /* Hangup (POSIX). */
"INT", SIGINT, /* Interrupt (ANSI). */
"QUIT", SIGQUIT, /* Quit (POSIX). */
"ILL", SIGILL, /* Illegal instruction (ANSI). */
"TRAP", SIGTRAP, /* Trace trap (POSIX). */
"ABRT", SIGABRT, /* Abort (ANSI). */
"IOT", SIGIOT, /* IOT trap (4.2 BSD). */
"BUS", SIGBUS, /* BUS error (4.2 BSD). */
"FPE", SIGFPE, /* Floating-point exception (ANSI). */
"KILL", SIGKILL, /* Kill, unblockable (POSIX). */
"USR1", SIGUSR1, /* User-defined signal 1 (POSIX). */
"SEGV", SIGSEGV, /* Segmentation violation (ANSI). */
"USR2", SIGUSR2, /* User-defined signal 2 (POSIX). */
"PIPE", SIGPIPE, /* Broken pipe (POSIX). */
"ALRM", SIGALRM, /* Alarm clock (POSIX). */
"TERM", SIGTERM, /* Termination (ANSI). */
#ifdef SIGSTKFLT
"STKFLT", SIGSTKFLT, /* Stack fault. */
#endif
"CLD", SIGCLD, /* Same as SIGCHLD (System V). */
"CHLD", SIGCHLD, /* Child status has changed (POSIX). */
"CONT", SIGCONT, /* Continue (POSIX). */
"STOP", SIGSTOP, /* Stop, unblockable (POSIX). */
"TSTP", SIGTSTP, /* Keyboard stop (POSIX). */
"TTIN", SIGTTIN, /* Background read from tty (POSIX). */
"TTOU", SIGTTOU, /* Background write to tty (POSIX). */
"URG", SIGURG, /* Urgent condition on socket (4.2 BSD). */
"XCPU", SIGXCPU, /* CPU limit exceeded (4.2 BSD). */
"XFSZ", SIGXFSZ, /* File size limit exceeded (4.2 BSD). */
"DANGER", SIGDANGER, /* System crash imminent; free up some page space (AIX). */
"VTALRM", SIGVTALRM, /* Virtual alarm clock (4.2 BSD). */
"PROF", SIGPROF, /* Profiling alarm clock (4.2 BSD). */
"WINCH", SIGWINCH, /* Window size change (4.3 BSD, Sun). */
"POLL", SIGPOLL, /* Pollable event occurred (System V). */
"IO", SIGIO, /* I/O now possible (4.2 BSD). */
"PWR", SIGPWR, /* Power failure restart (System V). */
#ifdef SIGSYS
"SYS", SIGSYS /* Bad system call. Only on some Linuxen! */
#endif
};
JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name))
/* find and return the named signal's number */
for(uint i=0; i<ARRAY_SIZE(siglabels); i++)
if(!strcmp(name, siglabels[i].name))
return siglabels[i].number;
return -1;
JVM_END
// used by os::exception_name()
extern bool signal_name(int signo, char* buf, size_t len) {
for(uint i = 0; i < ARRAY_SIZE(siglabels); i++) {
if (signo == siglabels[i].number) {
jio_snprintf(buf, len, "SIG%s", siglabels[i].name);
return true;
}
}
return false;
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_JVM_AIX_H
#define OS_AIX_VM_JVM_AIX_H
// HotSpot integration note:
//
// This is derived from the JDK classic file:
// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
// All local includes have been commented out.
#ifndef JVM_MD_H
#define JVM_MD_H
/*
* This file is currently collecting system-specific dregs for the
* JNI conversion, which should be sorted out later.
*/
// Since we are compiling with c++, we need the following to make c macros
// visible.
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#if !defined(__STDC_CONSTANT_MACROS)
# define __STDC_CONSTANT_MACROS 1
#endif
#if !defined(__STDC_FORMAT_MACROS)
# define __STDC_FORMAT_MACROS 1
#endif
#include <dirent.h> /* For DIR */
// Must redefine NULL because the macro gets redefined to int 0
// by dirent.h. This redefinition is included later then the standard definition in
// globalDefinitions_<compiler>.hpp and leads to assertions in the VM initialization.
// We definitely need NULL to have the same lengh as an address pointer.
#ifdef _LP64
#undef NULL
#define NULL 0L
#else
#ifndef NULL
#define NULL 0
#endif
#endif
#include <sys/param.h> /* For MAXPATHLEN */
#include <sys/socket.h> /* For socklen_t */
#include <unistd.h> /* For F_OK, R_OK, W_OK */
#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
#define JNI_LIB_PREFIX "lib"
#define JNI_LIB_SUFFIX ".so"
// Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
// cause problems if JVM and the rest of JDK are built on different
// Linux releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1,
// so buffers declared in VM are always >= 4096.
#define JVM_MAXPATHLEN MAXPATHLEN + 1
#define JVM_R_OK R_OK
#define JVM_W_OK W_OK
#define JVM_X_OK X_OK
#define JVM_F_OK F_OK
/*
* File I/O
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
/* O Flags */
#define JVM_O_RDONLY O_RDONLY
#define JVM_O_WRONLY O_WRONLY
#define JVM_O_RDWR O_RDWR
#define JVM_O_O_APPEND O_APPEND
#define JVM_O_EXCL O_EXCL
#define JVM_O_CREAT O_CREAT
/* Signal definitions */
#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */
#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
#define SHUTDOWN2_SIGNAL SIGINT
#define SHUTDOWN3_SIGNAL SIGTERM
#endif /* JVM_MD_H */
#endif // OS_AIX_VM_JVM_AIX_H

View File

@ -0,0 +1,124 @@
/*
* 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 "runtime/arguments.hpp"
#include "libperfstat_aix.hpp"
// For dlopen and friends
#include <fcntl.h>
// handle to the libperfstat
static void* g_libhandle = NULL;
// whether initialization worked
static bool g_initialized = false;
typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
int sizeof_userbuff, int desired_number);
typedef int (*fun_perfstat_memory_total_t) (perfstat_id_t *name, perfstat_memory_total_t* userbuff,
int sizeof_userbuff, int desired_number);
typedef void (*fun_perfstat_reset_t) ();
static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL;
static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL;
static fun_perfstat_reset_t g_fun_perfstat_reset = NULL;
bool libperfstat::init() {
if (g_initialized) {
return true;
}
g_initialized = false;
// dynamically load the libperfstat porting library.
g_libhandle = dlopen("/usr/lib/libperfstat.a(shr_64.o)", RTLD_MEMBER | RTLD_NOW);
if (!g_libhandle) {
if (Verbose) {
fprintf(stderr, "Cannot load libperfstat.a (dlerror: %s)", dlerror());
}
return false;
}
// resolve function pointers
#define RESOLVE_FUN_NO_ERROR(name) \
g_fun_##name = (fun_##name##_t) dlsym(g_libhandle, #name);
#define RESOLVE_FUN(name) \
RESOLVE_FUN_NO_ERROR(name) \
if (!g_fun_##name) { \
if (Verbose) { \
fprintf(stderr, "Cannot resolve " #name "() from libperfstat.a\n" \
" (dlerror: %s)", dlerror()); \
} \
return false; \
}
RESOLVE_FUN(perfstat_cpu_total);
RESOLVE_FUN(perfstat_memory_total);
RESOLVE_FUN(perfstat_reset);
g_initialized = true;
return true;
}
void libperfstat::cleanup() {
g_initialized = false;
if (g_libhandle) {
dlclose(g_libhandle);
g_libhandle = NULL;
}
g_fun_perfstat_cpu_total = NULL;
g_fun_perfstat_memory_total = NULL;
g_fun_perfstat_reset = NULL;
}
int libperfstat::perfstat_memory_total(perfstat_id_t *name,
perfstat_memory_total_t* userbuff,
int sizeof_userbuff, int desired_number) {
assert(g_initialized, "libperfstat not initialized");
assert(g_fun_perfstat_memory_total, "");
return g_fun_perfstat_memory_total(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
int sizeof_userbuff, int desired_number) {
assert(g_initialized, "libperfstat not initialized");
assert(g_fun_perfstat_cpu_total, "");
return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number);
}
void libperfstat::perfstat_reset() {
assert(g_initialized, "libperfstat not initialized");
assert(g_fun_perfstat_reset, "");
g_fun_perfstat_reset();
}

View File

@ -0,0 +1,59 @@
/*
* 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.
*
*/
// encapsulates the libperfstat library.
//
// The purpose of this code is to dynamically load the libperfstat library
// instead of statically linking against it. The libperfstat library is an
// AIX-specific library which only exists on AIX, not on PASE. If I want to
// share binaries between AIX and PASE, I cannot directly link against libperfstat.so.
#ifndef OS_AIX_VM_LIBPERFSTAT_AIX_HPP
#define OS_AIX_VM_LIBPERFSTAT_AIX_HPP
#include <libperfstat.h>
class libperfstat {
public:
// Load the libperfstat library (must be in LIBPATH).
// Returns true if succeeded, false if error.
static bool init();
// cleanup of the libo4 porting library.
static void cleanup();
// direct wrappers for the libperfstat functionality. All they do is
// to call the functions with the same name via function pointers.
static int perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
int sizeof_userbuff, int desired_number);
static int perfstat_memory_total(perfstat_id_t *name, perfstat_memory_total_t* userbuff,
int sizeof_userbuff, int desired_number);
static void perfstat_reset();
};
#endif // OS_AIX_VM_LIBPERFSTAT_AIX_HPP

View File

@ -0,0 +1,185 @@
/*
* 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.
*
*/
// Implementation of LoadedLibraries and friends
// Ultimately this just uses loadquery()
// See:
// http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp
// ?topic=/com.ibm.aix.basetechref/doc/basetrf1/loadquery.htm
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
// 'allocation.inline.hpp' triggers the inclusion of 'inttypes.h' which defines macros
// required by the definitions in 'globalDefinitions.hpp'. But these macros in 'inttypes.h'
// are only defined if '__STDC_FORMAT_MACROS' is defined!
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/threadCritical.hpp"
#include "utilities/debug.hpp"
#include "utilities/ostream.hpp"
#include "loadlib_aix.hpp"
#include "porting_aix.hpp"
// For loadquery()
#include <sys/ldr.h>
///////////////////////////////////////////////////////////////////////////////
// Implementation for LoadedLibraryModule
// output debug info
void LoadedLibraryModule::print(outputStream* os) const {
os->print("%15.15s: text: " INTPTR_FORMAT " - " INTPTR_FORMAT
", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " ",
shortname, text_from, text_to, data_from, data_to);
os->print(" %s", fullpath);
if (strlen(membername) > 0) {
os->print("(%s)", membername);
}
os->cr();
}
///////////////////////////////////////////////////////////////////////////////
// Implementation for LoadedLibraries
// class variables
LoadedLibraryModule LoadedLibraries::tab[MAX_MODULES];
int LoadedLibraries::num_loaded = 0;
// Checks whether the address p points to any of the loaded code segments.
// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
// static
const LoadedLibraryModule* LoadedLibraries::find_for_text_address(const unsigned char* p) {
if (num_loaded == 0) {
reload();
}
for (int i = 0; i < num_loaded; i++) {
if (tab[i].is_in_text(p)) {
return &tab[i];
}
}
return NULL;
}
// Checks whether the address p points to any of the loaded data segments.
// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
// static
const LoadedLibraryModule* LoadedLibraries::find_for_data_address(const unsigned char* p) {
if (num_loaded == 0) {
reload();
}
for (int i = 0; i < num_loaded; i++) {
if (tab[i].is_in_data(p)) {
return &tab[i];
}
}
return NULL;
}
// Rebuild the internal table of LoadedLibraryModule objects
// static
void LoadedLibraries::reload() {
ThreadCritical cs;
// discard old content
num_loaded = 0;
// Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX.
size_t buf_size = 4096;
char* loadquery_buf = AllocateHeap(buf_size, mtInternal);
while(loadquery(L_GETINFO, loadquery_buf, buf_size) == -1) {
if (errno == ENOMEM) {
buf_size *= 2;
loadquery_buf = ReallocateHeap(loadquery_buf, buf_size, mtInternal);
} else {
FreeHeap(loadquery_buf);
// Ensure that the uintptr_t pointer is valid
assert(errno != EFAULT, "loadquery: Invalid uintptr_t in info buffer.");
fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
return;
}
}
// Iterate over the loadquery result. For details see sys/ldr.h on AIX.
const struct ld_info* p = (struct ld_info*) loadquery_buf;
// Ensure we have all loaded libs.
bool all_loaded = false;
while(num_loaded < MAX_MODULES) {
LoadedLibraryModule& mod = tab[num_loaded];
mod.text_from = (const unsigned char*) p->ldinfo_textorg;
mod.text_to = (const unsigned char*) (((char*)p->ldinfo_textorg) + p->ldinfo_textsize);
mod.data_from = (const unsigned char*) p->ldinfo_dataorg;
mod.data_to = (const unsigned char*) (((char*)p->ldinfo_dataorg) + p->ldinfo_datasize);
sprintf(mod.fullpath, "%.*s", sizeof(mod.fullpath), p->ldinfo_filename);
// do we have a member name as well (see ldr.h)?
const char* p_mbr_name = p->ldinfo_filename + strlen(p->ldinfo_filename) + 1;
if (*p_mbr_name) {
sprintf(mod.membername, "%.*s", sizeof(mod.membername), p_mbr_name);
} else {
mod.membername[0] = '\0';
}
// fill in the short name
const char* p_slash = strrchr(mod.fullpath, '/');
if (p_slash) {
sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), p_slash + 1);
} else {
sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), mod.fullpath);
}
num_loaded ++;
// next entry...
if (p->ldinfo_next) {
p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
} else {
all_loaded = true;
break;
}
}
FreeHeap(loadquery_buf);
// Ensure we have all loaded libs
assert(all_loaded, "loadquery returned more entries then expected. Please increase MAX_MODULES");
} // end LoadedLibraries::reload()
// output loaded libraries table
//static
void LoadedLibraries::print(outputStream* os) {
for (int i = 0; i < num_loaded; i++) {
tab[i].print(os);
}
}

View File

@ -0,0 +1,128 @@
/*
* 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.
*
*/
// Loadlib_aix.cpp contains support code for analysing the memory
// layout of loaded binaries in ones own process space.
//
// It is needed, among other things, to provide a dladdr() emulation, because
// that one is not provided by AIX
#ifndef OS_AIX_VM_LOADLIB_AIX_HPP
#define OS_AIX_VM_LOADLIB_AIX_HPP
class outputStream;
// This class holds information about a single loaded library module.
// Note that on AIX, a single library can be spread over multiple
// uintptr_t range on a module base, eg.
// libC.a(shr3_64.o) or libC.a(shrcore_64.o).
class LoadedLibraryModule {
friend class LoadedLibraries;
char fullpath[512]; // eg /usr/lib/libC.a
char shortname[30]; // eg libC.a
char membername[30]; // eg shrcore_64.o
const unsigned char* text_from;
const unsigned char* text_to;
const unsigned char* data_from;
const unsigned char* data_to;
public:
const char* get_fullpath() const {
return fullpath;
}
const char* get_shortname() const {
return shortname;
}
const char* get_membername() const {
return membername;
}
// text_from, text_to: returns the range of the text (code)
// segment for that module
const unsigned char* get_text_from() const {
return text_from;
}
const unsigned char* get_text_to() const {
return text_to;
}
// data_from/data_to: returns the range of the data
// segment for that module
const unsigned char* get_data_from() const {
return data_from;
}
const unsigned char* get_data_to() const {
return data_to;
}
// returns true if the
bool is_in_text(const unsigned char* p) const {
return p >= text_from && p < text_to ? true : false;
}
bool is_in_data(const unsigned char* p) const {
return p >= data_from && p < data_to ? true : false;
}
// output debug info
void print(outputStream* os) const;
}; // end LoadedLibraryModule
// This class is a singleton holding a map of all loaded binaries
// in the AIX process space.
class LoadedLibraries
// : AllStatic (including allocation.hpp just for AllStatic is overkill.)
{
private:
enum {MAX_MODULES = 100};
static LoadedLibraryModule tab[MAX_MODULES];
static int num_loaded;
public:
// rebuild the internal table of LoadedLibraryModule objects
static void reload();
// checks whether the address p points to any of the loaded code segments.
// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
static const LoadedLibraryModule* find_for_text_address(const unsigned char* p);
// checks whether the address p points to any of the loaded data segments.
// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
static const LoadedLibraryModule* find_for_data_address(const unsigned char* p);
// output debug info
static void print(outputStream* os);
}; // end LoadedLibraries
#endif // OS_AIX_VM_LOADLIB_AIX_HPP

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_MUTEX_AIX_INLINE_HPP
#define OS_AIX_VM_MUTEX_AIX_INLINE_HPP
#include "os_aix.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "thread_aix.inline.hpp"
#endif // OS_AIX_VM_MUTEX_AIX_INLINE_HPP

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
// no precompiled headers
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/vmThread.hpp"
#ifdef TARGET_ARCH_ppc
# include "assembler_ppc.inline.hpp"
#endif
void OSThread::pd_initialize() {
assert(this != NULL, "check");
_thread_id = 0;
_pthread_id = 0;
_siginfo = NULL;
_ucontext = NULL;
_expanding_stack = 0;
_alt_sig_stack = NULL;
_last_cpu_times.sys = _last_cpu_times.user = 0L;
sigemptyset(&_caller_sigmask);
_startThread_lock = new Monitor(Mutex::event, "startThread_lock", true);
assert(_startThread_lock !=NULL, "check");
}
void OSThread::pd_destroy() {
delete _startThread_lock;
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_OSTHREAD_AIX_HPP
#define OS_AIX_VM_OSTHREAD_AIX_HPP
public:
typedef pid_t thread_id_t;
private:
int _thread_type;
public:
int thread_type() const {
return _thread_type;
}
void set_thread_type(int type) {
_thread_type = type;
}
private:
// _pthread_id is the pthread id, which is used by library calls
// (e.g. pthread_kill).
pthread_t _pthread_id;
sigset_t _caller_sigmask; // Caller's signal mask
public:
// Methods to save/restore caller's signal mask
sigset_t caller_sigmask() const { return _caller_sigmask; }
void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; }
#ifndef PRODUCT
// Used for debugging, return a unique integer for each thread.
int thread_identifier() const { return _thread_id; }
#endif
#ifdef ASSERT
// We expect no reposition failures so kill vm if we get one.
//
bool valid_reposition_failure() {
return false;
}
#endif // ASSERT
pthread_t pthread_id() const {
return _pthread_id;
}
void set_pthread_id(pthread_t tid) {
_pthread_id = tid;
}
// ***************************************************************
// suspension support.
// ***************************************************************
public:
// flags that support signal based suspend/resume on Linux are in a
// separate class to avoid confusion with many flags in OSThread that
// are used by VM level suspend/resume.
os::SuspendResume sr;
// _ucontext and _siginfo are used by SR_handler() to save thread context,
// and they will later be used to walk the stack or reposition thread PC.
// If the thread is not suspended in SR_handler() (e.g. self suspend),
// the value in _ucontext is meaningless, so we must use the last Java
// frame information as the frame. This will mean that for threads
// that are parked on a mutex the profiler (and safepoint mechanism)
// will see the thread as if it were still in the Java frame. This
// not a problem for the profiler since the Java frame is a close
// enough result. For the safepoint mechanism when the give it the
// Java frame we are not at a point where the safepoint needs the
// frame to that accurate (like for a compiled safepoint) since we
// should be in a place where we are native and will block ourselves
// if we transition.
private:
void* _siginfo;
ucontext_t* _ucontext;
int _expanding_stack; // non zero if manually expanding stack
address _alt_sig_stack; // address of base of alternate signal stack
public:
void* siginfo() const { return _siginfo; }
void set_siginfo(void* ptr) { _siginfo = ptr; }
ucontext_t* ucontext() const { return _ucontext; }
void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
void set_expanding_stack(void) { _expanding_stack = 1; }
void clear_expanding_stack(void) { _expanding_stack = 0; }
int expanding_stack(void) { return _expanding_stack; }
void set_alt_sig_stack(address val) { _alt_sig_stack = val; }
address alt_sig_stack(void) { return _alt_sig_stack; }
private:
Monitor* _startThread_lock; // sync parent and child in thread creation
public:
Monitor* startThread_lock() const {
return _startThread_lock;
}
// ***************************************************************
// Platform dependent initialization and cleanup
// ***************************************************************
private:
void pd_initialize();
void pd_destroy();
public:
// The last measured values of cpu timing to prevent the "stale
// value return" bug in thread_cpu_time.
volatile struct {
jlong sys;
jlong user;
} _last_cpu_times;
#endif // OS_AIX_VM_OSTHREAD_AIX_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,385 @@
/*
* Copyright (c) 1999, 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.
*
* 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.
*
*/
#ifndef OS_AIX_VM_OS_AIX_HPP
#define OS_AIX_VM_OS_AIX_HPP
// Information about the protection of the page at address '0' on this os.
static bool zero_page_read_protected() { return false; }
// Class Aix defines the interface to the Aix operating systems.
class Aix {
friend class os;
// For signal-chaining
// highest so far (AIX 5.2) is SIGSAK (63)
#define MAXSIGNUM 63
// length of strings included in the libperfstat structures
#define IDENTIFIER_LENGTH 64
static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions
static unsigned int sigs; // mask of signals that have
// preinstalled signal handlers
static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
// __sigaction(), signal() is loaded
static struct sigaction *(*get_signal_action)(int);
static struct sigaction *get_preinstalled_handler(int);
static void save_preinstalled_handler(int, struct sigaction&);
static void check_signal_handler(int sig);
// For signal flags diagnostics
static int sigflags[MAXSIGNUM];
protected:
static julong _physical_memory;
static pthread_t _main_thread;
static Mutex* _createThread_lock;
static int _page_size;
static int _logical_cpus;
// -1 = uninitialized, 0 = AIX, 1 = OS/400 (PASE)
static int _on_pase;
// -1 = uninitialized, otherwise 16 bit number:
// lower 8 bit - minor version
// higher 8 bit - major version
// For AIX, e.g. 0x0601 for AIX 6.1
// for OS/400 e.g. 0x0504 for OS/400 V5R4
static int _os_version;
// -1 = uninitialized,
// 0 - SPEC1170 not requested (XPG_SUS_ENV is OFF or not set)
// 1 - SPEC1170 requested (XPG_SUS_ENV is ON)
static int _xpg_sus_mode;
// -1 = uninitialized,
// 0 - EXTSHM=OFF or not set
// 1 - EXTSHM=ON
static int _extshm;
// page sizes on AIX.
//
// AIX supports four different page sizes - 4K, 64K, 16MB, 16GB. The latter two
// (16M "large" resp. 16G "huge" pages) require special setup and are normally
// not available.
//
// AIX supports multiple page sizes per process, for:
// - Stack (of the primordial thread, so not relevant for us)
// - Data - data, bss, heap, for us also pthread stacks
// - Text - text code
// - shared memory
//
// Default page sizes can be set via linker options (-bdatapsize, -bstacksize, ...)
// and via environment variable LDR_CNTRL (DATAPSIZE, STACKPSIZE, ...)
//
// For shared memory, page size can be set dynamically via shmctl(). Different shared memory
// regions can have different page sizes.
//
// More information can be found at AIBM info center:
// http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/multiple_page_size_app_support.htm
//
// -----
// We want to support 4K and 64K and, if the machine is set up correctly, 16MB pages.
//
// page size of the stack of newly created pthreads
// (should be LDR_CNTRL DATAPSIZE because stack is allocated on heap by pthread lib)
static int _stack_page_size;
// Default shm page size. Read: what page size shared memory will be backed
// with if no page size was set explicitly using shmctl(SHM_PAGESIZE).
// Should be LDR_CNTRL SHMPSIZE.
static size_t _shm_default_page_size;
// True if sys V shm can be used with 64K pages dynamically.
// (via shmctl(.. SHM_PAGESIZE..). Should be true for AIX 53 and
// newer / PASE V6R1 and newer. (0 or 1, -1 if not initialized)
static int _can_use_64K_pages;
// True if sys V shm can be used with 16M pages dynamically.
// (via shmctl(.. SHM_PAGESIZE..). Only true on AIX 5.3 and
// newer, if the system was set up to use 16M pages and the
// jvm has enough user rights. (0 or 1, -1 if not initialized)
static int _can_use_16M_pages;
static julong available_memory();
static julong physical_memory() { return _physical_memory; }
static void initialize_system_info();
// OS recognitions (PASE/AIX, OS level) call this before calling any
// one of Aix::on_pase(), Aix::os_version().
static void initialize_os_info();
static int commit_memory_impl(char* addr, size_t bytes, bool exec);
static int commit_memory_impl(char* addr, size_t bytes,
size_t alignment_hint, bool exec);
// Scan environment for important settings which might effect the
// VM. Trace out settings. Warn about invalid settings and/or
// correct them.
//
// Must run after os::Aix::initialue_os_info().
static void scan_environment();
// Retrieve information about multipage size support. Will initialize
// _page_size, _stack_page_size, _can_use_64K_pages/_can_use_16M_pages
static void query_multipage_support();
// Initialize libo4 (on PASE) and libperfstat (on AIX). Call this
// before relying on functions from either lib, e.g. Aix::get_meminfo().
static void initialize_libo4();
static void initialize_libperfstat();
static bool supports_variable_stack_size();
public:
static void init_thread_fpu_state();
static pthread_t main_thread(void) { return _main_thread; }
// returns kernel thread id (similar to LWP id on Solaris), which can be
// used to access /proc
static pid_t gettid();
static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; }
static Mutex* createThread_lock(void) { return _createThread_lock; }
static void hotspot_sigmask(Thread* thread);
// Given an address, returns the size of the page backing that address
static size_t query_pagesize(void* p);
// Return `true' if the calling thread is the primordial thread. The
// primordial thread is the thread which contains the main function,
// *not* necessarily the thread which initialized the VM by calling
// JNI_CreateJavaVM.
static bool is_primordial_thread(void);
static int page_size(void) {
assert(_page_size != -1, "not initialized");
return _page_size;
}
// Accessor methods for stack page size which may be different from usual page size.
static int stack_page_size(void) {
assert(_stack_page_size != -1, "not initialized");
return _stack_page_size;
}
// default shm page size. Read: what page size shared memory
// will be backed with if no page size was set explicitly using shmctl(SHM_PAGESIZE).
// Should be LDR_CNTRL SHMPSIZE.
static int shm_default_page_size(void) {
assert(_shm_default_page_size != -1, "not initialized");
return _shm_default_page_size;
}
// Return true if sys V shm can be used with 64K pages dynamically
// (via shmctl(.. SHM_PAGESIZE..).
static bool can_use_64K_pages () {
assert(_can_use_64K_pages != -1, "not initialized");
return _can_use_64K_pages == 1 ? true : false;
}
// Return true if sys V shm can be used with 16M pages dynamically.
// (via shmctl(.. SHM_PAGESIZE..).
static bool can_use_16M_pages () {
assert(_can_use_16M_pages != -1, "not initialized");
return _can_use_16M_pages == 1 ? true : false;
}
static address ucontext_get_pc(ucontext_t* uc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* uc, address pc);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_aix_signal, harmlessly.
static bool signal_handlers_are_installed;
static int get_our_sigflags(int);
static void set_our_sigflags(int, int);
static void signal_sets_init();
static void install_signal_handlers();
static void set_signal_handler(int, bool);
static bool is_sig_ignored(int sig);
static sigset_t* unblocked_signals();
static sigset_t* vm_signals();
static sigset_t* allowdebug_blocked_signals();
// For signal-chaining
static struct sigaction *get_chained_signal_action(int sig);
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
// libpthread version string
static void libpthread_init();
// Minimum stack size a thread can be created with (allowing
// the VM to completely create the thread and enter user code)
static size_t min_stack_allowed;
// Return default stack size or guard size for the specified thread type
static size_t default_stack_size(os::ThreadType thr_type);
static size_t default_guard_size(os::ThreadType thr_type);
// Function returns true if we run on OS/400 (pase), false if we run
// on AIX.
static bool on_pase() {
assert(_on_pase != -1, "not initialized");
return _on_pase ? true : false;
}
// Function returns true if we run on AIX, false if we run on OS/400
// (pase).
static bool on_aix() {
assert(_on_pase != -1, "not initialized");
return _on_pase ? false : true;
}
// -1 = uninitialized, otherwise 16 bit number:
// lower 8 bit - minor version
// higher 8 bit - major version
// For AIX, e.g. 0x0601 for AIX 6.1
// for OS/400 e.g. 0x0504 for OS/400 V5R4
static int os_version () {
assert(_os_version != -1, "not initialized");
return _os_version;
}
// Convenience method: returns true if running on AIX 5.3 or older.
static bool on_aix_53_or_older() {
return on_aix() && os_version() <= 0x0503;
}
// Returns true if we run in SPEC1170 compliant mode (XPG_SUS_ENV=ON).
static bool xpg_sus_mode() {
assert(_xpg_sus_mode != -1, "not initialized");
return _xpg_sus_mode;
}
// Returns true if EXTSHM=ON.
static bool extshm() {
assert(_extshm != -1, "not initialized");
return _extshm;
}
// result struct for get_meminfo()
struct meminfo_t {
// Amount of virtual memory (in units of 4 KB pages)
unsigned long long virt_total;
// Amount of real memory, in bytes
unsigned long long real_total;
// Amount of free real memory, in bytes
unsigned long long real_free;
// Total amount of paging space, in bytes
unsigned long long pgsp_total;
// Amount of free paging space, in bytes
unsigned long long pgsp_free;
};
// Result struct for get_cpuinfo().
struct cpuinfo_t {
char description[IDENTIFIER_LENGTH]; // processor description (type/official name)
u_longlong_t processorHZ; // processor speed in Hz
int ncpus; // number of active logical processors
double loadavg[3]; // (1<<SBITS) times the average number of runnables processes during the last 1, 5 and 15 minutes.
// To calculate the load average, divide the numbers by (1<<SBITS). SBITS is defined in <sys/proc.h>.
char version[20]; // processor version from _system_configuration (sys/systemcfg.h)
};
// Functions to retrieve memory information on AIX, PASE.
// (on AIX, using libperfstat, on PASE with libo4.so).
// Returns true if ok, false if error.
static bool get_meminfo(meminfo_t* pmi);
// Function to retrieve cpu information on AIX
// (on AIX, using libperfstat)
// Returns true if ok, false if error.
static bool get_cpuinfo(cpuinfo_t* pci);
}; // os::Aix class
class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4]; // increase odds that _mutex is sole occupant of cache line
volatile int _Event;
volatile int _nParked;
pthread_mutex_t _mutex [1];
pthread_cond_t _cond [1];
double PostPad [2];
Thread * _Assoc;
public: // TODO-FIXME: make dtor private
~PlatformEvent() { guarantee (0, "invariant"); }
public:
PlatformEvent() {
int status;
status = pthread_cond_init (_cond, NULL);
assert_status(status == 0, status, "cond_init");
status = pthread_mutex_init (_mutex, NULL);
assert_status(status == 0, status, "mutex_init");
_Event = 0;
_nParked = 0;
_Assoc = NULL;
}
// Use caution with reset() and fired() -- they may require MEMBARs
void reset() { _Event = 0; }
int fired() { return _Event; }
void park ();
void unpark ();
int TryPark ();
int park (jlong millis);
void SetAssociation (Thread * a) { _Assoc = a; }
};
class PlatformParker : public CHeapObj<mtInternal> {
protected:
pthread_mutex_t _mutex [1];
pthread_cond_t _cond [1];
public: // TODO-FIXME: make dtor private
~PlatformParker() { guarantee (0, "invariant"); }
public:
PlatformParker() {
int status;
status = pthread_cond_init (_cond, NULL);
assert_status(status == 0, status, "cond_init");
status = pthread_mutex_init (_mutex, NULL);
assert_status(status == 0, status, "mutex_init");
}
};
#endif // OS_AIX_VM_OS_AIX_HPP

View File

@ -0,0 +1,286 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_OS_AIX_INLINE_HPP
#define OS_AIX_VM_OS_AIX_INLINE_HPP
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#ifdef TARGET_OS_ARCH_aix_ppc
# include "atomic_aix_ppc.inline.hpp"
# include "orderAccess_aix_ppc.inline.hpp"
#endif
// System includes
#include <unistd.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <netdb.h>
// Defined in the system headers included above.
#undef rem_size
inline void* os::thread_local_storage_at(int index) {
return pthread_getspecific((pthread_key_t)index);
}
inline const char* os::file_separator() {
return "/";
}
inline const char* os::line_separator() {
return "\n";
}
inline const char* os::path_separator() {
return ":";
}
// File names are case-sensitive on windows only
inline int os::file_name_strcmp(const char* s1, const char* s2) {
return strcmp(s1, s2);
}
inline bool os::obsolete_option(const JavaVMOption *option) {
return false;
}
inline bool os::uses_stack_guard_pages() {
return true;
}
inline bool os::allocate_stack_guard_pages() {
assert(uses_stack_guard_pages(), "sanity check");
return true;
}
// On Aix, reservations are made on a page by page basis, nothing to do.
inline void os::pd_split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
}
// Bang the shadow pages if they need to be touched to be mapped.
inline void os::bang_stack_shadow_pages() {
}
inline void os::dll_unload(void *lib) {
::dlclose(lib);
}
inline const int os::default_file_open_flags() { return 0;}
inline DIR* os::opendir(const char* dirname)
{
assert(dirname != NULL, "just checking");
return ::opendir(dirname);
}
inline int os::readdir_buf_size(const char *path)
{
// according to aix sys/limits, NAME_MAX must be retrieved at runtime. */
const long my_NAME_MAX = pathconf(path, _PC_NAME_MAX);
return my_NAME_MAX + sizeof(dirent) + 1;
}
inline jlong os::lseek(int fd, jlong offset, int whence) {
return (jlong) ::lseek64(fd, offset, whence);
}
inline int os::fsync(int fd) {
return ::fsync(fd);
}
inline char* os::native_path(char *path) {
return path;
}
inline int os::ftruncate(int fd, jlong length) {
return ::ftruncate64(fd, length);
}
inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
{
dirent* p;
int status;
assert(dirp != NULL, "just checking");
// NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
// version. Here is the doc for this function:
// http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
errno = status;
return NULL;
} else
return p;
}
inline int os::closedir(DIR *dirp) {
assert(dirp != NULL, "argument is NULL");
return ::closedir(dirp);
}
// macros for restartable system calls
#define RESTARTABLE(_cmd, _result) do { \
_result = _cmd; \
} while(((int)_result == OS_ERR) && (errno == EINTR))
#define RESTARTABLE_RETURN_INT(_cmd) do { \
int _result; \
RESTARTABLE(_cmd, _result); \
return _result; \
} while(false)
// We don't have NUMA support on Aix, but we need this for compilation.
inline bool os::numa_has_static_binding() { ShouldNotReachHere(); return true; }
inline bool os::numa_has_group_homing() { ShouldNotReachHere(); return false; }
inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
size_t res;
RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res);
return res;
}
inline size_t os::write(int fd, const void *buf, unsigned int nBytes) {
size_t res;
RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
return res;
}
inline int os::close(int fd) {
return ::close(fd);
}
inline int os::socket_close(int fd) {
return ::close(fd);
}
inline int os::socket(int domain, int type, int protocol) {
return ::socket(domain, type, protocol);
}
inline int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, flags));
}
inline int os::send(int fd, char* buf, size_t nBytes, uint flags) {
RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags));
}
inline int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
return os::send(fd, buf, nBytes, flags);
}
inline int os::timeout(int fd, long timeout) {
julong prevtime,newtime;
struct timeval t;
gettimeofday(&t, NULL);
prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
for(;;) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN | POLLERR;
int res = ::poll(&pfd, 1, timeout);
if (res == OS_ERR && errno == EINTR) {
// On Linux any value < 0 means "forever"
if(timeout >= 0) {
gettimeofday(&t, NULL);
newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
timeout -= newtime - prevtime;
if(timeout <= 0)
return OS_OK;
prevtime = newtime;
}
} else
return res;
}
}
inline int os::listen(int fd, int count) {
return ::listen(fd, count);
}
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
// Linux doc says this can't return EINTR, unlike accept() on Solaris.
// But see attachListener_linux.cpp, LinuxAttachListener::dequeue().
return (int)::accept(fd, him, len);
}
inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
sockaddr* from, socklen_t* fromlen) {
RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
}
inline int os::sendto(int fd, char* buf, size_t len, uint flags,
struct sockaddr* to, socklen_t tolen) {
RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
}
inline int os::socket_shutdown(int fd, int howto) {
return ::shutdown(fd, howto);
}
inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
return ::bind(fd, him, len);
}
inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
return ::getsockname(fd, him, len);
}
inline int os::get_host_name(char* name, int namelen) {
return ::gethostname(name, namelen);
}
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
inline int os::get_sock_opt(int fd, int level, int optname,
char* optval, socklen_t* optlen) {
return ::getsockopt(fd, level, optname, optval, optlen);
}
inline int os::set_sock_opt(int fd, int level, int optname,
const char* optval, socklen_t optlen) {
return ::setsockopt(fd, level, optname, optval, optlen);
}
#endif // OS_AIX_VM_OS_AIX_INLINE_HPP

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 1999, 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.
*
* 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.
*
*/
#ifndef OS_AIX_VM_OS_SHARE_AIX_HPP
#define OS_AIX_VM_OS_SHARE_AIX_HPP
// misc
void signalHandler(int, siginfo_t*, ucontext_t*);
void handle_unexpected_exception(Thread* thread, int sig, siginfo_t* info, address pc, address adjusted_pc);
#ifndef PRODUCT
void continue_with_dump(void);
#endif
#define PROCFILE_LENGTH 128
#endif // OS_AIX_VM_OS_SHARE_AIX_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/*
* 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 "asm/assembler.hpp"
#include "loadlib_aix.hpp"
#include "porting_aix.hpp"
#include "utilities/debug.hpp"
#include <demangle.h>
#include <sys/debug.h>
//////////////////////////////////
// Provide implementation for dladdr based on LoadedLibraries pool and
// traceback table scan (see getFuncName).
// Search traceback table in stack,
// return procedure name from trace back table.
#define MAX_FUNC_SEARCH_LEN 0x10000
// Any PC below this value is considered toast.
#define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024)
#define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2))
// Align a pointer without having to cast.
inline char* align_ptr_up(char* ptr, intptr_t alignment) {
return (char*) align_size_up((intptr_t)ptr, alignment);
}
// Trace if verbose to tty.
// I use these now instead of the Xtrace system because the latter is
// not available at init time, hence worthless. Until we fix this, all
// tracing here is done with -XX:+Verbose.
#define trcVerbose(fmt, ...) { \
if (Verbose) { \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fputc('\n', stderr); fflush(stderr); \
} \
}
#define ERRBYE(s) { trcVerbose(s); return -1; }
// Unfortunately, the interface of dladdr makes the implementator
// responsible for maintaining memory for function name/library
// name. I guess this is because most OS's keep those values as part
// of the mapped executable image ready to use. On AIX, this doesn't
// work, so I have to keep the returned strings. For now, I do this in
// a primitive string map. Should this turn out to be a performance
// problem, a better hashmap has to be used.
class fixed_strings {
struct node {
char* v;
node* next;
};
node* first;
public:
fixed_strings() : first(0) {}
~fixed_strings() {
node* n = first;
while (n) {
node* p = n;
n = n->next;
free(p->v);
delete p;
}
}
char* intern(const char* s) {
for (node* n = first; n; n = n->next) {
if (strcmp(n->v, s) == 0) {
return n->v;
}
}
node* p = new node;
p->v = strdup(s);
p->next = first;
first = p;
return p->v;
}
};
static fixed_strings dladdr_fixed_strings;
// Given a code pointer, returns the function name and the displacement.
// Function looks for the traceback table at the end of the function.
extern "C" int getFuncName(
codeptr_t pc, // [in] program counter
char* p_name, size_t namelen, // [out] optional: function name ("" if not available)
int* p_displacement, // [out] optional: displacement (-1 if not available)
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further
// information (NULL if not available)
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
) {
struct tbtable* tb = 0;
unsigned int searchcount = 0;
// initialize output parameters
if (p_name && namelen > 0) {
*p_name = '\0';
}
if (p_errmsg && errmsglen > 0) {
*p_errmsg = '\0';
}
if (p_displacement) {
*p_displacement = -1;
}
if (p_tb) {
*p_tb = NULL;
}
// weed out obvious bogus states
if (pc < MINIMUM_VALUE_FOR_PC) {
ERRBYE("invalid program counter");
}
codeptr_t pc2 = pc;
// make sure the pointer is word aligned.
pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4);
// Find start of traceback table.
// (starts after code, is marked by word-aligned (32bit) zeros)
while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) {
pc2++;
}
if (*pc2 != 0) {
ERRBYE("could not find traceback table within 5000 bytes of program counter");
}
//
// Set up addressability to the traceback table
//
tb = (struct tbtable*) (pc2 + 1);
// Is this really a traceback table? No way to be sure but
// some indicators we can check.
if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) {
// Language specifiers, go from 0 (C) to 14 (Objective C).
// According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm.
ERRBYE("not a traceback table");
}
// Existence of fields in the tbtable extension are contingent upon
// specific fields in the base table. Check for their existence so
// that we can address the function name if it exists.
pc2 = (codeptr_t) tb +
sizeof(struct tbtable_short)/sizeof(int);
if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0)
pc2++;
if (tb->tb.has_tboff == TRUE) {
// I want to know the displacement
const unsigned int tb_offset = *pc2;
codeptr_t start_of_procedure =
(codeptr_t)(((char*)tb) - 4 - tb_offset); // (-4 to omit leading 0000)
// Weed out the cases where we did find the wrong traceback table.
if (pc < start_of_procedure) {
ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter");
}
// return the displacement
if (p_displacement) {
(*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure);
}
pc2++;
} else {
// return -1 for displacement
if (p_displacement) {
(*p_displacement) = -1;
}
}
if (tb->tb.int_hndl == TRUE)
pc2++;
if (tb->tb.has_ctl == TRUE)
pc2 += (*pc2) + 1; // don't care
//
// return function name if it exists.
//
if (p_name && namelen > 0) {
if (tb->tb.name_present) {
char buf[256];
const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1);
memcpy(buf, (char*)pc2 + sizeof(short), l);
buf[l] = '\0';
p_name[0] = '\0';
// If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
char* rest;
Name* const name = Demangle(buf, rest);
if (name) {
const char* const demangled_name = name->Text();
if (demangled_name) {
strncpy(p_name, demangled_name, namelen-1);
p_name[namelen-1] = '\0';
}
delete name;
}
// Fallback: if demangling did not work, just provide the unmangled name.
if (p_name[0] == '\0') {
strncpy(p_name, buf, namelen-1);
p_name[namelen-1] = '\0';
}
} else {
strncpy(p_name, "<nameless function>", namelen-1);
p_name[namelen-1] = '\0';
}
}
// Return traceback table, if user wants it.
if (p_tb) {
(*p_tb) = tb;
}
return 0;
}
// Special implementation of dladdr for Aix based on LoadedLibraries
// Note: dladdr returns non-zero for ok, 0 for error!
// Note: dladdr is not posix, but a non-standard GNU extension. So this tries to
// fulfill the contract of dladdr on Linux (see http://linux.die.net/man/3/dladdr)
// Note: addr may be both an AIX function descriptor or a real code pointer
// to the entry of a function.
extern "C"
int dladdr(void* addr, Dl_info* info) {
if (!addr) {
return 0;
}
assert(info, "");
int rc = 0;
const char* const ZEROSTRING = "";
// Always return a string, even if a "" one. Linux dladdr manpage
// does not say anything about returning NULL
info->dli_fname = ZEROSTRING;
info->dli_sname = ZEROSTRING;
info->dli_saddr = NULL;
address p = (address) addr;
const LoadedLibraryModule* lib = NULL;
enum { noclue, code, data } type = noclue;
trcVerbose("dladdr(%p)...", p);
// Note: input address may be a function. I accept both a pointer to
// the entry of a function and a pointer to the function decriptor.
// (see ppc64 ABI)
lib = LoadedLibraries::find_for_text_address(p);
if (lib) {
type = code;
}
if (!lib) {
// Not a pointer into any text segment. Is it a function descriptor?
const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p;
p = pfd->entry();
if (p) {
lib = LoadedLibraries::find_for_text_address(p);
if (lib) {
type = code;
}
}
}
if (!lib) {
// Neither direct code pointer nor function descriptor. A data ptr?
p = (address)addr;
lib = LoadedLibraries::find_for_data_address(p);
if (lib) {
type = data;
}
}
// If we did find the shared library this address belongs to (either
// code or data segment) resolve library path and, if possible, the
// symbol name.
if (lib) {
const char* const interned_libpath =
dladdr_fixed_strings.intern(lib->get_fullpath());
if (interned_libpath) {
info->dli_fname = interned_libpath;
}
if (type == code) {
// For code symbols resolve function name and displacement. Use
// displacement to calc start of function.
char funcname[256] = "";
int displacement = 0;
if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
NULL, NULL, 0) == 0) {
if (funcname[0] != '\0') {
const char* const interned = dladdr_fixed_strings.intern(funcname);
info->dli_sname = interned;
trcVerbose("... function name: %s ...", interned);
}
// From the displacement calculate the start of the function.
if (displacement != -1) {
info->dli_saddr = p - displacement;
} else {
info->dli_saddr = p;
}
} else {
// No traceback table found. Just assume the pointer is it.
info->dli_saddr = p;
}
} else if (type == data) {
// For data symbols.
info->dli_saddr = p;
} else {
ShouldNotReachHere();
}
rc = 1; // success: return 1 [sic]
}
// sanity checks.
if (rc) {
assert(info->dli_fname, "");
assert(info->dli_sname, "");
assert(info->dli_saddr, "");
}
return rc; // error: return 0 [sic]
}

View File

@ -0,0 +1,81 @@
/*
* 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 <stddef.h>
// Header file to contain porting-relevant code which does not have a
// home anywhere else and which can not go into os_<platform>.h because
// that header is included inside the os class definition, hence all
// its content is part of the os class.
// 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;
const char *dli_sname; // symbol name; "" if not known
void *dli_saddr; // address of *entry* of function; not function descriptor;
} Dl_info;
// Note: we export this to use it inside J2se too
#ifdef __cplusplus
extern "C"
#endif
int dladdr(void *addr, Dl_info *info);
// The semantics in this file are thus that codeptr_t is a *real code ptr*.
// This means that any function taking codeptr_t as arguments will assume
// a real codeptr and won't handle function descriptors (eg getFuncName),
// whereas functions taking address as args will deal with function
// descriptors (eg os::dll_address_to_library_name).
typedef unsigned int* codeptr_t;
// helper function - given a program counter, tries to locate the traceback table and
// returns info from it (like, most importantly, function name, displacement of the
// pc inside the function, and the traceback table itself.
#ifdef __cplusplus
extern "C"
#endif
int getFuncName(
codeptr_t pc, // [in] program counter
char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name
int* p_displacement, // [out] optional: displacement
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
);

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* 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 "precompiled.hpp"
#include "runtime/threadCritical.hpp"
#include "thread_aix.inline.hpp"
// put OS-includes here
# include <pthread.h>
//
// See threadCritical.hpp for details of this class.
//
static pthread_t tc_owner = 0;
static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER;
static int tc_count = 0;
void ThreadCritical::initialize() {
}
void ThreadCritical::release() {
}
ThreadCritical::ThreadCritical() {
pthread_t self = pthread_self();
if (self != tc_owner) {
int ret = pthread_mutex_lock(&tc_mutex);
guarantee(ret == 0, "fatal error with pthread_mutex_lock()");
assert(tc_count == 0, "Lock acquired with illegal reentry count.");
tc_owner = self;
}
tc_count++;
}
ThreadCritical::~ThreadCritical() {
assert(tc_owner == pthread_self(), "must have correct owner");
assert(tc_count > 0, "must have correct count");
tc_count--;
if (tc_count == 0) {
tc_owner = 0;
int ret = pthread_mutex_unlock(&tc_mutex);
guarantee(ret == 0, "fatal error with pthread_mutex_unlock()");
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_AIX_VM_THREAD_AIX_INLINE_HPP
#define OS_AIX_VM_THREAD_AIX_INLINE_HPP
#include "runtime/atomic.hpp"
#include "runtime/prefetch.hpp"
#include "runtime/thread.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "atomic_aix_ppc.inline.hpp"
#include "orderAccess_aix_ppc.inline.hpp"
#include "prefetch_aix_ppc.inline.hpp"
// Contains inlined functions for class Thread and ThreadLocalStorage
inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
#endif // OS_AIX_VM_THREAD_AIX_INLINE_HPP

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2003, 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.
*
* 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 "precompiled.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/vmError.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'dbx -a %d'; then switch to thread tid " INTX_FORMAT ", k-tid " INTX_FORMAT "\n"
"Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(),
os::current_thread_id(), thread_self());
yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "dbx -a %d", os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
} while (yes);
}
// Handle all synchronous signals which may happen during signal handling,
// not just SIGSEGV and SIGBUS.
static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
// Space for our "saved" signal flags and handlers
static int resettedSigflags[NUM_SIGNALS];
static address resettedSighandler[NUM_SIGNALS];
static void save_signal(int idx, int sig) {
struct sigaction sa;
sigaction(sig, NULL, &sa);
resettedSigflags[idx] = sa.sa_flags;
resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
: CAST_FROM_FN_PTR(address, sa.sa_handler);
}
int VMError::get_resetted_sigflags(int sig) {
// Handle all program errors.
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSigflags[i];
}
}
return -1;
}
address VMError::get_resetted_sighandler(int sig) {
// Handle all program errors.
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSighandler[i];
}
}
return NULL;
}
static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
// Unmask current signal.
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
Unimplemented();
}
void VMError::reset_signal_handlers() {
sigset_t newset;
sigemptyset(&newset);
for (int i = 0; i < NUM_SIGNALS; i++) {
save_signal(i, SIGNALS[i]);
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
}

View File

@ -0,0 +1,401 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
#define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
#include "orderAccess_aix_ppc.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "vm_version_ppc.hpp"
#ifndef _LP64
#error "Atomic currently only impleneted for PPC64"
#endif
// Implementation of class atomic
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
inline jlong Atomic::load(volatile jlong* src) { return *src; }
/*
machine barrier instructions:
- ppc_sync two-way memory barrier, aka fence
- ppc_lwsync orders Store|Store,
Load|Store,
Load|Load,
but not Store|Load
- ppc_eieio orders memory accesses for device memory (only)
- ppc_isync invalidates speculatively executed instructions
From the POWER ISA 2.06 documentation:
"[...] an isync instruction prevents the execution of
instructions following the isync until instructions
preceding the isync have completed, [...]"
From IBM's AIX assembler reference:
"The isync [...] instructions causes the processor to
refetch any instructions that might have been fetched
prior to the isync instruction. The instruction isync
causes the processor to wait for all previous instructions
to complete. Then any instructions already fetched are
discarded and instruction processing continues in the
environment established by the previous instructions."
semantic barrier instructions:
(as defined in orderAccess.hpp)
- ppc_release orders Store|Store, (maps to ppc_lwsync)
Load|Store
- ppc_acquire orders Load|Store, (maps to ppc_lwsync)
Load|Load
- ppc_fence orders Store|Store, (maps to ppc_sync)
Load|Store,
Load|Load,
Store|Load
*/
#define strasm_ppc_sync "\n sync \n"
#define strasm_ppc_lwsync "\n lwsync \n"
#define strasm_ppc_isync "\n isync \n"
#define strasm_ppc_release strasm_ppc_lwsync
#define strasm_ppc_acquire strasm_ppc_lwsync
#define strasm_ppc_fence strasm_ppc_sync
#define strasm_ppc_nobarrier ""
#define strasm_ppc_nobarrier_clobber_memory ""
inline jint Atomic::add (jint add_value, volatile jint* dest) {
unsigned int result;
__asm__ __volatile__ (
strasm_ppc_lwsync
"1: lwarx %0, 0, %2 \n"
" add %0, %0, %1 \n"
" stwcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_isync
: /*%0*/"=&r" (result)
: /*%1*/"r" (add_value), /*%2*/"r" (dest)
: "cc", "memory" );
return (jint) result;
}
inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
long result;
__asm__ __volatile__ (
strasm_ppc_lwsync
"1: ldarx %0, 0, %2 \n"
" add %0, %0, %1 \n"
" stdcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_isync
: /*%0*/"=&r" (result)
: /*%1*/"r" (add_value), /*%2*/"r" (dest)
: "cc", "memory" );
return (intptr_t) result;
}
inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
return (void*)add_ptr(add_value, (volatile intptr_t*)dest);
}
inline void Atomic::inc (volatile jint* dest) {
unsigned int temp;
__asm__ __volatile__ (
strasm_ppc_nobarrier
"1: lwarx %0, 0, %2 \n"
" addic %0, %0, 1 \n"
" stwcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_nobarrier
: /*%0*/"=&r" (temp), "=m" (*dest)
: /*%2*/"r" (dest), "m" (*dest)
: "cc" strasm_ppc_nobarrier_clobber_memory);
}
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
long temp;
__asm__ __volatile__ (
strasm_ppc_nobarrier
"1: ldarx %0, 0, %2 \n"
" addic %0, %0, 1 \n"
" stdcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_nobarrier
: /*%0*/"=&r" (temp), "=m" (*dest)
: /*%2*/"r" (dest), "m" (*dest)
: "cc" strasm_ppc_nobarrier_clobber_memory);
}
inline void Atomic::inc_ptr(volatile void* dest) {
inc_ptr((volatile intptr_t*)dest);
}
inline void Atomic::dec (volatile jint* dest) {
unsigned int temp;
__asm__ __volatile__ (
strasm_ppc_nobarrier
"1: lwarx %0, 0, %2 \n"
" addic %0, %0, -1 \n"
" stwcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_nobarrier
: /*%0*/"=&r" (temp), "=m" (*dest)
: /*%2*/"r" (dest), "m" (*dest)
: "cc" strasm_ppc_nobarrier_clobber_memory);
}
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
long temp;
__asm__ __volatile__ (
strasm_ppc_nobarrier
"1: ldarx %0, 0, %2 \n"
" addic %0, %0, -1 \n"
" stdcx. %0, 0, %2 \n"
" bne- 1b \n"
strasm_ppc_nobarrier
: /*%0*/"=&r" (temp), "=m" (*dest)
: /*%2*/"r" (dest), "m" (*dest)
: "cc" strasm_ppc_nobarrier_clobber_memory);
}
inline void Atomic::dec_ptr(volatile void* dest) {
dec_ptr((volatile intptr_t*)dest);
}
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
// Note that xchg_ptr doesn't necessarily do an acquire
// (see synchronizer.cpp).
unsigned int old_value;
const uint64_t zero = 0;
__asm__ __volatile__ (
/* lwsync */
strasm_ppc_lwsync
/* atomic loop */
"1: \n"
" lwarx %[old_value], %[dest], %[zero] \n"
" stwcx. %[exchange_value], %[dest], %[zero] \n"
" bne- 1b \n"
/* isync */
strasm_ppc_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
"=m" (*dest)
/* in */
: [dest] "b" (dest),
[zero] "r" (zero),
[exchange_value] "r" (exchange_value),
"m" (*dest)
/* clobber */
: "cc",
"memory"
);
return (jint) old_value;
}
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
// Note that xchg_ptr doesn't necessarily do an acquire
// (see synchronizer.cpp).
long old_value;
const uint64_t zero = 0;
__asm__ __volatile__ (
/* lwsync */
strasm_ppc_lwsync
/* atomic loop */
"1: \n"
" ldarx %[old_value], %[dest], %[zero] \n"
" stdcx. %[exchange_value], %[dest], %[zero] \n"
" bne- 1b \n"
/* isync */
strasm_ppc_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
"=m" (*dest)
/* in */
: [dest] "b" (dest),
[zero] "r" (zero),
[exchange_value] "r" (exchange_value),
"m" (*dest)
/* clobber */
: "cc",
"memory"
);
return (intptr_t) old_value;
}
inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
}
inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
// (see atomic.hpp).
unsigned int old_value;
const uint64_t zero = 0;
__asm__ __volatile__ (
/* fence */
strasm_ppc_sync
/* simple guard */
" lwz %[old_value], 0(%[dest]) \n"
" cmpw %[compare_value], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" lwarx %[old_value], %[dest], %[zero] \n"
" cmpw %[compare_value], %[old_value] \n"
" bne- 2f \n"
" stwcx. %[exchange_value], %[dest], %[zero] \n"
" bne- 1b \n"
/* acquire */
strasm_ppc_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
"=m" (*dest)
/* in */
: [dest] "b" (dest),
[zero] "r" (zero),
[compare_value] "r" (compare_value),
[exchange_value] "r" (exchange_value),
"m" (*dest)
/* clobber */
: "cc",
"memory"
);
return (jint) old_value;
}
inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
// (see atomic.hpp).
long old_value;
const uint64_t zero = 0;
__asm__ __volatile__ (
/* fence */
strasm_ppc_sync
/* simple guard */
" ld %[old_value], 0(%[dest]) \n"
" cmpd %[compare_value], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" ldarx %[old_value], %[dest], %[zero] \n"
" cmpd %[compare_value], %[old_value] \n"
" bne- 2f \n"
" stdcx. %[exchange_value], %[dest], %[zero] \n"
" bne- 1b \n"
/* acquire */
strasm_ppc_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
"=m" (*dest)
/* in */
: [dest] "b" (dest),
[zero] "r" (zero),
[compare_value] "r" (compare_value),
[exchange_value] "r" (exchange_value),
"m" (*dest)
/* clobber */
: "cc",
"memory"
);
return (jlong) old_value;
}
inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
#undef strasm_ppc_sync
#undef strasm_ppc_lwsync
#undef strasm_ppc_isync
#undef strasm_ppc_release
#undef strasm_ppc_acquire
#undef strasm_ppc_fence
#undef strasm_ppc_nobarrier
#undef strasm_ppc_nobarrier_clobber_memory
#endif // OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP
#define OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP
// Sets the default values for platform dependent flags used by the runtime system.
// (see globals.hpp)
define_pd_global(bool, DontYieldALot, false);
define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default
define_pd_global(intx, VMThreadStackSize, 2048);
// if we set CompilerThreadStackSize to a value different than 0, it will
// be used in os::create_thread(). Otherwise, due the strange logic in os::create_thread(),
// the stack size for compiler threads will default to VMThreadStackSize, although it
// is defined to 4M in os::Aix::default_stack_size()!
define_pd_global(intx, CompilerThreadStackSize, 4096);
// Allow extra space in DEBUG builds for asserts.
define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
define_pd_global(intx, StackYellowPages, 6);
define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+2));
// Only used on 64 bit platforms
define_pd_global(uintx,HeapBaseMinAddress, 2*G);
// Only used on 64 bit Windows platforms
define_pd_global(bool, UseVectoredExceptions, false);
#endif // OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP
#define OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP
#include "runtime/orderAccess.hpp"
#include "vm_version_ppc.hpp"
// Implementation of class OrderAccess.
//
// Machine barrier instructions:
//
// - ppc_sync Two-way memory barrier, aka fence.
// - ppc_lwsync orders Store|Store,
// Load|Store,
// Load|Load,
// but not Store|Load
// - ppc_eieio orders Store|Store
// - ppc_isync Invalidates speculatively executed instructions,
// but isync may complete before storage accesses
// associated with instructions preceding isync have
// been performed.
//
// Semantic barrier instructions:
// (as defined in orderAccess.hpp)
//
// - ppc_release orders Store|Store, (maps to ppc_lwsync)
// Load|Store
// - ppc_acquire orders Load|Store, (maps to ppc_lwsync)
// Load|Load
// - ppc_fence orders Store|Store, (maps to ppc_sync)
// Load|Store,
// Load|Load,
// Store|Load
//
#define inlasm_ppc_sync() __asm__ __volatile__ ("sync" : : : "memory");
#define inlasm_ppc_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory");
#define inlasm_ppc_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
#define inlasm_ppc_isync() __asm__ __volatile__ ("isync" : : : "memory");
#define inlasm_ppc_release() inlasm_ppc_lwsync();
#define inlasm_ppc_acquire() inlasm_ppc_lwsync();
// Use twi-isync for load_acquire (faster than lwsync).
// ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"):
// #define inlasm_ppc_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
#define inlasm_ppc_acquire_reg(X) inlasm_ppc_lwsync();
#define inlasm_ppc_fence() inlasm_ppc_sync();
inline void OrderAccess::loadload() { inlasm_ppc_lwsync(); }
inline void OrderAccess::storestore() { inlasm_ppc_lwsync(); }
inline void OrderAccess::loadstore() { inlasm_ppc_lwsync(); }
inline void OrderAccess::storeload() { inlasm_ppc_fence(); }
inline void OrderAccess::acquire() { inlasm_ppc_acquire(); }
inline void OrderAccess::release() { inlasm_ppc_release(); }
inline void OrderAccess::fence() { inlasm_ppc_fence(); }
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_ppc_acquire_reg(t); return t; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_ppc_acquire(); return t; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_ppc_acquire(); return t; }
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); }
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); }
inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; }
inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; }
inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; inlasm_ppc_fence(); }
#undef inlasm_ppc_sync
#undef inlasm_ppc_lwsync
#undef inlasm_ppc_eieio
#undef inlasm_ppc_isync
#undef inlasm_ppc_release
#undef inlasm_ppc_acquire
#undef inlasm_ppc_fence
#endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP

View File

@ -0,0 +1,560 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
// no precompiled headers
#include "assembler_ppc.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm_aix.h"
#include "memory/allocation.inline.hpp"
#include "mutex_aix.inline.hpp"
#include "nativeInst_ppc.hpp"
#include "os_share_aix.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/osThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/timer.hpp"
#include "thread_aix.inline.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
// put OS-includes here
# include <ucontext.h>
address os::current_stack_pointer() {
address csp;
#if !defined(USE_XLC_BUILTINS)
// inline assembly for `ppc_mr regno(csp), PPC_SP':
__asm__ __volatile__ ("mr %0, 1":"=r"(csp):);
#else
csp = (address) __builtin_frame_address(0);
#endif
return csp;
}
char* os::non_memory_address_word() {
// Must never look like an address returned by reserve_memory,
// even in its subfields (as defined by the CPU immediate fields,
// if the CPU splits constants across multiple instructions).
return (char*) -1;
}
// OS specific thread initialization
//
// Calculate and store the limits of the memory stack.
void os::initialize_thread(Thread *thread) { }
// Frame information (pc, sp, fp) retrieved via ucontext
// always looks like a C-frame according to the frame
// conventions in frame_ppc64.hpp.
address os::Aix::ucontext_get_pc(ucontext_t * uc) {
return (address)uc->uc_mcontext.jmp_context.iar;
}
intptr_t* os::Aix::ucontext_get_sp(ucontext_t * uc) {
// gpr1 holds the stack pointer on aix
return (intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/];
}
intptr_t* os::Aix::ucontext_get_fp(ucontext_t * uc) {
return NULL;
}
void os::Aix::ucontext_set_pc(ucontext_t* uc, address new_pc) {
uc->uc_mcontext.jmp_context.iar = (uint64_t) new_pc;
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Aix::ucontext_get_pc(uc));
if (ret_sp) *ret_sp = os::Aix::ucontext_get_sp(uc);
if (ret_fp) *ret_fp = os::Aix::ucontext_get_fp(uc);
} else {
// construct empty ExtendedPC for return value checking
epc = ExtendedPC(NULL);
if (ret_sp) *ret_sp = (intptr_t *)NULL;
if (ret_fp) *ret_fp = (intptr_t *)NULL;
}
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
// Avoid crash during crash if pc broken.
if (epc.pc()) {
frame fr(sp, epc.pc());
return fr;
}
frame fr(sp);
return fr;
}
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == NULL) {
// fr is the last C frame
return frame(NULL, NULL);
}
return frame(fr->sender_sp(), fr->sender_pc());
}
frame os::current_frame() {
intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer());
// hack.
frame topframe(csp, (address)0x8);
// return sender of current topframe which hopefully has pc != NULL.
return os::get_sender_for_C_frame(&topframe);
}
// Utility functions
extern "C" JNIEXPORT int
JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady
SignalHandlerMark shm(t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_aix_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE) {
if (os::Aix::chained_handler(sig, info, ucVoid)) {
return 1;
} else {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
warning("Ignoring SIGPIPE - see bug 4229104");
}
return 1;
}
}
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Aix::signal_handlers_are_installed) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = (JavaThread*)t;
}
else if(t->is_VM_thread()) {
vmthread = (VMThread *)t;
}
}
}
// Decide if this trap can be handled by a stub.
address stub = NULL;
// retrieve program counter
address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL;
// retrieve crash address
address const addr = info ? (const address) info->si_addr : NULL;
// SafeFetch 32 handling:
// - make it work if _thread is null
// - make it use the standard os::...::ucontext_get/set_pc APIs
if (uc) {
address const pc = os::Aix::ucontext_get_pc(uc);
if (pc && StubRoutines::is_safefetch_fault(pc)) {
os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
}
// Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
// space falls below 30%. This is only a chance for the process to gracefully abort.
// We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
if (sig == SIGDANGER) {
goto report_and_die;
}
if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
goto run_chained_handler;
}
// If we are a java thread...
if (thread != NULL) {
// Handle ALL stack overflow variations here
if (sig == SIGSEGV && (addr < thread->stack_base() &&
addr >= thread->stack_base() - thread->stack_size())) {
// stack overflow
//
// If we are in a yellow zone and we are inside java, we disable the yellow zone and
// throw a stack overflow exception.
// If we are in native code or VM C code, we report-and-die. The original coding tried
// to continue with yellow zone disabled, but that doesn't buy us much and prevents
// hs_err_pid files.
if (thread->in_stack_yellow_zone(addr)) {
thread->disable_stack_yellow_zone();
if (thread->thread_state() == _thread_in_Java) {
// Throw a stack overflow exception.
// Guard pages will be reenabled while unwinding the stack.
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
goto run_stub;
} else {
// Thread was in the vm or native code. Return and try to finish.
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {
// Fatal red zone violation. Disable the guard pages and fall through
// to handle_unexpected_exception way down below.
thread->disable_stack_red_zone();
tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
goto report_and_die;
} else {
// this means a segv happened inside our stack, but not in
// the guarded zone. I'd like to know when this happens,
tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone.");
goto report_and_die;
}
} // end handle SIGSEGV inside stack boundaries
if (thread->thread_state() == _thread_in_Java) {
// Java thread running in Java code
// The following signals are used for communicating VM events:
//
// SIGILL: the compiler generates illegal opcodes
// at places where it wishes to interrupt the VM:
// Safepoints, Unreachable Code, Entry points of Zombie methods,
// This results in a SIGILL with (*pc) == inserted illegal instruction.
//
// (so, SIGILLs with a pc inside the zero page are real errors)
//
// SIGTRAP:
// The ppc trap instruction raises a SIGTRAP and is very efficient if it
// does not trap. It is used for conditional branches that are expected
// to be never taken. These are:
// - zombie methods
// - IC (inline cache) misses.
// - null checks leading to UncommonTraps.
// - range checks leading to Uncommon Traps.
// On Aix, these are especially null checks, as the ImplicitNullCheck
// optimization works only in rare cases, as the page at address 0 is only
// write protected. //
// Note: !UseSIGTRAP is used to prevent SIGTRAPS altogether, to facilitate debugging.
//
// SIGSEGV:
// used for safe point polling:
// To notify all threads that they have to reach a safe point, safe point polling is used:
// All threads poll a certain mapped memory page. Normally, this page has read access.
// If the VM wants to inform the threads about impending safe points, it puts this
// page to read only ("poisens" the page), and the threads then reach a safe point.
// used for null checks:
// If the compiler finds a store it uses it for a null check. Unfortunately this
// happens rarely. In heap based and disjoint base compressd oop modes also loads
// are used for null checks.
// A VM-related SIGILL may only occur if we are not in the zero page.
// On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else
// in the zero page, because it is filled with 0x0. We ignore
// explicit SIGILLs in the zero page.
if (sig == SIGILL && (pc < (address) 0x200)) {
if (TraceTraps)
tty->print_raw_cr("SIGILL happened inside zero page.");
goto report_and_die;
}
// Handle signal from NativeJump::patch_verified_entry().
if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) ||
(!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) {
if (TraceTraps)
tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");
stub = SharedRuntime::get_handle_wrong_method_stub();
goto run_stub;
}
else if (sig == SIGSEGV && os::is_poll_address(addr)) {
if (TraceTraps)
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc);
stub = SharedRuntime::get_poll_stub(pc);
goto run_stub;
}
// SIGTRAP-based ic miss check in compiled code
else if (sig == SIGTRAP && TrapBasedICMissChecks &&
nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {
if (TraceTraps)
tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
stub = SharedRuntime::get_ic_miss_stub();
goto run_stub;
}
#ifdef COMPILER2
// SIGTRAP-based implicit null check in compiled code.
else if (sig == SIGTRAP && TrapBasedNullChecks &&
nativeInstruction_at(pc)->is_sigtrap_null_check()) {
if (TraceTraps)
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
goto run_stub;
}
#endif
// SIGSEGV-based implicit null check in compiled code.
else if (sig == SIGSEGV && ImplicitNullChecks &&
CodeCache::contains((void*) pc) &&
!MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
if (TraceTraps)
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc);
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
#ifdef COMPILER2
// SIGTRAP-based implicit range check in compiled code.
else if (sig == SIGTRAP && TrapBasedRangeChecks &&
nativeInstruction_at(pc)->is_sigtrap_range_check()) {
if (TraceTraps)
tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
goto run_stub;
}
#endif
else if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
if (TraceTraps) {
tty->print_raw_cr("Fix SIGFPE handler, trying divide by zero handler.");
}
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
goto run_stub;
}
else if (sig == SIGBUS) {
// BugId 4454115: A read from a MappedByteBuffer can fault here if the
// underlying file has been truncated. Do not crash the VM in such a case.
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
return 1;
}
}
}
else { // thread->thread_state() != _thread_in_Java
// Detect CPU features. This is only done at the very start of the VM. Later, the
// VM_Version::is_determine_features_test_running() flag should be false.
if (sig == SIGILL && VM_Version::is_determine_features_test_running()) {
// SIGILL must be caused by VM_Version::determine_features().
*(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL,
// flushing of icache is not necessary.
stub = pc + 4; // continue with next instruction.
goto run_stub;
}
else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
return 1;
}
}
// Check to see if we caught the safepoint code in the
// process of write protecting the memory serialization page.
// It write enables the page immediately after protecting it
// so we can just return to retry the write.
if ((sig == SIGSEGV) &&
os::is_memory_serialize_page(thread, addr)) {
// Synchronization problem in the pseudo memory barrier code (bug id 6546278)
// Block current thread until the memory serialize page permission restored.
os::block_on_serialize_page_trap();
return true;
}
}
run_stub:
// One of the above code blocks ininitalized the stub, so we want to
// delegate control to that stub.
if (stub != NULL) {
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
uc->uc_mcontext.jmp_context.iar = (unsigned long)stub;
return 1;
}
run_chained_handler:
// signal-chaining
if (os::Aix::chained_handler(sig, info, ucVoid)) {
return 1;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return 0;
}
report_and_die:
// Use sigthreadmask instead of sigprocmask on AIX and unmask current signal.
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
VMError err(t, sig, pc, info, ucVoid);
err.report_and_die();
ShouldNotReachHere();
return 0;
}
void os::Aix::init_thread_fpu_state(void) {
#if !defined(USE_XLC_BUILTINS)
// Disable FP exceptions.
__asm__ __volatile__ ("mtfsfi 6,0");
#else
__mtfsfi(6, 0);
#endif
}
////////////////////////////////////////////////////////////////////////////////
// thread stack
size_t os::Aix::min_stack_allowed = 768*K;
// Aix is always in floating stack mode. The stack size for a new
// thread can be set via pthread_attr_setstacksize().
bool os::Aix::supports_variable_stack_size() { return true; }
// return default stack size for thr_type
size_t os::Aix::default_stack_size(os::ThreadType thr_type) {
// default stack size (compiler thread needs larger stack)
// Notice that the setting for compiler threads here have no impact
// because of the strange 'fallback logic' in os::create_thread().
// Better set CompilerThreadStackSize in globals_<os_cpu>.hpp if you want to
// specify a different stack size for compiler threads!
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
return s;
}
size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
return 2 * page_size();
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
if (context == NULL) return;
ucontext_t* uc = (ucontext_t*)context;
st->print_cr("Registers:");
st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.iar);
st->print("lr =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.lr);
st->print("ctr=" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.ctr);
st->cr();
for (int i = 0; i < 32; i++) {
st->print("r%-2d=" INTPTR_FORMAT " ", i, uc->uc_mcontext.jmp_context.gpr[i]);
if (i % 3 == 2) st->cr();
}
st->cr();
st->cr();
intptr_t *sp = (intptr_t *)os::Aix::ucontext_get_sp(uc);
st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
print_hex_dump(st, (address)sp, (address)(sp + 128), sizeof(intptr_t));
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Aix::ucontext_get_pc(uc);
st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4);
st->cr();
// Try to decode the instructions.
st->print_cr("Decoded instructions: (pc=" PTR_FORMAT ")", pc);
st->print("<TODO: PPC port - print_context>");
// TODO: PPC port Disassembler::decode(pc, 16, 16, st);
st->cr();
}
void os::print_register_info(outputStream *st, void *context) {
if (context == NULL) return;
st->print("Not ported - print_register_info\n");
}
extern "C" {
int SpinPause() {
return 0;
}
}
#ifndef PRODUCT
void os::verify_stack_alignment() {
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
}
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP
#define OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP
static void setup_fpu() {}
// Used to register dynamic code cache area with the OS
// Note: Currently only used in 64 bit Windows implementations
static bool register_code_area(char *low, char *high) { return true; }
#endif // OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP
#define OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP
#include "runtime/prefetch.hpp"
inline void Prefetch::read(void *loc, intx interval) {
#if !defined(USE_XLC_BUILTINS)
__asm__ __volatile__ (
" dcbt 0, %0 \n"
:
: /*%0*/"r" ( ((address)loc) +((long)interval) )
//:
);
#else
__dcbt(((address)loc) +((long)interval));
#endif
}
inline void Prefetch::write(void *loc, intx interval) {
#if !defined(USE_XLC_PREFETCH_WRITE_BUILTIN)
__asm__ __volatile__ (
" dcbtst 0, %0 \n"
:
: /*%0*/"r" ( ((address)loc) +((long)interval) )
//:
);
#else
__dcbtst( ((address)loc) +((long)interval) );
#endif
}
#endif // OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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 "precompiled.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "thread_aix.inline.hpp"
void ThreadLocalStorage::generate_code_for_get_thread() {
// nothing we can do here for user-level thread
}
void ThreadLocalStorage::pd_init() {
// Nothing to do
}
void ThreadLocalStorage::pd_set_thread(Thread* thread) {
os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP
#define OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP
// Processor dependent parts of ThreadLocalStorage
public:
static Thread* thread() {
return (Thread *) os::thread_local_storage_at(thread_index());
}
#endif // OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* 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 "precompiled.hpp"
#include "runtime/frame.inline.hpp"
#include "thread_aix.inline.hpp"
// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
Unimplemented();
return false;
}
void JavaThread::cache_global_variables() { }

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP
#define OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP
private:
void pd_initialize() {
_anchor.clear();
_last_interpreter_fp = NULL;
}
// The `last' frame is the youngest Java frame on the thread's stack.
frame pd_last_frame() {
assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
intptr_t* sp = last_Java_sp();
address pc = _anchor.last_Java_pc();
// Last_Java_pc ist not set, if we come here from compiled code.
if (pc == NULL)
pc = (address) *(sp + 2);
return frame(sp, pc);
}
public:
void set_base_of_stack_pointer(intptr_t* base_sp) {}
intptr_t* base_of_stack_pointer() { return NULL; }
void record_base_of_stack_pointer() {}
// These routines are only used on cpu architectures that
// have separate register stacks (Itanium).
static bool register_stack_overflow() { return false; }
static void enable_register_stack_guard() {}
static void disable_register_stack_guard() {}
bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
bool isInJava);
// -Xprof support
//
// In order to find the last Java fp from an async profile
// tick, we store the current interpreter fp in the thread.
// This value is only valid while we are in the C++ interpreter
// and profiling.
protected:
intptr_t *_last_interpreter_fp;
public:
static ByteSize last_interpreter_fp_offset() {
return byte_offset_of(JavaThread, _last_interpreter_fp);
}
intptr_t* last_interpreter_fp() { return _last_interpreter_fp; }
#endif // OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP
#define OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP
// These are the OS and CPU-specific fields, types and integer
// constants required by the Serviceability Agent. This file is
// referenced by vmStructs.cpp.
#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
\
/******************************/ \
/* Threads (NOTE: incomplete) */ \
/******************************/ \
nonstatic_field(OSThread, _thread_id, pid_t) \
nonstatic_field(OSThread, _pthread_id, pthread_t)
#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
\
/**********************/ \
/* Posix Thread IDs */ \
/**********************/ \
\
declare_integer_type(pid_t) \
declare_unsigned_integer_type(pthread_t)
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
#endif // OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
*/
#ifndef SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP
#define SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP
#include "prims/jni.h"
// This file holds compiler-dependent includes,
// globally used constants & types, class (forward)
// declarations and a few frequently used utility functions.
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef FP_PZERO
// Linux doesn't have positive/negative zero
#define FP_PZERO FP_ZERO
#endif
#if (!defined fpclass)
#define fpclass fpclassify
#endif
#include <time.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>
#include <stdint.h>
// Use XLC compiler builtins instead of inline assembler
#define USE_XLC_BUILTINS
#ifdef USE_XLC_BUILTINS
#include <builtins.h>
#if __IBMCPP__ < 1000
// the funtion prototype for __dcbtst(void *) is missing in XLC V8.0
// I could compile a little test, where I provided the prototype.
// The generated code was correct there. This is the prototype:
// extern "builtin" void __dcbtst (void *);
// For now we don't make use of it when compiling with XLC V8.0
#else
// __IBMCPP__ >= 1000
// XLC V10 provides the prototype for __dcbtst (void *);
#define USE_XLC_PREFETCH_WRITE_BUILTIN
#endif
#endif // USE_XLC_BUILTINS
// NULL vs NULL_WORD:
// On Linux NULL is defined as a special type '__null'. Assigning __null to
// integer variable will cause gcc warning. Use NULL_WORD in places where a
// pointer is stored as integer value. On some platforms, sizeof(intptr_t) >
// sizeof(void*), so here we want something which is integer type, but has the
// same size as a pointer.
#ifdef __GNUC__
#error XLC and __GNUC__?
#else
#define NULL_WORD NULL
#endif
// AIX also needs a 64 bit NULL to work as a null address pointer.
// Most system includes on AIX would define it as an int 0 if not already defined with one
// exception: /usr/include/dirent.h will unconditionally redefine NULL to int 0 again.
// In this case you need to copy the following defines to a position after #include <dirent.h>
// (see jmv_aix.h).
#ifdef AIX
#ifdef _LP64
#undef NULL
#define NULL 0L
#else
#ifndef NULL
#define NULL 0
#endif
#endif
#endif // AIX
// Compiler-specific primitive types
// All defs of int (uint16_6 etc) are defined in AIX' /usr/include/stdint.h
// Additional Java basic types
typedef uint8_t jubyte;
typedef uint16_t jushort;
typedef uint32_t juint;
typedef uint64_t julong;
//----------------------------------------------------------------------------------------------------
// Special (possibly not-portable) casts
// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar
inline jint jint_cast (jfloat x) { return *(jint* )&x; }
inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; }
inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; }
inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; }
//----------------------------------------------------------------------------------------------------
// Constant for jlong (specifying an long long canstant is C++ compiler specific)
// Build a 64bit integer constant
#define CONST64(x) (x ## LL)
#define UCONST64(x) (x ## ULL)
const jlong min_jlong = CONST64(0x8000000000000000);
const jlong max_jlong = CONST64(0x7fffffffffffffff);
//----------------------------------------------------------------------------------------------------
// Debugging
#define DEBUG_EXCEPTION ::abort();
extern "C" void breakpoint();
#define BREAKPOINT ::breakpoint()
// checking for nanness
#ifdef AIX
inline int g_isnan(float f) { return isnan(f); }
inline int g_isnan(double f) { return isnan(f); }
#else
#error "missing platform-specific definition here"
#endif
// Checking for finiteness
inline int g_isfinite(jfloat f) { return finite(f); }
inline int g_isfinite(jdouble f) { return finite(f); }
// Wide characters
inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
// Portability macros
#define PRAGMA_INTERFACE #pragma interface
#define PRAGMA_IMPLEMENTATION #pragma implementation
#define VALUE_OBJ_CLASS_SPEC
// Formatting.
#ifdef _LP64
#define FORMAT64_MODIFIER "l"
#else // !_LP64
#define FORMAT64_MODIFIER "ll"
#endif // _LP64
// Cannot use xlc's offsetof as implementation of hotspot's
// offset_of(), because xlc warns about applying offsetof() to non-POD
// object and xlc cannot compile the expression offsetof(DataLayout,
// _cells[index]) in DataLayout::cell_offset() . Therefore we define
// offset_of as it is defined for gcc.
#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16)
// Some constant sizes used throughout the AIX port
#define SIZE_1K ((uint64_t) 0x400ULL)
#define SIZE_4K ((uint64_t) 0x1000ULL)
#define SIZE_64K ((uint64_t) 0x10000ULL)
#define SIZE_1M ((uint64_t) 0x100000ULL)
#define SIZE_4M ((uint64_t) 0x400000ULL)
#define SIZE_8M ((uint64_t) 0x800000ULL)
#define SIZE_16M ((uint64_t) 0x1000000ULL)
#define SIZE_256M ((uint64_t) 0x10000000ULL)
#define SIZE_1G ((uint64_t) 0x40000000ULL)
#define SIZE_2G ((uint64_t) 0x80000000ULL)
#define SIZE_4G ((uint64_t) 0x100000000ULL)
#define SIZE_16G ((uint64_t) 0x400000000ULL)
#define SIZE_32G ((uint64_t) 0x800000000ULL)
#define SIZE_64G ((uint64_t) 0x1000000000ULL)
#define SIZE_1T ((uint64_t) 0x10000000000ULL)
#endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP