8023038: PPC64 (part 15): Platform files for AIX/PPC64 support
Reviewed-by: kvn
This commit is contained in:
parent
56654216c4
commit
2af861eed1
574
hotspot/src/os/aix/vm/attachListener_aix.cpp
Normal file
574
hotspot/src/os/aix/vm/attachListener_aix.cpp
Normal 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();
|
||||
}
|
37
hotspot/src/os/aix/vm/c2_globals_aix.hpp
Normal file
37
hotspot/src/os/aix/vm/c2_globals_aix.hpp
Normal 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
|
48
hotspot/src/os/aix/vm/decoder_aix.hpp
Normal file
48
hotspot/src/os/aix/vm/decoder_aix.hpp
Normal 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;
|
||||
}
|
||||
};
|
63
hotspot/src/os/aix/vm/globals_aix.hpp
Normal file
63
hotspot/src/os/aix/vm/globals_aix.hpp
Normal 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
|
35
hotspot/src/os/aix/vm/interfaceSupport_aix.hpp
Normal file
35
hotspot/src/os/aix/vm/interfaceSupport_aix.hpp
Normal 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
|
233
hotspot/src/os/aix/vm/jsig.c
Normal file
233
hotspot/src/os/aix/vm/jsig.c
Normal 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;
|
||||
}
|
201
hotspot/src/os/aix/vm/jvm_aix.cpp
Normal file
201
hotspot/src/os/aix/vm/jvm_aix.cpp
Normal 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;
|
||||
}
|
123
hotspot/src/os/aix/vm/jvm_aix.h
Normal file
123
hotspot/src/os/aix/vm/jvm_aix.h
Normal 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
|
124
hotspot/src/os/aix/vm/libperfstat_aix.cpp
Normal file
124
hotspot/src/os/aix/vm/libperfstat_aix.cpp
Normal 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();
|
||||
}
|
59
hotspot/src/os/aix/vm/libperfstat_aix.hpp
Normal file
59
hotspot/src/os/aix/vm/libperfstat_aix.hpp
Normal 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
|
185
hotspot/src/os/aix/vm/loadlib_aix.cpp
Normal file
185
hotspot/src/os/aix/vm/loadlib_aix.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
128
hotspot/src/os/aix/vm/loadlib_aix.hpp
Normal file
128
hotspot/src/os/aix/vm/loadlib_aix.hpp
Normal 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
|
33
hotspot/src/os/aix/vm/mutex_aix.inline.hpp
Normal file
33
hotspot/src/os/aix/vm/mutex_aix.inline.hpp
Normal 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
|
58
hotspot/src/os/aix/vm/osThread_aix.cpp
Normal file
58
hotspot/src/os/aix/vm/osThread_aix.cpp
Normal 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;
|
||||
}
|
144
hotspot/src/os/aix/vm/osThread_aix.hpp
Normal file
144
hotspot/src/os/aix/vm/osThread_aix.hpp
Normal 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
|
5126
hotspot/src/os/aix/vm/os_aix.cpp
Normal file
5126
hotspot/src/os/aix/vm/os_aix.cpp
Normal file
File diff suppressed because it is too large
Load Diff
385
hotspot/src/os/aix/vm/os_aix.hpp
Normal file
385
hotspot/src/os/aix/vm/os_aix.hpp
Normal 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
|
286
hotspot/src/os/aix/vm/os_aix.inline.hpp
Normal file
286
hotspot/src/os/aix/vm/os_aix.inline.hpp
Normal 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
|
37
hotspot/src/os/aix/vm/os_share_aix.hpp
Normal file
37
hotspot/src/os/aix/vm/os_share_aix.hpp
Normal 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
|
1026
hotspot/src/os/aix/vm/perfMemory_aix.cpp
Normal file
1026
hotspot/src/os/aix/vm/perfMemory_aix.cpp
Normal file
File diff suppressed because it is too large
Load Diff
367
hotspot/src/os/aix/vm/porting_aix.cpp
Normal file
367
hotspot/src/os/aix/vm/porting_aix.cpp
Normal 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]
|
||||
|
||||
}
|
81
hotspot/src/os/aix/vm/porting_aix.hpp
Normal file
81
hotspot/src/os/aix/vm/porting_aix.hpp
Normal 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
|
||||
);
|
68
hotspot/src/os/aix/vm/threadCritical_aix.cpp
Normal file
68
hotspot/src/os/aix/vm/threadCritical_aix.cpp
Normal 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()");
|
||||
}
|
||||
}
|
42
hotspot/src/os/aix/vm/thread_aix.inline.hpp
Normal file
42
hotspot/src/os/aix/vm/thread_aix.inline.hpp
Normal 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
|
122
hotspot/src/os/aix/vm/vmError_aix.cpp
Normal file
122
hotspot/src/os/aix/vm/vmError_aix.cpp
Normal 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);
|
||||
}
|
401
hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
Normal file
401
hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
Normal 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
|
54
hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp
Normal file
54
hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp
Normal 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
|
147
hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp
Normal file
147
hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp
Normal 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
|
560
hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
Normal file
560
hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
Normal 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
|
35
hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp
Normal file
35
hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp
Normal 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
|
58
hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp
Normal file
58
hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp
Normal 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
|
40
hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp
Normal file
40
hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp
Normal 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);
|
||||
}
|
36
hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp
Normal file
36
hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp
Normal 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
|
36
hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp
Normal file
36
hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp
Normal 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() { }
|
79
hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp
Normal file
79
hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp
Normal 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
|
55
hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp
Normal file
55
hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp
Normal 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
|
202
hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp
Normal file
202
hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp
Normal 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
|
Loading…
x
Reference in New Issue
Block a user