提交 fea084e8 编写于 作者: S simonis

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

Reviewed-by: kvn
上级 6183eade
/*
* 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();
}
/*
* 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
/*
* 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;
}
};
/*
* 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
/*
* 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
/*
* 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;
}
/*
* 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;
}
/*
* 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
/*
* 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();
}
/*
* 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
/*
* 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);
}
}
/*
* 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
/*
* 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
/*
* 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;
}
/*
* 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
此差异已折叠。
/*
* 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
/*
* 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
/*
* 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
此差异已折叠。
/*
* 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]
}
/*
* 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
);
/*
* 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()");
}
}
/*
* 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
/*
* 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);
}
/*
* 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
/*
* 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
此差异已折叠。
此差异已折叠。
/*
* 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
此差异已折叠。
/*
* 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);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册