view ppc_patches/0015_aix_ppc_files.patch @ 4881:edf2bb42e70f

Recent changes to patch queue
author goetz
date Fri, 28 Jun 2013 16:31:09 +0200
parents 8d5597e3e9bb
children 874e94d3b21d
line wrap: on
line source
# HG changeset patch
# Parent 4acea56cea4c90d9df275761feed0626ecd2ea7f
aix: AIX platform files as required to start up the interpreter.

With this change the AIX vm should compile as jvmgcore and run
purely interpreted.

diff -r 4acea56cea4c src/os/aix/vm/attachListener_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/attachListener_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2005, 2010, 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;
+}
+
+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();
+}
diff -r 4acea56cea4c src/os/aix/vm/c2_globals_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/c2_globals_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2000, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/decoder_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/decoder_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, 2012, 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;
+  }
+};
diff -r 4acea56cea4c src/os/aix/vm/globals_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/globals_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005, 2011, 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
diff -r 4acea56cea4c src/os/aix/vm/interfaceSupport_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/interfaceSupport_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/jsig.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/jsig.c	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2001, 2010, 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;
+}
diff -r 4acea56cea4c src/os/aix/vm/jvm_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/jvm_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1999, 2011, 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;
+}
diff -r 4acea56cea4c src/os/aix/vm/jvm_aix.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/jvm_aix.h	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/libperfstat_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/libperfstat_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "runtime/arguments.hpp"
+#include "libperfstat_aix.hpp"
+
+// For dlopen and friends
+#include <fcntl.h>
+
+// handle to the libperfstat
+static void* g_libhandle = NULL;
+
+// whether initialization worked
+static bool g_initialized = false;
+
+
+typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
+                                         int sizeof_userbuff, int desired_number);
+
+typedef int (*fun_perfstat_memory_total_t) (perfstat_id_t *name, perfstat_memory_total_t* userbuff,
+                                            int sizeof_userbuff, int desired_number);
+
+typedef void (*fun_perfstat_reset_t) ();
+
+static fun_perfstat_cpu_total_t     g_fun_perfstat_cpu_total = NULL;
+static fun_perfstat_memory_total_t  g_fun_perfstat_memory_total = NULL;
+static fun_perfstat_reset_t         g_fun_perfstat_reset = NULL;
+
+bool libperfstat::init() {
+
+  if (g_initialized) {
+    return true;
+  }
+
+  g_initialized = false;
+
+  // dynamically load the libperfstat porting library.
+  g_libhandle = dlopen("/usr/lib/libperfstat.a(shr_64.o)", RTLD_MEMBER | RTLD_NOW);
+  if (!g_libhandle) {
+    if (Verbose) {
+      fprintf(stderr, "Cannot load libperfstat.a (dlerror: %s)", dlerror());
+    }
+    return false;
+  }
+
+  // resolve function pointers
+
+#define RESOLVE_FUN_NO_ERROR(name) \
+  g_fun_##name = (fun_##name##_t) dlsym(g_libhandle, #name);
+
+#define RESOLVE_FUN(name) \
+  RESOLVE_FUN_NO_ERROR(name) \
+  if (!g_fun_##name) { \
+    if (Verbose) { \
+      fprintf(stderr, "Cannot resolve " #name "() from libperfstat.a\n" \
+                      "   (dlerror: %s)", dlerror()); \
+      } \
+    return false; \
+  }
+
+  RESOLVE_FUN(perfstat_cpu_total);
+  RESOLVE_FUN(perfstat_memory_total);
+  RESOLVE_FUN(perfstat_reset);
+
+  g_initialized = true;
+
+  return true;
+}
+
+void libperfstat::cleanup() {
+
+  g_initialized = false;
+
+  if (g_libhandle) {
+    dlclose(g_libhandle);
+    g_libhandle = NULL;
+  }
+
+  g_fun_perfstat_cpu_total = NULL;
+  g_fun_perfstat_memory_total = NULL;
+  g_fun_perfstat_reset = NULL;
+}
+
+int libperfstat::perfstat_memory_total(perfstat_id_t *name,
+                                       perfstat_memory_total_t* userbuff,
+                                       int sizeof_userbuff, int desired_number) {
+  assert(g_initialized, "libperfstat not initialized");
+  assert(g_fun_perfstat_memory_total, "");
+  return g_fun_perfstat_memory_total(name, userbuff, sizeof_userbuff, desired_number);
+}
+
+int libperfstat::perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
+                                    int sizeof_userbuff, int desired_number) {
+  assert(g_initialized, "libperfstat not initialized");
+  assert(g_fun_perfstat_cpu_total, "");
+  return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number);
+}
+
+void libperfstat::perfstat_reset() {
+  assert(g_initialized, "libperfstat not initialized");
+  assert(g_fun_perfstat_reset, "");
+  g_fun_perfstat_reset();
+}
diff -r 4acea56cea4c src/os/aix/vm/libperfstat_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/libperfstat_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// encapsulates the libperfstat library.
+//
+// The purpose of this code is to dynamically load the libperfstat library
+// instead of statically linking against it. The libperfstat library is an
+// AIX-specific library which only exists on AIX, not on PASE. If I want to
+// share binaries between AIX and PASE, I cannot directly link against libperfstat.so.
+
+#ifndef OS_AIX_VM_LIBPERFSTAT_AIX_HPP
+#define OS_AIX_VM_LIBPERFSTAT_AIX_HPP
+
+#include <libperfstat.h>
+
+class libperfstat {
+
+public:
+
+  // Load the libperfstat library (must be in LIBPATH).
+  // Returns true if succeeded, false if error.
+  static bool init();
+
+  // cleanup of the libo4 porting library.
+  static void cleanup();
+
+  // direct wrappers for the libperfstat functionality. All they do is
+  // to call the functions with the same name via function pointers.
+  static int perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff,
+                                int sizeof_userbuff, int desired_number);
+
+  static int perfstat_memory_total(perfstat_id_t *name, perfstat_memory_total_t* userbuff,
+                                   int sizeof_userbuff, int desired_number);
+
+  static void perfstat_reset();
+};
+
+#endif // OS_AIX_VM_LIBPERFSTAT_AIX_HPP
diff -r 4acea56cea4c src/os/aix/vm/loadlib_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/loadlib_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+
+// Implementation of LoadedLibraries and friends
+
+// Ultimately this just uses loadquery()
+// See:
+// http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp
+//      ?topic=/com.ibm.aix.basetechref/doc/basetrf1/loadquery.htm
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+// 'allocation.inline.hpp' triggers the inclusion of 'inttypes.h' which defines macros
+// required by the definitions in 'globalDefinitions.hpp'. But these macros in 'inttypes.h'
+// are only defined if '__STDC_FORMAT_MACROS' is defined!
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/threadCritical.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/ostream.hpp"
+#include "loadlib_aix.hpp"
+#include "porting_aix.hpp"
+
+// For loadquery()
+#include <sys/ldr.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation for LoadedLibraryModule
+
+// output debug info
+void LoadedLibraryModule::print(outputStream* os) const {
+  os->print("%15.15s: text: " INTPTR_FORMAT " - " INTPTR_FORMAT
+               ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " ",
+      shortname, text_from, text_to, data_from, data_to);
+  os->print(" %s", fullpath);
+  if (strlen(membername) > 0) {
+    os->print("(%s)", membername);
+  }
+  os->cr();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation for LoadedLibraries
+
+// class variables
+LoadedLibraryModule LoadedLibraries::tab[MAX_MODULES];
+int LoadedLibraries::num_loaded = 0;
+
+// Checks whether the address p points to any of the loaded code segments.
+// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
+// static
+const LoadedLibraryModule* LoadedLibraries::find_for_text_address(const unsigned char* p) {
+
+  if (num_loaded == 0) {
+    reload();
+  }
+  for (int i = 0; i < num_loaded; i++) {
+    if (tab[i].is_in_text(p)) {
+      return &tab[i];
+    }
+  }
+  return NULL;
+}
+
+// Checks whether the address p points to any of the loaded data segments.
+// If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
+// static
+const LoadedLibraryModule* LoadedLibraries::find_for_data_address(const unsigned char* p) {
+  if (num_loaded == 0) {
+    reload();
+  }
+  for (int i = 0; i < num_loaded; i++) {
+    if (tab[i].is_in_data(p)) {
+      return &tab[i];
+    }
+  }
+  return NULL;
+}
+
+// Rebuild the internal table of LoadedLibraryModule objects
+// static
+void LoadedLibraries::reload() {
+
+  ThreadCritical cs;
+
+  // discard old content
+  num_loaded = 0;
+
+  // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX.
+  size_t buf_size = 4096;
+  char* loadquery_buf = AllocateHeap(buf_size, mtInternal);
+
+  while(loadquery(L_GETINFO, loadquery_buf, buf_size) == -1) {
+    if (errno == ENOMEM) {
+      buf_size *= 2;
+      loadquery_buf = ReallocateHeap(loadquery_buf, buf_size, mtInternal);
+    } else {
+      FreeHeap(loadquery_buf);
+      // Ensure that the uintptr_t pointer is valid
+      assert(errno != EFAULT, "loadquery: Invalid uintptr_t in info buffer.");
+      fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
+      return;
+    }
+  }
+
+  // Iterate over the loadquery result. For details see sys/ldr.h on AIX.
+  const struct ld_info* p = (struct ld_info*) loadquery_buf;
+
+  // Ensure we have all loaded libs.
+  bool all_loaded = false;
+  while(num_loaded < MAX_MODULES) {
+    LoadedLibraryModule& mod = tab[num_loaded];
+    mod.text_from = (const unsigned char*) p->ldinfo_textorg;
+    mod.text_to   = (const unsigned char*) (((char*)p->ldinfo_textorg) + p->ldinfo_textsize);
+    mod.data_from = (const unsigned char*) p->ldinfo_dataorg;
+    mod.data_to   = (const unsigned char*) (((char*)p->ldinfo_dataorg) + p->ldinfo_datasize);
+    sprintf(mod.fullpath, "%.*s", sizeof(mod.fullpath), p->ldinfo_filename);
+    // do we have a member name as well (see ldr.h)?
+    const char* p_mbr_name = p->ldinfo_filename + strlen(p->ldinfo_filename) + 1;
+    if (*p_mbr_name) {
+      sprintf(mod.membername, "%.*s", sizeof(mod.membername), p_mbr_name);
+    } else {
+      mod.membername[0] = '\0';
+    }
+
+    // fill in the short name
+    const char* p_slash = strrchr(mod.fullpath, '/');
+    if (p_slash) {
+      sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), p_slash + 1);
+    } else {
+      sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), mod.fullpath);
+    }
+    num_loaded ++;
+
+    // next entry...
+    if (p->ldinfo_next) {
+      p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
+    } else {
+      all_loaded = true;
+      break;
+    }
+  }
+
+  FreeHeap(loadquery_buf);
+
+  // Ensure we have all loaded libs
+  assert(all_loaded, "loadquery returned more entries then expected. Please increase MAX_MODULES");
+
+} // end LoadedLibraries::reload()
+
+
+// output loaded libraries table
+//static
+void LoadedLibraries::print(outputStream* os) {
+
+  for (int i = 0; i < num_loaded; i++) {
+    tab[i].print(os);
+  }
+
+}
+
diff -r 4acea56cea4c src/os/aix/vm/loadlib_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/loadlib_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+
+// Loadlib_aix.cpp contains support code for analysing the memory
+// layout of loaded binaries in ones own process space.
+//
+// It is needed, among other things, to provide a  dladdr() emulation, because
+// that one is not provided by AIX
+
+#ifndef OS_AIX_VM_LOADLIB_AIX_HPP
+#define OS_AIX_VM_LOADLIB_AIX_HPP
+
+class outputStream;
+
+// This class holds information about a single loaded library module.
+// Note that on AIX, a single library can be spread over multiple
+// uintptr_t range on a module base, eg.
+// libC.a(shr3_64.o) or libC.a(shrcore_64.o).
+class LoadedLibraryModule {
+
+    friend class LoadedLibraries;
+
+    char fullpath[512];  // eg /usr/lib/libC.a
+    char shortname[30];  // eg libC.a
+    char membername[30]; // eg shrcore_64.o
+    const unsigned char* text_from;
+    const unsigned char* text_to;
+    const unsigned char* data_from;
+    const unsigned char* data_to;
+
+  public:
+
+    const char* get_fullpath() const {
+      return fullpath;
+    }
+    const char* get_shortname() const {
+      return shortname;
+    }
+    const char* get_membername() const {
+      return membername;
+    }
+
+    // text_from, text_to: returns the range of the text (code)
+    // segment for that module
+    const unsigned char* get_text_from() const {
+      return text_from;
+    }
+    const unsigned char* get_text_to() const {
+      return text_to;
+    }
+
+    // data_from/data_to: returns the range of the data
+    // segment for that module
+    const unsigned char* get_data_from() const {
+      return data_from;
+    }
+    const unsigned char* get_data_to() const {
+      return data_to;
+    }
+
+    // returns true if the
+    bool is_in_text(const unsigned char* p) const {
+      return p >= text_from && p < text_to ? true : false;
+    }
+
+    bool is_in_data(const unsigned char* p) const {
+      return p >= data_from && p < data_to ? true : false;
+    }
+
+    // output debug info
+    void print(outputStream* os) const;
+
+}; // end LoadedLibraryModule
+
+// This class is a singleton holding a map of all loaded binaries
+// in the AIX process space.
+class LoadedLibraries
+// : AllStatic (including allocation.hpp just for AllStatic is overkill.)
+{
+
+  private:
+
+    enum {MAX_MODULES = 100};
+    static LoadedLibraryModule tab[MAX_MODULES];
+    static int num_loaded;
+
+  public:
+
+    // rebuild the internal table of LoadedLibraryModule objects
+    static void reload();
+
+    // checks whether the address p points to any of the loaded code segments.
+    // If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
+    static const LoadedLibraryModule* find_for_text_address(const  unsigned char* p);
+
+    // checks whether the address p points to any of the loaded data segments.
+    // If it does, returns the LoadedLibraryModule entry. If not, returns NULL.
+    static const LoadedLibraryModule* find_for_data_address(const  unsigned char* p);
+
+    // output debug info
+    static void print(outputStream* os);
+
+}; // end LoadedLibraries
+
+
+#endif // OS_AIX_VM_LOADLIB_AIX_HPP
diff -r 4acea56cea4c src/os/aix/vm/mutex_aix.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/mutex_aix.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1999, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/osThread_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/osThread_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1999, 2011, 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;
+}
diff -r 4acea56cea4c src/os/aix/vm/osThread_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/osThread_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1999, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/os_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/os_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,5098 @@
+/*
+ * Copyright (c) 1999, 2012, 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.
+ *
+ */
+
+// According to the AIX OS doc #pragma alloca must be used
+// with C++ compiler before referencing the function alloca()
+#pragma alloca
+
+// no precompiled headers
+#include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/icBuffer.hpp"
+#include "code/vtableStubs.hpp"
+#include "compiler/compileBroker.hpp"
+#include "interpreter/interpreter.hpp"
+#include "jvm_aix.h"
+#include "libperfstat_aix.hpp"
+#include "loadlib_aix.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/filemap.hpp"
+#include "mutex_aix.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "os_share_aix.hpp"
+#include "porting_aix.hpp"
+#include "prims/jniFastGetField.hpp"
+#include "prims/jvm.h"
+#include "prims/jvm_misc.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/extendedPC.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/java.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/objectMonitor.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/perfMemory.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/statSampler.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/threadCritical.hpp"
+#include "runtime/timer.hpp"
+#include "services/attachListener.hpp"
+#include "services/runtimeService.hpp"
+#include "thread_aix.inline.hpp"
+#include "utilities/decoder.hpp"
+#include "utilities/defaultStream.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/vmError.hpp"
+#ifdef TARGET_ARCH_ppc
+# include "assembler_ppc.inline.hpp"
+# include "nativeInst_ppc.hpp"
+#endif
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif
+#ifdef COMPILER2
+#include "opto/runtime.hpp"
+#endif
+
+// put OS-includes here (sorted alphabetically)
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <procinfo.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysinfo.h>
+#include <sys/systemcfg.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/vminfo.h>
+#include <sys/wait.h>
+
+// Add missing declarations (should be in procinfo.h but isn't until AIX 6.1).
+#if !defined(_AIXVERSION_610)
+extern "C" {
+  int getthrds64(pid_t ProcessIdentifier,
+                 struct thrdentry64* ThreadBuffer,
+                 int ThreadSize,
+                 tid64_t* IndexPointer,
+                 int Count);
+}
+#endif
+
+// Excerpts from systemcfg.h definitions newer than AIX 5.3
+#ifndef PV_7
+# define PV_7 0x200000          // Power PC 7
+# define PV_7_Compat 0x208000   // Power PC 7
+#endif
+
+#define MAX_PATH (2 * K)
+
+// for timer info max values which include all bits
+#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
+// for multipage initialization error analysis (in 'g_multipage_error')
+#define ERROR_MP_OS_TOO_OLD                          100
+#define ERROR_MP_EXTSHM_ACTIVE                       101
+#define ERROR_MP_VMGETINFO_FAILED                    102
+#define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103
+
+// 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;
+
+// typedefs for stackslots, stack pointers, pointers to op codes
+typedef unsigned long stackslot_t;
+typedef stackslot_t* stackptr_t;
+
+// query dimensions of the stack of the calling thread
+static void query_stack_dimensions(address* p_stack_base, size_t* p_stack_size);
+
+// function to check a given stack pointer against given stack limits
+inline bool is_valid_stackpointer(stackptr_t sp, stackptr_t stack_base, size_t stack_size) {
+  if (((uintptr_t)sp) & 0x7) {
+    return false;
+  }
+  if (sp > stack_base) {
+    return false;
+  }
+  if (sp < (stackptr_t) ((address)stack_base - stack_size)) {
+    return false;
+  }
+  return true;
+}
+
+// returns true if function is a valid codepointer
+inline bool is_valid_codepointer(codeptr_t p) {
+  if (!p) {
+    return false;
+  }
+  if (((uintptr_t)p) & 0x3) {
+    return false;
+  }
+  if (LoadedLibraries::find_for_text_address((address)p) == NULL) {
+    return false;
+  }
+  return true;
+}
+
+// macro to check a given stack pointer against given stack limits and to die if test fails
+#define CHECK_STACK_PTR(sp, stack_base, stack_size) { \
+    guarantee(is_valid_stackpointer((stackptr_t)(sp), (stackptr_t)(stack_base), stack_size), "Stack Pointer Invalid"); \
+}
+
+// macro to check the current stack pointer against given stacklimits
+#define CHECK_CURRENT_STACK_PTR(stack_base, stack_size) { \
+  address sp; \
+  sp = os::current_stack_pointer(); \
+  CHECK_STACK_PTR(sp, stack_base, stack_size); \
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// global variables (for a description see os_aix.hpp)
+
+julong    os::Aix::_physical_memory = 0;
+pthread_t os::Aix::_main_thread = ((pthread_t)0);
+int       os::Aix::_page_size = -1;
+int       os::Aix::_on_pase = -1;
+int       os::Aix::_os_version = -1;
+int       os::Aix::_stack_page_size = -1;
+size_t    os::Aix::_shm_default_page_size = -1;
+int       os::Aix::_can_use_64K_pages = -1;
+int       os::Aix::_can_use_16M_pages = -1;
+int       os::Aix::_xpg_sus_mode = -1;
+int       os::Aix::_extshm = -1;
+int       os::Aix::_logical_cpus = -1;
+
+////////////////////////////////////////////////////////////////////////////////
+// local variables
+
+static int      g_multipage_error  = -1;   // error analysis for multipage initialization
+static jlong    initial_time_count = 0;
+static int      clock_tics_per_sec = 100;
+static sigset_t check_signal_done;         // For diagnostics to print a message once (see run_periodic_checks)
+static bool     check_signals      = true;
+static pid_t    _initial_pid       = 0;
+static int      SR_signum          = SIGUSR2; // Signal used to suspend/resume a thread (must be > SIGSEGV, see 4355769)
+static sigset_t SR_sigset;
+static pthread_mutex_t dl_mutex;           // Used to protect dlsym() calls */
+
+julong os::available_memory() {
+  return Aix::available_memory();
+}
+
+julong os::Aix::available_memory() {
+  Unimplemented();
+  return 0;
+}
+
+julong os::physical_memory() {
+  return Aix::physical_memory();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// environment support
+
+bool os::getenv(const char* name, char* buf, int len) {
+  const char* val = ::getenv(name);
+  if (val != NULL && strlen(val) < (size_t)len) {
+    strcpy(buf, val);
+    return true;
+  }
+  if (len > 0) buf[0] = 0;  // return a null string
+  return false;
+}
+
+
+// Return true if user is running as root.
+
+bool os::have_special_privileges() {
+  static bool init = false;
+  static bool privileges = false;
+  if (!init) {
+    privileges = (getuid() != geteuid()) || (getgid() != getegid());
+    init = true;
+  }
+  return privileges;
+}
+
+// Helper function, emulates disclaim64 using multiple 32bit disclaims
+// because we cannot use disclaim64() on AS/400 and old AIX releases.
+static bool my_disclaim64(char* addr, size_t size) {
+
+  if (size == 0) {
+    return true;
+  }
+
+  // Maximum size 32bit disclaim() accepts. (Theoretically 4GB, but I just do not trust that.)
+  const unsigned int maxDisclaimSize = 0x80000000;
+
+  const unsigned int numFullDisclaimsNeeded = (size / maxDisclaimSize);
+  const unsigned int lastDisclaimSize = (size % maxDisclaimSize);
+
+  char* p = addr;
+
+  for (int i = 0; i < numFullDisclaimsNeeded; i ++) {
+    if (::disclaim(p, maxDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
+      //if (Verbose)
+      fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno);
+      return false;
+    }
+    p += maxDisclaimSize;
+  }
+
+  if (lastDisclaimSize > 0) {
+    if (::disclaim(p, lastDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
+      //if (Verbose)
+        fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+// Cpu architecture string
+#if defined(PPC32)
+static char cpu_arch[] = "ppc";
+#elif defined(PPC64)
+static char cpu_arch[] = "ppc64";
+#else
+#error Add appropriate cpu_arch setting
+#endif
+
+
+// Given an address, returns the size of the page backing that address.
+size_t os::Aix::query_pagesize(void* addr) {
+
+  vm_page_info pi;
+  pi.addr = (uint64_t)addr;
+  if (::vmgetinfo(&pi, VM_PAGE_INFO, sizeof(pi)) == 0) {
+    return pi.pagesize;
+  } else {
+    fprintf(stderr, "vmgetinfo failed to retrieve page size for address %p (errno %d).\n", addr, errno);
+    assert(false, "vmgetinfo failed to retrieve page size");
+    return SIZE_4K;
+  }
+
+}
+
+// Returns the kernel thread id of the currently running thread.
+pid_t os::Aix::gettid() {
+  return (pid_t) thread_self();
+}
+
+void os::Aix::initialize_system_info() {
+
+  // get the number of online(logical) cpus instead of configured
+  os::_processor_count = sysconf(_SC_NPROCESSORS_ONLN);
+  assert(_processor_count > 0, "_processor_count must be > 0");
+
+  // retrieve total physical storage
+  os::Aix::meminfo_t mi;
+  if (!os::Aix::get_meminfo(&mi)) {
+    fprintf(stderr, "os::Aix::get_meminfo failed.\n"); fflush(stderr);
+    assert(false, "os::Aix::get_meminfo failed.");
+  }
+  _physical_memory = (julong) mi.real_total;
+}
+
+// Helper function for tracing page sizes.
+static const char* describe_pagesize(size_t pagesize) {
+  switch (pagesize) {
+    case SIZE_4K : return "4K";
+    case SIZE_64K: return "64K";
+    case SIZE_16M: return "16M";
+    case SIZE_16G: return "16G";
+    default:
+      assert(false, "surprise");
+      return "??";
+  }
+}
+
+// Retrieve information about multipage size support. Will initialize
+// Aix::_page_size, Aix::_stack_page_size, Aix::_can_use_64K_pages,
+// Aix::_can_use_16M_pages.
+// Must be called before calling os::large_page_init().
+void os::Aix::query_multipage_support() {
+
+  guarantee(_page_size == -1 &&
+            _stack_page_size == -1 &&
+            _can_use_64K_pages == -1 &&
+            _can_use_16M_pages == -1 &&
+            g_multipage_error == -1,
+            "do not call twice");
+
+  _page_size = ::sysconf(_SC_PAGESIZE);
+
+  // This really would surprise me.
+  assert(_page_size == SIZE_4K, "surprise!");
+
+
+  // query default data page size (default page size for C-Heap, pthread stacks and .bss).
+  // Default data page size is influenced either by linker options (-bdatapsize)
+  // or by environment variable LDR_CNTRL (suboption DATAPSIZE). If none is given,
+  // default should be 4K.
+  size_t data_page_size = SIZE_4K;
+  {
+    void* p = ::malloc(SIZE_16M);
+    data_page_size = os::Aix::query_pagesize(p);
+    ::free(p);
+  }
+
+  // query default shm page size (LDR_CNTRL SHMPSIZE)
+  {
+    const int shmid = ::shmget(IPC_PRIVATE, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
+    guarantee(shmid != -1, "shmget failed");
+    void* p = ::shmat(shmid, NULL, 0);
+    ::shmctl(shmid, IPC_RMID, NULL);
+    guarantee(p != (void*) -1, "shmat failed");
+    _shm_default_page_size = os::Aix::query_pagesize(p);
+    ::shmdt(p);
+  }
+
+  // before querying the stack page size, make sure we are not running as primordial
+  // thread (because primordial thread's stack may have different page size than
+  // pthread thread stacks). Running a VM on the primordial thread won't work for a
+  // number of reasons so we may just as well guarantee it here
+  guarantee(!os::Aix::is_primordial_thread(), "Must not be called for primordial thread");
+
+  // query stack page size
+  {
+    int dummy = 0;
+    _stack_page_size = os::Aix::query_pagesize(&dummy);
+    // everything else would surprise me and should be looked into
+    guarantee(_stack_page_size == SIZE_4K || _stack_page_size == SIZE_64K, "Wrong page size");
+    // also, just for completeness: pthread stacks are allocated from C heap, so
+    // stack page size should be the same as data page size
+    guarantee(_stack_page_size == data_page_size, "stack page size should be the same as data page size");
+  }
+
+  // EXTSHM is bad: among other things, it prevents setting pagesize dynamically
+  // for system V shm.
+  if (Aix::extshm()) {
+    if (Verbose) {
+      fprintf(stderr, "EXTSHM is active - will disable large page support.\n"
+                      "Please make sure EXTSHM is OFF for large page support.\n");
+    }
+    g_multipage_error = ERROR_MP_EXTSHM_ACTIVE;
+    _can_use_64K_pages = _can_use_16M_pages = 0;
+    goto query_multipage_support_end;
+  }
+
+  // now check which page sizes the OS claims it supports, and of those, which actually can be used.
+  {
+    const int MAX_PAGE_SIZES = 4;
+    psize_t sizes[MAX_PAGE_SIZES];
+    const int num_psizes = ::vmgetinfo(sizes, VMINFO_GETPSIZES, MAX_PAGE_SIZES);
+    if (num_psizes == -1) {
+      if (Verbose) {
+        fprintf(stderr, "vmgetinfo(VMINFO_GETPSIZES) failed (errno: %d)\n", errno);
+        fprintf(stderr, "disabling multipage support.\n");
+      }
+      g_multipage_error = ERROR_MP_VMGETINFO_FAILED;
+      _can_use_64K_pages = _can_use_16M_pages = 0;
+      goto query_multipage_support_end;
+    }
+    guarantee(num_psizes > 0, "vmgetinfo(.., VMINFO_GETPSIZES, ...) failed.");
+    assert(num_psizes <= MAX_PAGE_SIZES, "Surprise! more than 4 page sizes?");
+    if (Verbose) {
+      fprintf(stderr, "vmgetinfo(.., VMINFO_GETPSIZES, ...) returns %d supported page sizes: ", num_psizes);
+      for (int i = 0; i < num_psizes; i ++) {
+        fprintf(stderr, " %s ", describe_pagesize(sizes[i]));
+      }
+      fprintf(stderr, " .\n");
+    }
+
+    // Can we use 64K, 16M pages?
+    _can_use_64K_pages = 0;
+    _can_use_16M_pages = 0;
+    for (int i = 0; i < num_psizes; i ++) {
+      if (sizes[i] == SIZE_64K) {
+        _can_use_64K_pages = 1;
+      } else if (sizes[i] == SIZE_16M) {
+        _can_use_16M_pages = 1;
+      }
+    }
+
+    if (!_can_use_64K_pages) {
+      g_multipage_error = ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K;
+    }
+
+    // Double-check for 16M pages: Even if AIX claims to be able to use 16M pages,
+    // there must be an actual 16M page pool, and we must run with enough rights.
+    if (_can_use_16M_pages) {
+      const int shmid = ::shmget(IPC_PRIVATE, SIZE_16M, IPC_CREAT | S_IRUSR | S_IWUSR);
+      guarantee(shmid != -1, "shmget failed");
+      struct shmid_ds shm_buf = { 0 };
+      shm_buf.shm_pagesize = SIZE_16M;
+      const bool can_set_pagesize = ::shmctl(shmid, SHM_PAGESIZE, &shm_buf) == 0 ? true : false;
+      const int en = errno;
+      ::shmctl(shmid, IPC_RMID, NULL);
+      if (!can_set_pagesize) {
+        if (Verbose) {
+          fprintf(stderr, "Failed to allocate even one misely 16M page. shmctl failed with %d (%s).\n"
+                          "Will deactivate 16M support.\n", en, strerror(en));
+        }
+        _can_use_16M_pages = 0;
+      }
+    }
+
+  } // end: check which pages can be used for shared memory
+
+query_multipage_support_end:
+
+  guarantee(_page_size != -1 &&
+            _stack_page_size != -1 &&
+            _can_use_64K_pages != -1 &&
+            _can_use_16M_pages != -1, "Page sizes not properly initialized");
+
+  if (_can_use_64K_pages) {
+    g_multipage_error = 0;
+  }
+
+  if (Verbose) {
+    fprintf(stderr, "Data page size (C-Heap, bss, etc): %s\n", describe_pagesize(data_page_size));
+    fprintf(stderr, "Thread stack page size (pthread): %s\n", describe_pagesize(_stack_page_size));
+    fprintf(stderr, "Default shared memory page size: %s\n", describe_pagesize(_shm_default_page_size));
+    fprintf(stderr, "Can use 64K pages dynamically with shared meory: %s\n", (_can_use_64K_pages ? "yes" :"no"));
+    fprintf(stderr, "Can use 16M pages dynamically with shared memory: %s\n", (_can_use_16M_pages ? "yes" :"no"));
+    fprintf(stderr, "Multipage error details: %d\n", g_multipage_error);
+  }
+
+} // end os::Aix::query_multipage_support()
+
+
+// The code for this method was initially derived from the version in os_linux.cpp
+void os::init_system_properties_values() {
+  // The next few definitions allow the code to be verbatim:
+#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
+#define DEFAULT_LIBPATH "/usr/lib:/lib"
+#define EXTENSIONS_DIR  "/lib/ext"
+#define ENDORSED_DIR    "/lib/endorsed"
+
+  // sysclasspath, java_home, dll_dir
+  char *home_path;
+  char *dll_path;
+  char *pslash;
+  char buf[MAXPATHLEN];
+  os::jvm_path(buf, sizeof(buf));
+
+  // Found the full path to libjvm.so.
+  // Now cut the path to <java_home>/jre if we can.
+  *(strrchr(buf, '/')) = '\0'; // get rid of /libjvm.so
+  pslash = strrchr(buf, '/');
+  if (pslash != NULL) {
+    *pslash = '\0';            // get rid of /{client|server|hotspot}
+  }
+
+  dll_path = malloc(strlen(buf) + 1);
+  strcpy(dll_path, buf);
+  Arguments::set_dll_dir(dll_path);
+
+  if (pslash != NULL) {
+    pslash = strrchr(buf, '/');
+    if (pslash != NULL) {
+      *pslash = '\0';          // get rid of /<arch>
+      pslash = strrchr(buf, '/');
+      if (pslash != NULL) {
+        *pslash = '\0';        // get rid of /lib
+      }
+    }
+  }
+
+  home_path = malloc(strlen(buf) + 1);
+  strcpy(home_path, buf);
+  Arguments::set_java_home(home_path);
+
+  if (!set_boot_path('/', ':')) return;
+
+  // Where to look for native libraries
+
+  // On Aix we get the user setting of LIBPATH
+  // Eventually, all the library path setting will be done here.
+  char *ld_library_path;
+
+  // Construct the invariant part of ld_library_path.
+  ld_library_path = (char *) malloc(sizeof(DEFAULT_LIBPATH));
+  sprintf(ld_library_path, DEFAULT_LIBPATH);
+
+  // Get the user setting of LIBPATH, and prepended it.
+  char *v = ::getenv("LIBPATH");
+  if (v == NULL) {
+    v = "";
+  }
+
+  char *t = ld_library_path;
+  // That's +1 for the colon and +1 for the trailing '\0'
+  ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1);
+  sprintf(ld_library_path, "%s:%s", v, t);
+
+  Arguments::set_library_path(ld_library_path);
+
+  // Extensions directories
+  char* cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(EXTENSIONS_DIR));
+  sprintf(cbuf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
+  Arguments::set_ext_dirs(cbuf);
+
+  // Endorsed standards default directory.
+  cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
+  sprintf(cbuf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+  Arguments::set_endorsed_dirs(cbuf);
+
+#undef malloc
+#undef DEFAULT_LIBPATH
+#undef EXTENSIONS_DIR
+#undef ENDORSED_DIR
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// breakpoint support
+
+void os::breakpoint() {
+  BREAKPOINT;
+}
+
+extern "C" void breakpoint() {
+  // use debugger to set breakpoint here
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// signal support
+
+debug_only(static bool signal_sets_initialized = false);
+static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs;
+
+bool os::Aix::is_sig_ignored(int sig) {
+  struct sigaction oact;
+  sigaction(sig, (struct sigaction*)NULL, &oact);
+  void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction)
+    : CAST_FROM_FN_PTR(void*, oact.sa_handler);
+  if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN))
+    return true;
+  else
+    return false;
+}
+
+void os::Aix::signal_sets_init() {
+  // Should also have an assertion stating we are still single-threaded.
+  assert(!signal_sets_initialized, "Already initialized");
+  // Fill in signals that are necessarily unblocked for all threads in
+  // the VM. Currently, we unblock the following signals:
+  // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden
+  //                         by -Xrs (=ReduceSignalUsage));
+  // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all
+  // other threads. The "ReduceSignalUsage" boolean tells us not to alter
+  // the dispositions or masks wrt these signals.
+  // Programs embedding the VM that want to use the above signals for their
+  // own purposes must, at this time, use the "-Xrs" option to prevent
+  // interference with shutdown hooks and BREAK_SIGNAL thread dumping.
+  // (See bug 4345157, and other related bugs).
+  // In reality, though, unblocking these signals is really a nop, since
+  // these signals are not blocked by default.
+  sigemptyset(&unblocked_sigs);
+  sigemptyset(&allowdebug_blocked_sigs);
+  sigaddset(&unblocked_sigs, SIGILL);
+  sigaddset(&unblocked_sigs, SIGSEGV);
+  sigaddset(&unblocked_sigs, SIGBUS);
+  sigaddset(&unblocked_sigs, SIGFPE);
+  sigaddset(&unblocked_sigs, SIGTRAP);
+  sigaddset(&unblocked_sigs, SIGDANGER);
+  sigaddset(&unblocked_sigs, SR_signum);
+
+  if (!ReduceSignalUsage) {
+   if (!os::Aix::is_sig_ignored(SHUTDOWN1_SIGNAL)) {
+     sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL);
+     sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL);
+   }
+   if (!os::Aix::is_sig_ignored(SHUTDOWN2_SIGNAL)) {
+     sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL);
+     sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL);
+   }
+   if (!os::Aix::is_sig_ignored(SHUTDOWN3_SIGNAL)) {
+     sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL);
+     sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL);
+   }
+  }
+  // Fill in signals that are blocked by all but the VM thread.
+  sigemptyset(&vm_sigs);
+  if (!ReduceSignalUsage)
+    sigaddset(&vm_sigs, BREAK_SIGNAL);
+  debug_only(signal_sets_initialized = true);
+}
+
+// These are signals that are unblocked while a thread is running Java.
+// (For some reason, they get blocked by default.)
+sigset_t* os::Aix::unblocked_signals() {
+  assert(signal_sets_initialized, "Not initialized");
+  return &unblocked_sigs;
+}
+
+// These are the signals that are blocked while a (non-VM) thread is
+// running Java. Only the VM thread handles these signals.
+sigset_t* os::Aix::vm_signals() {
+  assert(signal_sets_initialized, "Not initialized");
+  return &vm_sigs;
+}
+
+// These are signals that are blocked during cond_wait to allow debugger in
+sigset_t* os::Aix::allowdebug_blocked_signals() {
+  assert(signal_sets_initialized, "Not initialized");
+  return &allowdebug_blocked_sigs;
+}
+
+void os::Aix::hotspot_sigmask(Thread* thread) {
+
+  //Save caller's signal mask before setting VM signal mask
+  sigset_t caller_sigmask;
+  pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask);
+
+  OSThread* osthread = thread->osthread();
+  osthread->set_caller_sigmask(caller_sigmask);
+
+  pthread_sigmask(SIG_UNBLOCK, os::Aix::unblocked_signals(), NULL);
+
+  if (!ReduceSignalUsage) {
+    if (thread->is_VM_thread()) {
+      // Only the VM thread handles BREAK_SIGNAL ...
+      pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL);
+    } else {
+      // ... all other threads block BREAK_SIGNAL
+      pthread_sigmask(SIG_BLOCK, vm_signals(), NULL);
+    }
+  }
+}
+
+// retrieve memory information.
+// Returns false if something went wrong;
+// content of pmi undefined in this case.
+bool os::Aix::get_meminfo(meminfo_t* pmi) {
+
+  assert(pmi, "get_meminfo: invalid parameter");
+
+  memset(pmi, 0, sizeof(meminfo_t));
+
+  if (os::Aix::on_pase()) {
+
+    Unimplemented();
+    return false;
+
+  } else {
+
+    // On AIX, I use the (dynamically loaded) perfstat library to retrieve memory statistics
+    // See:
+    // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
+    //        ?topic=/com.ibm.aix.basetechref/doc/basetrf1/perfstat_memtot.htm
+    // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
+    //        ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm
+
+    perfstat_memory_total_t psmt;
+    memset (&psmt, '\0', sizeof(psmt));
+    const int rc = libperfstat::perfstat_memory_total(NULL, &psmt, sizeof(psmt), 1);
+    if (rc == -1) {
+      fprintf(stderr, "perfstat_memory_total() failed (errno=%d)\n", errno);
+      assert(0, "perfstat_memory_total() failed");
+      return false;
+    }
+
+    assert(rc == 1, "perfstat_memory_total() - weird return code");
+
+    // excerpt from
+    // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
+    //        ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm
+    // The fields of perfstat_memory_total_t:
+    // u_longlong_t virt_total         Total virtual memory (in 4 KB pages).
+    // u_longlong_t real_total         Total real memory (in 4 KB pages).
+    // u_longlong_t real_free          Free real memory (in 4 KB pages).
+    // u_longlong_t pgsp_total         Total paging space (in 4 KB pages).
+    // u_longlong_t pgsp_free          Free paging space (in 4 KB pages).
+
+    pmi->virt_total = psmt.virt_total * 4096;
+    pmi->real_total = psmt.real_total * 4096;
+    pmi->real_free = psmt.real_free * 4096;
+    pmi->pgsp_total = psmt.pgsp_total * 4096;
+    pmi->pgsp_free = psmt.pgsp_free * 4096;
+
+    return true;
+
+  }
+} // end os::Aix::get_meminfo
+
+// Retrieve global cpu information.
+// Returns false if something went wrong;
+// the content of pci is undefined in this case.
+bool os::Aix::get_cpuinfo(cpuinfo_t* pci) {
+  assert(pci, "get_cpuinfo: invalid parameter");
+  memset(pci, 0, sizeof(cpuinfo_t));
+
+  perfstat_cpu_total_t psct;
+  memset (&psct, '\0', sizeof(psct));
+
+  if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(perfstat_cpu_total_t), 1)) {
+    fprintf(stderr, "perfstat_cpu_total() failed (errno=%d)\n", errno);
+    assert(0, "perfstat_cpu_total() failed");
+    return false;
+  }
+
+  // global cpu information
+  strcpy (pci->description, psct.description);
+  pci->processorHZ = psct.processorHZ;
+  pci->ncpus = psct.ncpus;
+  os::Aix::_logical_cpus = psct.ncpus;
+  for (int i = 0; i < 3; i++) {
+    pci->loadavg[i] = (double) psct.loadavg[i] / (1 << SBITS);
+  }
+
+  // get the processor version from _system_configuration
+  switch (_system_configuration.version) {
+  case PV_7:
+    strcpy(pci->version, "Power PC 7");
+    break;
+  case PV_6_1:
+    strcpy(pci->version, "Power PC 6 DD1.x");
+    break;
+  case PV_6:
+    strcpy(pci->version, "Power PC 6");
+    break;
+  case PV_5:
+    strcpy(pci->version, "Power PC 5");
+    break;
+  case PV_5_2:
+    strcpy(pci->version, "Power PC 5_2");
+    break;
+  case PV_5_3:
+    strcpy(pci->version, "Power PC 5_3");
+    break;
+  case PV_5_Compat:
+    strcpy(pci->version, "PV_5_Compat");
+    break;
+  case PV_6_Compat:
+    strcpy(pci->version, "PV_6_Compat");
+    break;
+  case PV_7_Compat:
+    strcpy(pci->version, "PV_7_Compat");
+    break;
+  default:
+    strcpy(pci->version, "unknown");
+  }
+
+  return true;
+
+} //end os::Aix::get_cpuinfo
+
+//////////////////////////////////////////////////////////////////////////////
+// detecting pthread library
+
+void os::Aix::libpthread_init() {
+  return;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// create new thread
+
+// Thread start routine for all newly created threads
+static void *java_start(Thread *thread) {
+
+  // find out my own stack dimensions
+  {
+    // actually, this should do exactly the same as thread->record_stack_base_and_size...
+    address base = 0;
+    size_t size = 0;
+    query_stack_dimensions(&base, &size);
+    thread->set_stack_base(base);
+    thread->set_stack_size(size);
+  }
+
+  // Do some sanity checks.
+  CHECK_CURRENT_STACK_PTR(thread->stack_base(), thread->stack_size());
+
+  // Try to randomize the cache line index of hot stack frames.
+  // This helps when threads of the same stack traces evict each other's
+  // cache lines. The threads can be either from the same JVM instance, or
+  // from different JVM instances. The benefit is especially true for
+  // processors with hyperthreading technology.
+
+  static int counter = 0;
+  int pid = os::current_process_id();
+  alloca(((pid ^ counter++) & 7) * 128);
+
+  ThreadLocalStorage::set_thread(thread);
+
+  OSThread* osthread = thread->osthread();
+
+  // thread_id is kernel thread id (similar to Solaris LWP id)
+  osthread->set_thread_id(os::Aix::gettid());
+
+  // initialize signal mask for this thread
+  os::Aix::hotspot_sigmask(thread);
+
+  // initialize floating point control register
+  os::Aix::init_thread_fpu_state();
+
+  assert(osthread->get_state() == RUNNABLE, "invalid os thread state");
+
+  // call one more level start routine
+  thread->run();
+
+  return 0;
+}
+
+bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
+
+  // We want the whole function to be synchronized.
+  ThreadCritical cs;
+
+  assert(thread->osthread() == NULL, "caller responsible");
+
+  // Allocate the OSThread object
+  OSThread* osthread = new OSThread(NULL, NULL);
+  if (osthread == NULL) {
+    return false;
+  }
+
+  // set the correct thread state
+  osthread->set_thread_type(thr_type);
+
+  // Initial state is ALLOCATED but not INITIALIZED
+  osthread->set_state(ALLOCATED);
+
+  thread->set_osthread(osthread);
+
+  // init thread attributes
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???");
+
+  // Make sure we run in 1:1 kernel-user-thread mode.
+  if (os::Aix::on_aix()) {
+    guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???");
+    guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???");
+  } // end: aix
+
+  // Start in suspended state, and in os::thread_start, wake the thread up.
+  guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");
+
+  // calculate stack size if it's not specified by caller
+  if (os::Aix::supports_variable_stack_size()) {
+    if (stack_size == 0) {
+      stack_size = os::Aix::default_stack_size(thr_type);
+
+      switch (thr_type) {
+      case os::java_thread:
+        // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss.
+        assert(JavaThread::stack_size_at_create() > 0, "this should be set");
+        stack_size = JavaThread::stack_size_at_create();
+        break;
+      case os::compiler_thread:
+        if (CompilerThreadStackSize > 0) {
+          stack_size = (size_t)(CompilerThreadStackSize * K);
+          break;
+        } // else fall through:
+          // use VMThreadStackSize if CompilerThreadStackSize is not defined
+      case os::vm_thread:
+      case os::pgc_thread:
+      case os::cgc_thread:
+      case os::watcher_thread:
+        if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
+        break;
+      }
+    }
+
+    stack_size = MAX2(stack_size, os::Aix::min_stack_allowed);
+    pthread_attr_setstacksize(&attr, stack_size);
+  } //else let thread_create() pick the default value (96 K on AIX)
+
+  pthread_t tid;
+  int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
+
+  pthread_attr_destroy(&attr);
+
+  if (ret != 0) {
+    if (PrintMiscellaneous && (Verbose || WizardMode)) {
+      perror("pthread_create()");
+    }
+    // Need to clean up stuff we've allocated so far
+    thread->set_osthread(NULL);
+    delete osthread;
+    return false;
+  }
+
+  // Store pthread info into the OSThread
+  osthread->set_pthread_id(tid);
+
+  return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// attach existing thread
+
+// bootstrap the main thread
+bool os::create_main_thread(JavaThread* thread) {
+  assert(os::Aix::_main_thread == pthread_self(), "should be called inside main thread");
+  return create_attached_thread(thread);
+}
+
+bool os::create_attached_thread(JavaThread* thread) {
+#ifdef ASSERT
+    thread->verify_not_published();
+#endif
+
+  // Allocate the OSThread object
+  OSThread* osthread = new OSThread(NULL, NULL);
+
+  if (osthread == NULL) {
+    return false;
+  }
+
+  // Store pthread info into the OSThread
+  osthread->set_thread_id(os::Aix::gettid());
+  osthread->set_pthread_id(::pthread_self());
+
+  // initialize floating point control register
+  os::Aix::init_thread_fpu_state();
+
+  // some sanity checks
+  CHECK_CURRENT_STACK_PTR(thread->stack_base(), thread->stack_size());
+
+  // Initial thread state is RUNNABLE
+  osthread->set_state(RUNNABLE);
+
+  thread->set_osthread(osthread);
+
+  if (UseNUMA) {
+    int lgrp_id = os::numa_get_group_id();
+    if (lgrp_id != -1) {
+      thread->set_lgrp_id(lgrp_id);
+    }
+  }
+
+  // initialize signal mask for this thread
+  // and save the caller's signal mask
+  os::Aix::hotspot_sigmask(thread);
+
+  return true;
+}
+
+void os::pd_start_thread(Thread* thread) {
+  int status = pthread_continue_np(thread->osthread()->pthread_id());
+  assert(status == 0, "thr_continue failed");
+}
+
+// Free OS resources related to the OSThread
+void os::free_thread(OSThread* osthread) {
+  assert(osthread != NULL, "osthread not set");
+
+  if (Thread::current()->osthread() == osthread) {
+    // Restore caller's signal mask
+    sigset_t sigmask = osthread->caller_sigmask();
+    pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
+   }
+
+  delete osthread;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// thread local storage
+
+int os::allocate_thread_local_storage() {
+  pthread_key_t key;
+  int rslt = pthread_key_create(&key, NULL);
+  assert(rslt == 0, "cannot allocate thread local storage");
+  return (int)key;
+}
+
+// Note: This is currently not used by VM, as we don't destroy TLS key
+// on VM exit.
+void os::free_thread_local_storage(int index) {
+  int rslt = pthread_key_delete((pthread_key_t)index);
+  assert(rslt == 0, "invalid index");
+}
+
+void os::thread_local_storage_at_put(int index, void* value) {
+  int rslt = pthread_setspecific((pthread_key_t)index, value);
+  assert(rslt == 0, "pthread_setspecific failed");
+}
+
+extern "C" Thread* get_thread() {
+  return ThreadLocalStorage::thread();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// time support
+
+// Time since start-up in seconds to a fine granularity.
+// Used by VMSelfDestructTimer and the MemProfiler.
+double os::elapsedTime() {
+  return (double)(os::elapsed_counter()) * 0.000001;
+}
+
+jlong os::elapsed_counter() {
+  timeval time;
+  int status = gettimeofday(&time, NULL);
+  return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count;
+}
+
+jlong os::elapsed_frequency() {
+  return (1000 * 1000);
+}
+
+// For now, we say that linux does not support vtime. I have no idea
+// whether it can actually be made to (DLD, 9/13/05).
+
+bool os::supports_vtime() { return false; }
+bool os::enable_vtime()   { return false; }
+bool os::vtime_enabled()  { return false; }
+double os::elapsedVTime() {
+  // better than nothing, but not much
+  return elapsedTime();
+}
+
+jlong os::javaTimeMillis() {
+  timeval time;
+  int status = gettimeofday(&time, NULL);
+  assert(status != -1, "aix error at gettimeofday()");
+  return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
+}
+
+// We need to manually declare mread_real_time,
+// because IBM didn't provide a prototype in time.h.
+// (they probably only ever tested in C, not C++)
+extern "C"
+int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t);
+
+jlong os::javaTimeNanos() {
+  if (os::Aix::on_pase()) {
+    Unimplemented();
+    return 0;
+  }
+  else {
+    // On AIX use the precision of processors real time clock
+    // or time base registers.
+    timebasestruct_t time;
+    int rc;
+
+    // If the CPU has a time register, it will be used and
+    // we have to convert to real time first. After convertion we have following data:
+    // time.tb_high [seconds since 00:00:00 UTC on 1.1.1970]
+    // time.tb_low  [nanoseconds after the last full second above]
+    // We better use mread_real_time here instead of read_real_time
+    // to ensure that we will get a monotonic increasing time.
+    if (mread_real_time(&time, TIMEBASE_SZ) != RTC_POWER) {
+      rc = time_base_to_time(&time, TIMEBASE_SZ);
+      assert(rc != -1, "aix error at time_base_to_time()");
+    }
+    return jlong(time.tb_high) * (1000 * 1000 * 1000) + jlong(time.tb_low);
+  }
+}
+
+void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
+  {
+    // gettimeofday - based on time in seconds since the Epoch thus does not wrap
+    info_ptr->max_value = ALL_64_BITS;
+
+    // gettimeofday is a real time clock so it skips
+    info_ptr->may_skip_backward = true;
+    info_ptr->may_skip_forward = true;
+  }
+
+  info_ptr->kind = JVMTI_TIMER_ELAPSED;    // elapsed not CPU time
+}
+
+// Return the real, user, and system times in seconds from an
+// arbitrary fixed point in the past.
+bool os::getTimesSecs(double* process_real_time,
+                      double* process_user_time,
+                      double* process_system_time) {
+  Unimplemented();
+  return false;
+}
+
+
+char * os::local_time_string(char *buf, size_t buflen) {
+  struct tm t;
+  time_t long_time;
+  time(&long_time);
+  localtime_r(&long_time, &t);
+  jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d",
+               t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
+               t.tm_hour, t.tm_min, t.tm_sec);
+  return buf;
+}
+
+struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {
+  return localtime_r(clock, res);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// runtime exit support
+
+// Note: os::shutdown() might be called very early during initialization, or
+// called from signal handler. Before adding something to os::shutdown(), make
+// sure it is async-safe and can handle partially initialized VM.
+void os::shutdown() {
+
+  // allow PerfMemory to attempt cleanup of any persistent resources
+  perfMemory_exit();
+
+  // needs to remove object in file system
+  AttachListener::abort();
+
+  // flush buffered output, finish log files
+  ostream_abort();
+
+  // Check for abort hook
+  abort_hook_t abort_hook = Arguments::abort_hook();
+  if (abort_hook != NULL) {
+    abort_hook();
+  }
+
+}
+
+// Note: os::abort() might be called very early during initialization, or
+// called from signal handler. Before adding something to os::abort(), make
+// sure it is async-safe and can handle partially initialized VM.
+void os::abort(bool dump_core) {
+  os::shutdown();
+  if (dump_core) {
+#ifndef PRODUCT
+    fdStream out(defaultStream::output_fd());
+    out.print_raw("Current thread is ");
+    char buf[16];
+    jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id());
+    out.print_raw_cr(buf);
+    out.print_raw_cr("Dumping core ...");
+#endif
+    ::abort(); // dump core
+  }
+
+  ::exit(1);
+}
+
+// Die immediately, no exit hook, no abort hook, no cleanup.
+void os::die() {
+  ::abort();
+}
+
+// Unused on Aix for now.
+void os::set_error_file(const char *logfile) {}
+
+
+// This method is a copy of JDK's sysGetLastErrorString
+// from src/solaris/hpi/src/system_md.c
+
+size_t os::lasterror(char *buf, size_t len) {
+
+  if (errno == 0)  return 0;
+
+  const char *s = ::strerror(errno);
+  size_t n = ::strlen(s);
+  if (n >= len) {
+    n = len - 1;
+  }
+  ::strncpy(buf, s, n);
+  buf[n] = '\0';
+  return n;
+}
+
+intx os::current_thread_id() { return (intx)pthread_self(); }
+int os::current_process_id() {
+
+  // This implementation returns a unique pid, the pid of the
+  // launcher thread that starts the vm 'process'.
+
+  // Under POSIX, getpid() returns the same pid as the
+  // launcher thread rather than a unique pid per thread.
+  // Use gettid() if you want the old pre NPTL behaviour.
+
+  // if you are looking for the result of a call to getpid() that
+  // returns a unique pid for the calling thread, then look at the
+  // OSThread::thread_id() method in osThread_linux.hpp file
+
+  return (int)(_initial_pid ? _initial_pid : getpid());
+}
+
+// DLL functions
+
+const char* os::dll_file_extension() { return ".so"; }
+
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
+
+static bool file_exists(const char* filename) {
+  struct stat statbuf;
+  if (filename == NULL || strlen(filename) == 0) {
+    return false;
+  }
+  return os::stat(filename, &statbuf) == 0;
+}
+
+bool os::dll_build_name(char* buffer, size_t buflen,
+                        const char* pname, const char* fname) {
+  bool retval = false;
+  // Copied from libhpi
+  const size_t pnamelen = pname ? strlen(pname) : 0;
+
+  // Return error on buffer overflow.
+  if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
+    *buffer = '\0';
+    return retval;
+  }
+
+  if (pnamelen == 0) {
+    snprintf(buffer, buflen, "lib%s.so", fname);
+    retval = true;
+  } else if (strchr(pname, *os::path_separator()) != NULL) {
+    int n;
+    char** pelements = split_path(pname, &n);
+    for (int i = 0; i < n; i++) {
+      // Really shouldn't be NULL, but check can't hurt
+      if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
+        continue; // skip the empty path values
+      }
+      snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
+      if (file_exists(buffer)) {
+        retval = true;
+        break;
+      }
+    }
+    // release the storage
+    for (int i = 0; i < n; i++) {
+      if (pelements[i] != NULL) {
+        FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal);
+      }
+    }
+    if (pelements != NULL) {
+      FREE_C_HEAP_ARRAY(char*, pelements, mtInternal);
+    }
+  } else {
+    snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
+    retval = true;
+  }
+  return retval;
+}
+
+// Check if addr is inside libjvm.so.
+bool os::address_is_in_vm(address addr) {
+
+  // Input could be a real pc or a function pointer literal. The latter
+  // would be a function descriptor residing in the data segment of a module.
+
+  const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(addr);
+  if (lib) {
+    if (strcmp(lib->get_shortname(), "libjvm.so") == 0) {
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    lib = LoadedLibraries::find_for_data_address(addr);
+    if (lib) {
+      if (strcmp(lib->get_shortname(), "libjvm.so") == 0) {
+        return true;
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+}
+
+// Resolve an AIX function descriptor literal to a code pointer.
+// If the input is a valid code pointer to a text segment of a loaded module,
+//   it is returned unchanged.
+// If the input is a valid AIX function descriptor, it is resolved to the
+//   code entry point.
+// If the input is neither a valid function descriptor nor a valid code pointer,
+//   NULL is returned.
+static address resolve_function_descriptor_to_code_pointer(address p) {
+
+  const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(p);
+  if (lib) {
+    // its a real code pointer
+    return p;
+  } else {
+    lib = LoadedLibraries::find_for_data_address(p);
+    if (lib) {
+      // pointer to data segment, potential function descriptor
+      address code_entry = (address)(((FunctionDescriptor*)p)->entry());
+      if (LoadedLibraries::find_for_text_address(code_entry)) {
+        // Its a function descriptor
+        return code_entry;
+      }
+    }
+  }
+  return NULL;
+}
+
+bool os::dll_address_to_function_name(address addr, char *buf,
+                                      int buflen, int *offset) {
+  if (offset) {
+    *offset = -1;
+  }
+  if (buf) {
+    buf[0] = '\0';
+  }
+
+  // Resolve function ptr literals first.
+  addr = resolve_function_descriptor_to_code_pointer(addr);
+  if (!addr) {
+    return false;
+  }
+
+  // Go through Decoder::decode to call getFuncName which reads the name from the traceback table.
+  return Decoder::decode(addr, buf, buflen, offset);
+}
+
+static int getModuleName(codeptr_t pc,                    // [in] program counter
+                         char* p_name, size_t namelen,    // [out] optional: function name
+                         char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
+                         ) {
+
+  // initialize output parameters
+  if (p_name && namelen > 0) {
+    *p_name = '\0';
+  }
+  if (p_errmsg && errmsglen > 0) {
+    *p_errmsg = '\0';
+  }
+
+  const LoadedLibraryModule* const lib = LoadedLibraries::find_for_text_address((address)pc);
+  if (lib) {
+    if (p_name && namelen > 0) {
+      sprintf(p_name, "%.*s", namelen, lib->get_shortname());
+    }
+    return 0;
+  }
+
+  if (Verbose) {
+    fprintf(stderr, "pc outside any module");
+  }
+
+  return -1;
+
+}
+
+bool os::dll_address_to_library_name(address addr, char* buf,
+                                     int buflen, int* offset) {
+  if (offset) {
+    *offset = -1;
+  }
+  if (buf) {
+      buf[0] = '\0';
+  }
+
+  // Resolve function ptr literals first.
+  addr = resolve_function_descriptor_to_code_pointer(addr);
+  if (!addr) {
+    return false;
+  }
+
+  if (::getModuleName((codeptr_t) addr, buf, buflen, 0, 0) == 0) {
+    return true;
+  }
+  return false;
+}
+
+// Loads .dll/.so and in case of error it checks if .dll/.so was built
+// for the same architecture as Hotspot is running on
+void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+
+  if (ebuf && ebuflen > 0) {
+    ebuf[0] = '\0';
+    ebuf[ebuflen - 1] = '\0';
+  }
+
+  if (!filename || strlen(filename) == 0) {
+    ::strncpy(ebuf, "dll_load: empty filename specified", ebuflen - 1);
+    return NULL;
+  }
+
+  // RTLD_LAZY is currently not implemented. The dl is loaded immediately with all its dependants.
+  void * result= ::dlopen(filename, RTLD_LAZY);
+  if (result != NULL) {
+    // Reload dll cache. Don't do this in signal handling.
+    LoadedLibraries::reload();
+    return result;
+  } else {
+    // error analysis when dlopen fails
+    const char* const error_report = ::dlerror();
+    if (error_report && ebuf && ebuflen > 0) {
+      snprintf(ebuf, ebuflen - 1, "%s, LIBPATH=%s, LD_LIBRARY_PATH=%s : %s",
+               filename, ::getenv("LIBPATH"), ::getenv("LD_LIBRARY_PATH"), error_report);
+    }
+  }
+  return NULL;
+}
+
+// Glibc-2.0 libdl is not MT safe. If you are building with any glibc,
+// chances are you might want to run the generated bits against glibc-2.0
+// libdl.so, so always use locking for any version of glibc.
+void* os::dll_lookup(void* handle, const char* name) {
+  pthread_mutex_lock(&dl_mutex);
+  void* res = dlsym(handle, name);
+  pthread_mutex_unlock(&dl_mutex);
+  return res;
+}
+
+void os::print_dll_info(outputStream *st) {
+  st->print_cr("Dynamic libraries:");
+  LoadedLibraries::print(st);
+}
+
+void os::print_os_info(outputStream* st) {
+  st->print("OS:");
+
+  st->print("uname:");
+  struct utsname name;
+  uname(&name);
+  st->print(name.sysname); st->print(" ");
+  st->print(name.nodename); st->print(" ");
+  st->print(name.release); st->print(" ");
+  st->print(name.version); st->print(" ");
+  st->print(name.machine);
+  st->cr();
+
+  // rlimit
+  st->print("rlimit:");
+  struct rlimit rlim;
+
+  st->print(" STACK ");
+  getrlimit(RLIMIT_STACK, &rlim);
+  if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+  else st->print("%uk", rlim.rlim_cur >> 10);
+
+  st->print(", CORE ");
+  getrlimit(RLIMIT_CORE, &rlim);
+  if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+  else st->print("%uk", rlim.rlim_cur >> 10);
+
+  st->print(", NPROC ");
+  st->print("%d", sysconf(_SC_CHILD_MAX));
+
+  st->print(", NOFILE ");
+  getrlimit(RLIMIT_NOFILE, &rlim);
+  if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+  else st->print("%d", rlim.rlim_cur);
+
+  st->print(", AS ");
+  getrlimit(RLIMIT_AS, &rlim);
+  if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+  else st->print("%uk", rlim.rlim_cur >> 10);
+
+  // Print limits on DATA, because it limits the C-heap.
+  st->print(", DATA ");
+  getrlimit(RLIMIT_DATA, &rlim);
+  if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+  else st->print("%uk", rlim.rlim_cur >> 10);
+  st->cr();
+
+  // load average
+  st->print("load average:");
+  double loadavg[3] = {-1.L, -1.L, -1.L};
+  os::loadavg(loadavg, 3);
+  st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);
+  st->cr();
+}
+
+void os::print_memory_info(outputStream* st) {
+
+  st->print_cr("Memory:");
+
+  st->print_cr("  default page size: %s", describe_pagesize(os::vm_page_size()));
+  st->print_cr("  default stack page size: %s", describe_pagesize(os::vm_page_size()));
+  st->print_cr("  default shm page size: %s", describe_pagesize(os::Aix::shm_default_page_size()));
+  st->print_cr("  can use 64K pages dynamically: %s", (os::Aix::can_use_64K_pages() ? "yes" :"no"));
+  st->print_cr("  can use 16M pages dynamically: %s", (os::Aix::can_use_16M_pages() ? "yes" :"no"));
+  if (g_multipage_error != 0) {
+    st->print_cr("  multipage error: %d", g_multipage_error);
+  }
+
+  // print out LDR_CNTRL because it affects the default page sizes
+  const char* const ldr_cntrl = ::getenv("LDR_CNTRL");
+  st->print_cr("  LDR_CNTRL=%s.", ldr_cntrl ? ldr_cntrl : "<unset>");
+
+  const char* const extshm = ::getenv("EXTSHM");
+  st->print_cr("  EXTSHM=%s.", extshm ? extshm : "<unset>");
+
+  // Call os::Aix::get_meminfo() to retrieve memory statistics.
+  os::Aix::meminfo_t mi;
+  if (os::Aix::get_meminfo(&mi)) {
+    char buffer[256];
+    if (os::Aix::on_aix()) {
+      jio_snprintf(buffer, sizeof(buffer),
+                   "  physical total : %llu\n"
+                   "  physical free  : %llu\n"
+                   "  swap total     : %llu\n"
+                   "  swap free      : %llu\n",
+                   mi.real_total,
+                   mi.real_free,
+                   mi.pgsp_total,
+                   mi.pgsp_free);
+    } else {
+      Unimplemented();
+    }
+    st->print_raw(buffer);
+  } else {
+    st->print_cr("  (no more information available)");
+  }
+}
+
+void os::pd_print_cpu_info(outputStream* st) {
+  // cpu
+  st->print("CPU:");
+  st->print("total %d", os::processor_count());
+  // It's not safe to query number of active processors after crash
+  // st->print("(active %d)", os::active_processor_count());
+  st->print(" %s", VM_Version::cpu_features());
+  st->cr();
+}
+
+void os::print_siginfo(outputStream* st, void* siginfo) {
+  // Use common posix version.
+  os::Posix::print_siginfo_brief(st, (const siginfo_t*) siginfo);
+  st->cr();
+}
+
+
+static void print_signal_handler(outputStream* st, int sig,
+                                 char* buf, size_t buflen);
+
+void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
+  st->print_cr("Signal Handlers:");
+  print_signal_handler(st, SIGSEGV, buf, buflen);
+  print_signal_handler(st, SIGBUS , buf, buflen);
+  print_signal_handler(st, SIGFPE , buf, buflen);
+  print_signal_handler(st, SIGPIPE, buf, buflen);
+  print_signal_handler(st, SIGXFSZ, buf, buflen);
+  print_signal_handler(st, SIGILL , buf, buflen);
+  print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen);
+  print_signal_handler(st, SR_signum, buf, buflen);
+  print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen);
+  print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen);
+  print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
+  print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
+  print_signal_handler(st, SIGTRAP, buf, buflen);
+  print_signal_handler(st, SIGDANGER, buf, buflen);
+}
+
+static char saved_jvm_path[MAXPATHLEN] = {0};
+
+// Find the full path to the current module, libjvm.so or libjvm_g.so
+void os::jvm_path(char *buf, jint buflen) {
+  // Error checking.
+  if (buflen < MAXPATHLEN) {
+    assert(false, "must use a large-enough buffer");
+    buf[0] = '\0';
+    return;
+  }
+  // Lazy resolve the path to current module.
+  if (saved_jvm_path[0] != 0) {
+    strcpy(buf, saved_jvm_path);
+    return;
+  }
+
+  Dl_info dlinfo;
+  int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
+  assert(ret != 0, "cannot locate libjvm");
+  char* rp = realpath((char *)dlinfo.dli_fname, buf);
+  assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?");
+
+  strcpy(saved_jvm_path, buf);
+}
+
+void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
+  // no prefix required, not even "_"
+}
+
+void os::print_jni_name_suffix_on(outputStream* st, int args_size) {
+  // no suffix required
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// sun.misc.Signal support
+
+static volatile jint sigint_count = 0;
+
+static void
+UserHandler(int sig, void *siginfo, void *context) {
+  // 4511530 - sem_post is serialized and handled by the manager thread. When
+  // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We
+  // don't want to flood the manager thread with sem_post requests.
+  if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1)
+    return;
+
+  // Ctrl-C is pressed during error reporting, likely because the error
+  // handler fails to abort. Let VM die immediately.
+  if (sig == SIGINT && is_error_reported()) {
+    os::die();
+  }
+
+  os::signal_notify(sig);
+}
+
+void* os::user_handler() {
+  return CAST_FROM_FN_PTR(void*, UserHandler);
+}
+
+extern "C" {
+  typedef void (*sa_handler_t)(int);
+  typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
+}
+
+void* os::signal(int signal_number, void* handler) {
+  struct sigaction sigAct, oldSigAct;
+
+  sigfillset(&(sigAct.sa_mask));
+
+  // Do not block out synchronous signals in the signal handler.
+  // Blocking synchronous signals only makes sense if you can really
+  // be sure that those signals won't happen during signal handling,
+  // when the blocking applies.  Normal signal handlers are lean and
+  // do not cause signals. But our signal handlers tend to be "risky"
+  // - secondary SIGSEGV, SIGILL, SIGBUS' may and do happen.
+  // On AIX, PASE there was a case where a SIGSEGV happened, followed
+  // by a SIGILL, which was blocked due to the signal mask. The process
+  // just hung forever. Better to crash from a secondary signal than to hang.
+  sigdelset(&(sigAct.sa_mask), SIGSEGV);
+  sigdelset(&(sigAct.sa_mask), SIGBUS);
+  sigdelset(&(sigAct.sa_mask), SIGILL);
+  sigdelset(&(sigAct.sa_mask), SIGFPE);
+  sigdelset(&(sigAct.sa_mask), SIGTRAP);
+
+  sigAct.sa_flags   = SA_RESTART|SA_SIGINFO;
+
+  sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
+
+  if (sigaction(signal_number, &sigAct, &oldSigAct)) {
+    // -1 means registration failed
+    return (void *)-1;
+  }
+
+  return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
+}
+
+void os::signal_raise(int signal_number) {
+  ::raise(signal_number);
+}
+
+//
+// The following code is moved from os.cpp for making this
+// code platform specific, which it is by its very nature.
+//
+
+// Will be modified when max signal is changed to be dynamic
+int os::sigexitnum_pd() {
+  return NSIG;
+}
+
+// a counter for each possible signal value
+static volatile jint pending_signals[NSIG+1] = { 0 };
+
+// Linux(POSIX) specific hand shaking semaphore.
+static sem_t sig_sem;
+
+void os::signal_init_pd() {
+  // Initialize signal structures
+  ::memset((void*)pending_signals, 0, sizeof(pending_signals));
+
+  // Initialize signal semaphore
+  int rc = ::sem_init(&sig_sem, 0, 0);
+  guarantee(rc != -1, "sem_init failed");
+}
+
+void os::signal_notify(int sig) {
+  Atomic::inc(&pending_signals[sig]);
+  ::sem_post(&sig_sem);
+}
+
+static int check_pending_signals(bool wait) {
+  Atomic::store(0, &sigint_count);
+  for (;;) {
+    for (int i = 0; i < NSIG + 1; i++) {
+      jint n = pending_signals[i];
+      if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
+        return i;
+      }
+    }
+    if (!wait) {
+      return -1;
+    }
+    JavaThread *thread = JavaThread::current();
+    ThreadBlockInVM tbivm(thread);
+
+    bool threadIsSuspended;
+    do {
+      thread->set_suspend_equivalent();
+      // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
+
+      ::sem_wait(&sig_sem);
+
+      // were we externally suspended while we were waiting?
+      threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
+      if (threadIsSuspended) {
+        //
+        // The semaphore has been incremented, but while we were waiting
+        // another thread suspended us. We don't want to continue running
+        // while suspended because that would surprise the thread that
+        // suspended us.
+        //
+        ::sem_post(&sig_sem);
+
+        thread->java_suspend_self();
+      }
+    } while (threadIsSuspended);
+  }
+}
+
+int os::signal_lookup() {
+  return check_pending_signals(false);
+}
+
+int os::signal_wait() {
+  return check_pending_signals(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Virtual Memory
+
+// AddrRange describes an immutable address range
+//
+// This is a helper class for the 'shared memory bookkeeping' below.
+class AddrRange {
+  friend class ShmBkBlock;
+
+  char* _start;
+  size_t _size;
+
+public:
+
+  AddrRange(char* start, size_t size)
+    : _start(start), _size(size)
+  {}
+
+  AddrRange(const AddrRange& r)
+    : _start(r.start()), _size(r.size())
+  {}
+
+  char* start() const { return _start; }
+  size_t size() const { return _size; }
+  char* end() const { return _start + _size; }
+  bool is_empty() const { return _size == 0 ? true : false; }
+
+  static AddrRange empty_range() { return AddrRange(NULL, 0); }
+
+  bool contains(const char* p) const {
+    return start() <= p && end() > p;
+  }
+
+  bool contains(const AddrRange& range) const {
+    return start() <= range.start() && end() >= range.end();
+  }
+
+  bool intersects(const AddrRange& range) const {
+    return (range.start() <= start() && range.end() > start()) ||
+           (range.start() < end() && range.end() >= end()) ||
+           contains(range);
+  }
+
+  bool is_same_range(const AddrRange& range) const {
+    return start() == range.start() && size() == range.size();
+  }
+
+  // return the closest inside range consisting of whole pages
+  AddrRange find_closest_aligned_range(size_t pagesize) const {
+    if (pagesize == 0 || is_empty()) {
+      return empty_range();
+    }
+    char* const from = (char*)align_size_up((intptr_t)_start, pagesize);
+    char* const to = (char*)align_size_down((intptr_t)end(), pagesize);
+    if (from > to) {
+      return empty_range();
+    }
+    return AddrRange(from, to - from);
+  }
+};
+
+////////////////////////////////////////////////////////////////////////////
+// shared memory bookkeeping
+//
+// the os::reserve_memory() API and friends hand out different kind of memory, depending
+// on need and circumstances. Memory may be allocated with mmap() or with shmget/shmat.
+//
+// But these memory types have to be treated differently. For example, to uncommit
+// mmap-based memory, msync(MS_INVALIDATE) is needed, to uncommit shmat-based memory,
+// disclaim64() is needed.
+//
+// Therefore we need to keep track of the allocated memory segments and their
+// properties.
+
+// ShmBkBlock: base class for all blocks in the shared memory bookkeeping
+class ShmBkBlock {
+
+  ShmBkBlock* _next;
+
+protected:
+
+  AddrRange _range;
+  const size_t _pagesize;
+  const bool _pinned;
+
+public:
+
+  ShmBkBlock(AddrRange range, size_t pagesize, bool pinned)
+    : _range(range), _pagesize(pagesize), _pinned(pinned) , _next(NULL) {
+
+    assert(_pagesize == SIZE_4K || _pagesize == SIZE_64K || _pagesize == SIZE_16M, "invalid page size");
+    assert(!_range.is_empty(), "invalid range");
+  }
+
+  virtual void print(outputStream* st) const {
+    st->print("0x%p ... 0x%p (%llu) - %d %s pages - %s",
+              _range.start(), _range.end(), _range.size(),
+              _range.size() / _pagesize, describe_pagesize(_pagesize),
+              _pinned ? "pinned" : "");
+  }
+
+  enum Type { MMAP, SHMAT };
+  virtual Type getType() = 0;
+
+  char* base() const { return _range.start(); }
+  size_t size() const { return _range.size(); }
+
+  void setAddrRange(AddrRange range) {
+    _range = range;
+  }
+
+  bool containsAddress(const char* p) const {
+    return _range.contains(p);
+  }
+
+  bool containsRange(const char* p, size_t size) const {
+    return _range.contains(AddrRange((char*)p, size));
+  }
+
+  bool isSameRange(const char* p, size_t size) const {
+    return _range.is_same_range(AddrRange((char*)p, size));
+  }
+
+  virtual bool disclaim(char* p, size_t size) = 0;
+  virtual bool release() = 0;
+
+  // blocks live in a list.
+  ShmBkBlock* next() const { return _next; }
+  void set_next(ShmBkBlock* blk) { _next = blk; }
+
+}; // end: ShmBkBlock
+
+
+// ShmBkMappedBlock: describes an block allocated with mmap()
+class ShmBkMappedBlock : public ShmBkBlock {
+public:
+
+  ShmBkMappedBlock(AddrRange range)
+    : ShmBkBlock(range, SIZE_4K, false) {} // mmap: always 4K, never pinned
+
+  void print(outputStream* st) const {
+    ShmBkBlock::print(st);
+    st->print_cr(" - mmap'ed");
+  }
+
+  Type getType() {
+    return MMAP;
+  }
+
+  bool disclaim(char* p, size_t size) {
+
+    AddrRange r(p, size);
+
+    guarantee(_range.contains(r), "invalid disclaim");
+
+    // only disclaim whole ranges.
+    const AddrRange r2 = r.find_closest_aligned_range(_pagesize);
+    if (r2.is_empty()) {
+      return true;
+    }
+
+    const int rc = ::msync(r2.start(), r2.size(), MS_INVALIDATE);
+
+    if (rc != 0) {
+      warning("msync(0x%p, %llu, MS_INVALIDATE) failed (%d)\n", r2.start(), r2.size(), errno);
+    }
+
+    return rc == 0 ? true : false;
+  }
+
+  bool release() {
+    // mmap'ed blocks are released using munmap
+    if (::munmap(_range.start(), _range.size()) != 0) {
+      warning("munmap(0x%p, %llu) failed (%d)\n", _range.start(), _range.size(), errno);
+      return false;
+    }
+    return true;
+  }
+}; // end: ShmBkMappedBlock
+
+// ShmBkShmatedBlock: describes an block allocated with shmget/shmat()
+class ShmBkShmatedBlock : public ShmBkBlock {
+public:
+
+  ShmBkShmatedBlock(AddrRange range, size_t pagesize, bool pinned)
+    : ShmBkBlock(range, pagesize, pinned) {}
+
+  void print(outputStream* st) const {
+    ShmBkBlock::print(st);
+    st->print_cr(" - shmat'ed");
+  }
+
+  Type getType() {
+    return SHMAT;
+  }
+
+  bool disclaim(char* p, size_t size) {
+
+    AddrRange r(p, size);
+
+    if (_pinned) {
+      return true;
+    }
+
+    // shmat'ed blocks are disclaimed using disclaim64
+    guarantee(_range.contains(r), "invalid disclaim");
+
+    // only disclaim whole ranges.
+    const AddrRange r2 = r.find_closest_aligned_range(_pagesize);
+    if (r2.is_empty()) {
+      return true;
+    }
+
+    const bool rc = my_disclaim64(r2.start(), r2.size());
+
+    if (Verbose && !rc) {
+      warning("failed to disclaim shm %p-%p\n", r2.start(), r2.end());
+    }
+
+    return rc;
+  }
+
+  bool release() {
+    bool rc = false;
+    if (::shmdt(_range.start()) != 0) {
+      warning("shmdt(0x%p) failed (%d)\n", _range.start(), errno);
+    } else {
+      rc = true;
+    }
+    return rc;
+  }
+
+}; // end: ShmBkShmatedBlock
+
+static ShmBkBlock* g_shmbk_list = NULL;
+static volatile jint g_shmbk_table_lock = 0;
+
+// keep some usage statistics
+static struct {
+  int nodes;    // number of nodes in list
+  size_t bytes; // reserved - not committed - bytes.
+  int reserves; // how often reserve was called
+  int lookups;  // how often a lookup was made
+} g_shmbk_stats = { 0, 0, 0, 0 };
+
+// add information about a shared memory segment to the bookkeeping
+static void shmbk_register(ShmBkBlock* p_block) {
+  guarantee(p_block, "logic error");
+  p_block->set_next(g_shmbk_list);
+  g_shmbk_list = p_block;
+  g_shmbk_stats.reserves ++;
+  g_shmbk_stats.bytes += p_block->size();
+  g_shmbk_stats.nodes ++;
+}
+
+// remove information about a shared memory segment by its starting address
+static void shmbk_unregister(ShmBkBlock* p_block) {
+  ShmBkBlock* p = g_shmbk_list;
+  ShmBkBlock* prev = NULL;
+  while (p) {
+    if (p == p_block) {
+      if (prev) {
+        prev->set_next(p->next());
+      } else {
+        g_shmbk_list = p->next();
+      }
+      g_shmbk_stats.nodes --;
+      g_shmbk_stats.bytes -= p->size();
+      return;
+    }
+    prev = p;
+    p = p->next();
+  }
+  assert(false, "should not happen");
+}
+
+// given a pointer, return shared memory bookkeeping record for the segment it points into
+// using the returned block info must happen under lock protection
+static ShmBkBlock* shmbk_find_by_containing_address(const char* addr) {
+  g_shmbk_stats.lookups ++;
+  ShmBkBlock* p = g_shmbk_list;
+  while (p) {
+    if (p->containsAddress(addr)) {
+      return p;
+    }
+    p = p->next();
+  }
+  return NULL;
+}
+
+// dump all information about all memory segments allocated with os::reserve_memory()
+void shmbk_dump_info() {
+  tty->print_cr("-- shared mem bookkeeping (alive: %d segments, %llu bytes, "
+    "total reserves: %d total lookups: %d)",
+    g_shmbk_stats.nodes, g_shmbk_stats.bytes, g_shmbk_stats.reserves, g_shmbk_stats.lookups);
+  const ShmBkBlock* p = g_shmbk_list;
+  int i = 0;
+  while (p) {
+    p->print(tty);
+    p = p->next();
+    i ++;
+  }
+}
+
+#define LOCK_SHMBK     { ThreadCritical _LOCK_SHMBK;
+#define UNLOCK_SHMBK   }
+
+// End: shared memory bookkeeping
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int os::vm_page_size() {
+  // Seems redundant as all get out
+  assert(os::Aix::page_size() != -1, "must call os::init");
+  return os::Aix::page_size();
+}
+
+// Aix allocates memory by pages.
+int os::vm_allocation_granularity() {
+  assert(os::Aix::page_size() != -1, "must call os::init");
+  return os::Aix::page_size();
+}
+
+bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
+
+  // Commit is a noop. There is no explicit commit
+  // needed on AIX. Memory is committed when touched.
+  //
+  // Debug : check address range for validity
+#ifdef ASSERT
+  LOCK_SHMBK
+    ShmBkBlock* const block = shmbk_find_by_containing_address(addr);
+    if (!block) {
+      fprintf(stderr, "invalid pointer: " INTPTR_FORMAT "\n", addr);
+      shmbk_dump_info();
+      assert(false, "invalid pointer");
+      return false;
+    } else if (!block->containsRange(addr, size)) {
+      fprintf(stderr, "invalid range: " INTPTR_FORMAT " .. " INTPTR_FORMAT "\n", addr, addr + size);
+      shmbk_dump_info();
+      assert(false, "invalid range");
+      return false;
+    }
+  UNLOCK_SHMBK
+#endif // ASSERT
+
+  return true;
+}
+
+bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, bool exec) {
+  return commit_memory(addr, size, exec);
+}
+
+bool os::pd_uncommit_memory(char* addr, size_t size) {
+
+  // Delegate to ShmBkBlock class which knows how to uncommit its memory.
+
+  bool rc = false;
+  LOCK_SHMBK
+    ShmBkBlock* const block = shmbk_find_by_containing_address(addr);
+    if (!block) {
+      fprintf(stderr, "invalid pointer: 0x%p.\n", addr);
+      shmbk_dump_info();
+      assert(false, "invalid pointer");
+      return false;
+    } else if (!block->containsRange(addr, size)) {
+      fprintf(stderr, "invalid range: 0x%p .. 0x%p.\n", addr, addr + size);
+      shmbk_dump_info();
+      assert(false, "invalid range");
+      return false;
+    }
+    rc = block->disclaim(addr, size);
+  UNLOCK_SHMBK
+
+  if (Verbose && !rc) {
+    warning("failed to disclaim 0x%p .. 0x%p (0x%llX bytes).", addr, addr + size, size);
+  }
+  return rc;
+}
+
+bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
+  return os::guard_memory(addr, size);
+}
+
+bool os::remove_stack_guard_pages(char* addr, size_t size) {
+  return os::unguard_memory(addr, size);
+}
+
+void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+}
+
+void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
+}
+
+void os::numa_make_global(char *addr, size_t bytes) {
+}
+
+void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
+}
+
+bool os::numa_topology_changed() {
+  return false;
+}
+
+size_t os::numa_get_groups_num() {
+  return 1;
+}
+
+int os::numa_get_group_id() {
+  return 0;
+}
+
+size_t os::numa_get_leaf_groups(int *ids, size_t size) {
+  if (size > 0) {
+    ids[0] = 0;
+    return 1;
+  }
+  return 0;
+}
+
+bool os::get_page_info(char *start, page_info* info) {
+  return false;
+}
+
+char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) {
+  return end;
+}
+
+// Flags for reserve_shmatted_memory:
+#define RESSHM_WISHADDR_OR_FAIL                     1
+#define RESSHM_TRY_16M_PAGES                        2
+#define RESSHM_16M_PAGES_OR_FAIL                    4
+
+// Result of reserve_shmatted_memory:
+struct shmatted_memory_info_t {
+  char* addr;
+  size_t pagesize;
+  bool pinned;
+};
+
+// Reserve a section of shmatted memory.
+// params:
+// bytes [in]: size of memory, in bytes
+// requested_addr [in]: wish address.
+//                      NULL = no wish.
+//                      If RESSHM_WISHADDR_OR_FAIL is set in flags and wish address cannot
+//                      be obtained, function will fail. Otherwise wish address is treated as hint and
+//                      another pointer is returned.
+// flags [in]:          some flags. Valid flags are:
+//                      RESSHM_WISHADDR_OR_FAIL - fail if wish address is given and cannot be obtained.
+//                      RESSHM_TRY_16M_PAGES - try to allocate from 16M page pool
+//                          (requires UseLargePages and Use16MPages)
+//                      RESSHM_16M_PAGES_OR_FAIL - if you cannot allocate from 16M page pool, fail.
+//                          Otherwise any other page size will do.
+// p_info [out] :       holds information about the created shared memory segment.
+static bool reserve_shmatted_memory(size_t bytes, char* requested_addr, int flags, shmatted_memory_info_t* p_info) {
+
+  assert(p_info, "parameter error");
+
+  // init output struct.
+  p_info->addr = NULL;
+
+  // neither should we be here for EXTSHM=ON.
+  if (os::Aix::extshm()) {
+    ShouldNotReachHere();
+  }
+
+  // extract flags. sanity checks.
+  const bool wishaddr_or_fail =
+    flags & RESSHM_WISHADDR_OR_FAIL;
+  const bool try_16M_pages =
+    flags & RESSHM_TRY_16M_PAGES;
+  const bool f16M_pages_or_fail =
+    flags & RESSHM_16M_PAGES_OR_FAIL;
+
+  // first check: if a wish address is given and it is mandatory, but not aligned to segment boundary,
+  // shmat will fail anyway, so save some cycles by failing right away
+  if (requested_addr && ((uintptr_t)requested_addr % SIZE_256M == 0)) {
+    if (wishaddr_or_fail) {
+      return false;
+    } else {
+      requested_addr = NULL;
+    }
+  }
+
+  char* addr = NULL;
+
+  // Align size of shm up to the largest possible page size, to avoid errors later on when we try to change
+  // pagesize dynamically.
+  const size_t size = align_size_up(bytes, SIZE_16M);
+
+  // reserve the shared segment
+  int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRUSR | S_IWUSR);
+  if (shmid == -1) {
+    warning("shmget(.., %lld, ..) failed (errno: %d).", size, errno);
+    return false;
+  }
+
+  // Important note:
+  // It is very important that we, upon leaving this function, do not leave a shm segment alive.
+  // We must right after attaching it remove it from the system. System V shm segments are global and
+  // survive the process.
+  // So, from here on: Do not assert. Do not return. Always do a "goto cleanup_shm".
+
+  // try forcing the page size
+  size_t pagesize = -1; // unknown so far
+
+  if (UseLargePages) {
+
+    struct shmid_ds shmbuf;
+    memset(&shmbuf, 0, sizeof(shmbuf));
+
+    // First, try to take from 16M page pool if...
+    if (os::Aix::can_use_16M_pages()  // we can ...
+        && Use16MPages                // we are not explicitly forbidden to do so (-XX:-Use16MPages)..
+        && try_16M_pages) {           // caller wants us to.
+      shmbuf.shm_pagesize = SIZE_16M;
+      if (shmctl(shmid, SHM_PAGESIZE, &shmbuf) == 0) {
+        pagesize = SIZE_16M;
+      } else {
+        warning("Failed to allocate %d 16M pages. 16M page pool might be exhausted. (shmctl failed with %d)",
+                size / SIZE_16M, errno);
+        if (f16M_pages_or_fail) {
+          goto cleanup_shm;
+        }
+      }
+    }
+
+    // Nothing yet? Try setting 64K pages. Note that I never saw this fail, but in theory it might,
+    // because the 64K page pool may also be exhausted.
+    if (pagesize == -1) {
+      shmbuf.shm_pagesize = SIZE_64K;
+      if (shmctl(shmid, SHM_PAGESIZE, &shmbuf) == 0) {
+        pagesize = SIZE_64K;
+      } else {
+        warning("Failed to allocate %d 64K pages. (shmctl failed with %d)",
+                size / SIZE_64K, errno);
+        // here I give up. leave page_size -1 - later, after attaching, we will query the
+        // real page size of the attached memory. (in theory, it may be something different
+        // from 4K if LDR_CNTRL SHM_PSIZE is set)
+      }
+    }
+  }
+
+  // sanity point
+  assert(pagesize == -1 || pagesize == SIZE_16M || pagesize == SIZE_64K, "wrong page size");
+
+  // Now attach the shared segment.
+  addr = (char*) shmat(shmid, requested_addr, 0);
+  if (addr == (char*)-1) {
+    // How to handle attach failure:
+    // If it failed for a specific wish address, tolerate this: in that case, if wish address was
+    // mandatory, fail, if not, retry anywhere.
+    // If it failed for any other reason, treat that as fatal error.
+    addr = NULL;
+    if (requested_addr) {
+      if (wishaddr_or_fail) {
+        goto cleanup_shm;
+      } else {
+        addr = (char*) shmat(shmid, NULL, 0);
+        if (addr == (char*)-1) { // fatal
+          addr = NULL;
+          warning("shmat failed (errno: %d)", errno);
+          goto cleanup_shm;
+        }
+      }
+    } else { // fatal
+      addr = NULL;
+      warning("shmat failed (errno: %d)", errno);
+      goto cleanup_shm;
+    }
+  }
+
+  // sanity point
+  assert(addr && addr != (char*) -1, "wrong address");
+
+  // after successful Attach remove the segment - right away.
+  if (::shmctl(shmid, IPC_RMID, NULL) == -1) {
+    warning("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno);
+    guarantee(false, "failed to remove shared memory segment!");
+  }
+  shmid = -1;
+
+  // query the real page size. In case setting the page size did not work (see above), the system
+  // may have given us something other then 4K (LDR_CNTRL)
+  {
+    const size_t real_pagesize = os::Aix::query_pagesize(addr);
+    if (pagesize != -1) {
+      assert(pagesize == real_pagesize, "unexpected pagesize after shmat");
+    } else {
+      pagesize = real_pagesize;
+    }
+  }
+
+  // Now register the reserved block with internal book keeping.
+  LOCK_SHMBK
+    const bool pinned = pagesize >= SIZE_16M ? true : false;
+    ShmBkShmatedBlock* const p_block = new ShmBkShmatedBlock(AddrRange(addr, size), pagesize, pinned);
+    assert(p_block, "");
+    shmbk_register(p_block);
+  UNLOCK_SHMBK
+
+cleanup_shm:
+
+  // if we have not done so yet, remove the shared memory segment. This is very important.
+  if (shmid != -1) {
+    if (::shmctl(shmid, IPC_RMID, NULL) == -1) {
+      warning("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno);
+      guarantee(false, "failed to remove shared memory segment!");
+    }
+    shmid = -1;
+  }
+
+  // trace
+  if (Verbose && !addr) {
+    if (requested_addr != NULL) {
+      warning("failed to shm-allocate 0x%llX bytes at with address 0x%p.", size, requested_addr);
+    } else {
+      warning("failed to shm-allocate 0x%llX bytes at any address.", size);
+    }
+  }
+
+  // hand info to caller
+  if (addr) {
+    p_info->addr = addr;
+    p_info->pagesize = pagesize;
+    p_info->pinned = pagesize == SIZE_16M ? true : false;
+  }
+
+  // sanity test:
+  if (requested_addr && addr && wishaddr_or_fail) {
+    guarantee(addr == requested_addr, "shmat error");
+  }
+
+  // just one more test to really make sure we have no dangling shm segments.
+  guarantee(shmid == -1, "dangling shm segments");
+
+  return addr ? true : false;
+
+} // end: reserve_shmatted_memory
+
+// Reserve memory using mmap. Behaves the same as reserve_shmatted_memory():
+// will return NULL in case of an error.
+static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) {
+
+  // if a wish address is given, but not aligned to 4K page boundary, mmap will fail.
+  if (requested_addr && ((uintptr_t)requested_addr % os::vm_page_size() != 0)) {
+    warning("Wish address 0x%p not aligned to page boundary.", requested_addr);
+    return NULL;
+  }
+
+  const size_t size = align_size_up(bytes, SIZE_4K);
+
+  // Note: MAP_SHARED (instead of MAP_PRIVATE) needed to be able to
+  // msync(MS_INVALIDATE) (see os::uncommit_memory)
+  int flags = MAP_ANONYMOUS | MAP_SHARED;
+
+  // MAP_FIXED is needed to enforce requested_addr - manpage is vague about what
+  // it means if wishaddress is given but MAP_FIXED is not set.
+  //
+  // Note however that this changes semantics in SPEC1170 mode insofar as MAP_FIXED
+  // clobbers the address range, which is probably not what the caller wants. That's
+  // why I assert here (again) that the SPEC1170 compat mode is off.
+  // If we want to be able to run under SPEC1170, we have to do some porting and
+  // testing.
+  if (requested_addr != NULL) {
+    assert(!os::Aix::xpg_sus_mode(), "SPEC1170 mode not allowed.");
+    flags |= MAP_FIXED;
+  }
+
+  char* addr = (char*)::mmap(requested_addr, size, PROT_READ|PROT_WRITE|PROT_EXEC, flags, -1, 0);
+
+  if (addr == MAP_FAILED) {
+    // attach failed: tolerate for specific wish addresses. Not being able to attach
+    // anywhere is a fatal error.
+    if (requested_addr == NULL) {
+      // It's ok to fail here if the machine has not enough memory.
+      warning("mmap(NULL, 0x%llX, ..) failed (%d)", size, errno);
+    }
+    addr = NULL;
+    goto cleanup_mmap;
+  }
+
+  // If we did request a specific address and that address was not available, fail.
+  if (addr && requested_addr) {
+    guarantee(addr == requested_addr, "unexpected");
+  }
+
+  // register this mmap'ed segment with book keeping
+  LOCK_SHMBK
+    ShmBkMappedBlock* const p_block = new ShmBkMappedBlock(AddrRange(addr, size));
+    assert(p_block, "");
+    shmbk_register(p_block);
+  UNLOCK_SHMBK
+
+cleanup_mmap:
+
+  if (addr) {
+    if (Verbose) {
+      fprintf(stderr, "mmap-allocated 0x%p .. 0x%p (0x%llX bytes)\n", addr, addr + bytes, bytes);
+    }
+  }
+  else {
+    if (requested_addr != NULL) {
+      warning("failed to mmap-allocate 0x%llX bytes at wish address 0x%p.", bytes, requested_addr);
+    } else {
+      warning("failed to mmap-allocate 0x%llX bytes at any address.", bytes);
+    }
+  }
+
+  return addr;
+
+} // end: reserve_mmaped_memory
+
+// Reserves and attaches a shared memory segment.
+// Will assert if a wish address is given and could not be obtained.
+char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
+  return os::attempt_reserve_memory_at(bytes, requested_addr);
+}
+
+bool os::pd_release_memory(char* addr, size_t size) {
+
+  // delegate to ShmBkBlock class which knows how to uncommit its memory.
+
+  bool rc = false;
+  LOCK_SHMBK
+    ShmBkBlock* const block = shmbk_find_by_containing_address(addr);
+    if (!block) {
+      fprintf(stderr, "invalid pointer: 0x%p.\n", addr);
+      shmbk_dump_info();
+      assert(false, "invalid pointer");
+      return false;
+    }
+    else if (!block->isSameRange(addr, size)) {
+      if (block->getType() == ShmBkBlock::MMAP) {
+        // Release only the same range or a the beginning or the end of a range.
+        if (block->base() == addr && size < block->size()) {
+          ShmBkMappedBlock* const b = new ShmBkMappedBlock(AddrRange(block->base() + size, block->size() - size));
+          assert(b, "");
+          shmbk_register(b);
+          block->setAddrRange(AddrRange(addr, size));
+        }
+        else if (addr > block->base() && addr + size == block->base() + block->size()) {
+          ShmBkMappedBlock* const b = new ShmBkMappedBlock(AddrRange(block->base(), block->size() - size));
+          assert(b, "");
+          shmbk_register(b);
+          block->setAddrRange(AddrRange(addr, size));
+        }
+        else {
+          fprintf(stderr, "invalid mmap range: 0x%p .. 0x%p.\n", addr, addr + size);
+          shmbk_dump_info();
+          assert(false, "invalid mmap range");
+          return false;
+        }
+      }
+      else {
+        // Release only the same range. No partial release allowed.
+        // Soften the requirement a bit, because the user may think he owns a smaller size
+        // than the block is due to alignment etc.
+        if (block->base() != addr || block->size() < size) {
+          fprintf(stderr, "invalid shmget range: 0x%p .. 0x%p.\n", addr, addr + size);
+          shmbk_dump_info();
+          assert(false, "invalid shmget range");
+          return false;
+        }
+      }
+    }
+    rc = block->release();
+    assert(rc, "release failed");
+    // remove block from bookkeeping
+    shmbk_unregister(block);
+    delete block;
+  UNLOCK_SHMBK
+
+  if (!rc) {
+    warning("failed to released %lu bytes at 0x%p", size, addr);
+  }
+
+  return rc;
+}
+
+static bool checked_mprotect(char* addr, size_t size, int prot) {
+
+  // Little problem here: if SPEC1170 behaviour is off, mprotect() on AIX will
+  // not tell me if protection failed when trying to protect an un-protectable range.
+  //
+  // This means if the memory was allocated using shmget/shmat, protection wont work
+  // but mprotect will still return 0:
+  //
+  // See http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/mprotect.htm
+
+  bool rc = ::mprotect(addr, size, prot) == 0 ? true : false;
+
+  if (!rc) {
+    const char* const s_errno = strerror(errno);
+    warning("mprotect(" PTR_FORMAT "-" PTR_FORMAT ", 0x%X) failed (%s).", addr, addr + size, prot, s_errno);
+    return false;
+  }
+
+  // mprotect success check
+  //
+  // Mprotect said it changed the protection but can I believe it?
+  //
+  // To be sure I need to check the protection afterwards. Try to
+  // read from protected memory and check whether that causes a segfault.
+  //
+  if (!os::Aix::xpg_sus_mode()) {
+
+    if (StubRoutines::SafeFetch32_stub()) {
+
+      const bool read_protected =
+        (SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
+         SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
+
+      if (prot & PROT_READ) {
+        rc = !read_protected;
+      } else {
+        rc = read_protected;
+      }
+    }
+  }
+  if (!rc) {
+    assert(false, "mprotect failed.");
+  }
+  return rc;
+}
+
+// Set protections specified
+bool os::protect_memory(char* addr, size_t size, ProtType prot, bool is_committed) {
+  unsigned int p = 0;
+  switch (prot) {
+  case MEM_PROT_NONE: p = PROT_NONE; break;
+  case MEM_PROT_READ: p = PROT_READ; break;
+  case MEM_PROT_RW:   p = PROT_READ|PROT_WRITE; break;
+  case MEM_PROT_RWX:  p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
+  default:
+    ShouldNotReachHere();
+  }
+  // is_committed is unused.
+  return checked_mprotect(addr, size, p);
+}
+
+bool os::guard_memory(char* addr, size_t size) {
+  return checked_mprotect(addr, size, PROT_NONE);
+}
+
+bool os::unguard_memory(char* addr, size_t size) {
+  return checked_mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC);
+}
+
+// Large page support
+
+static size_t _large_page_size = 0;
+
+// Enable large page support if OS allows that.
+void os::large_page_init() {
+
+  // Note: os::Aix::query_multipage_support must run first.
+
+  if (!UseLargePages) {
+    return;
+  }
+
+  if (!Aix::can_use_64K_pages()) {
+    assert(!Aix::can_use_16M_pages(), "64K is a precondition for 16M.");
+    UseLargePages = false;
+    return;
+  }
+
+  if (!Aix::can_use_16M_pages() && Use16MPages) {
+    fprintf(stderr, "Cannot use 16M pages. Please ensure that there is a 16M page pool "
+            " and that the VM runs with CAP_BYPASS_RAC_VMM and CAP_PROPAGATE capabilities.\n");
+  }
+
+  // Do not report 16M page alignment as part of os::_page_sizes if we are
+  // explicitly forbidden from using 16M pages. Doing so would increase the
+  // alignment the garbage collector calculates with, slightly increasing
+  // heap usage. We should only pay for 16M alignment if we really want to
+  // use 16M pages.
+  if (Use16MPages && Aix::can_use_16M_pages()) {
+    _large_page_size = SIZE_16M;
+    _page_sizes[0] = SIZE_16M;
+    _page_sizes[1] = SIZE_64K;
+    _page_sizes[2] = SIZE_4K;
+    _page_sizes[3] = 0;
+  } else if (Aix::can_use_64K_pages()) {
+    _large_page_size = SIZE_64K;
+    _page_sizes[0] = SIZE_64K;
+    _page_sizes[1] = SIZE_4K;
+    _page_sizes[2] = 0;
+  }
+
+  if (Verbose) {
+    ("Default large page size is 0x%llX.", _large_page_size);
+  }
+} // end: os::large_page_init()
+
+char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
+  // "exec" is passed in but not used. Creating the shared image for
+  // the code cache doesn't have an SHM_X executable permission to check.
+  Unimplemented();
+  return 0;
+}
+
+bool os::release_memory_special(char* base, size_t bytes) {
+  // detaching the SHM segment will also delete it, see reserve_memory_special()
+  Unimplemented();
+  return false;
+}
+
+size_t os::large_page_size() {
+  return _large_page_size;
+}
+
+bool os::can_commit_large_page_memory() {
+  // Well, sadly we cannot commit anything at all (see comment in
+  // os::commit_memory) but we claim to so we can make use of large pages
+  return true;
+}
+
+bool os::can_execute_large_page_memory() {
+  // We can do that
+  return true;
+}
+
+// Reserve memory at an arbitrary address, only if that area is
+// available (and not reserved for something else).
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+
+  bool use_mmap = false;
+
+  // mmap: smaller graining, no large page support
+  // shm: large graining (256M), large page support, limited number of shm segments
+  //
+  // Prefer mmap wherever we either do not need large page support or have OS limits
+
+  if (!UseLargePages || bytes < SIZE_16M) {
+    use_mmap = true;
+  }
+
+  char* addr = NULL;
+  if (use_mmap) {
+    addr = reserve_mmaped_memory(bytes, requested_addr);
+  } else {
+    // shmat: wish address is mandatory, and do not try 16M pages here.
+    shmatted_memory_info_t info;
+    const int flags = RESSHM_WISHADDR_OR_FAIL;
+    if (reserve_shmatted_memory(bytes, requested_addr, flags, &info)) {
+      addr = info.addr;
+    }
+  }
+
+  return addr;
+}
+
+size_t os::read(int fd, void *buf, unsigned int nBytes) {
+  return ::read(fd, buf, nBytes);
+}
+
+#define NANOSECS_PER_MILLISEC 1000000
+
+int os::sleep(Thread* thread, jlong millis, bool interruptible) {
+  assert(thread == Thread::current(), "thread consistency check");
+
+  // Prevent nasty overflow in deadline calculation
+  // by handling long sleeps similar to solaris or windows.
+  const jlong limit = INT_MAX;
+  int result;
+  while (millis > limit) {
+    if ((result = os::sleep(thread, limit, interruptible)) != OS_OK) {
+      return result;
+    }
+    millis -= limit;
+  }
+
+  ParkEvent * const slp = thread->_SleepEvent;
+  slp->reset();
+  OrderAccess::fence();
+
+  if (interruptible) {
+    jlong prevtime = javaTimeNanos();
+
+    // Prevent precision loss and too long sleeps
+    jlong deadline = prevtime + millis * NANOSECS_PER_MILLISEC;
+
+    for (;;) {
+      if (os::is_interrupted(thread, true)) {
+        return OS_INTRPT;
+      }
+
+      jlong newtime = javaTimeNanos();
+
+      assert(newtime >= prevtime, "time moving backwards");
+      // Doing prevtime and newtime in microseconds doesn't help precision,
+      // and trying to round up to avoid lost milliseconds can result in a
+      // too-short delay.
+      millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
+
+      if (millis <= 0) {
+        return OS_OK;
+      }
+
+      // Stop sleeping if we passed the deadline
+      if (newtime >= deadline) {
+        return OS_OK;
+      }
+
+      prevtime = newtime;
+
+      {
+        assert(thread->is_Java_thread(), "sanity check");
+        JavaThread *jt = (JavaThread *) thread;
+        ThreadBlockInVM tbivm(jt);
+        OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
+
+        jt->set_suspend_equivalent();
+
+        slp->park(millis);
+
+        // were we externally suspended while we were waiting?
+        jt->check_and_wait_while_suspended();
+      }
+    }
+  } else {
+    OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+    jlong prevtime = javaTimeNanos();
+
+    // Prevent precision loss and too long sleeps
+    jlong deadline = prevtime + millis * NANOSECS_PER_MILLISEC;
+
+    for (;;) {
+      // It'd be nice to avoid the back-to-back javaTimeNanos() calls on
+      // the 1st iteration ...
+      jlong newtime = javaTimeNanos();
+
+      if (newtime - prevtime < 0) {
+        // time moving backwards, should only happen if no monotonic clock
+        // not a guarantee() because JVM should not abort on kernel/glibc bugs
+        // - HS14 Commented out as not implemented.
+        // - TODO Maybe we should implement it?
+        //assert(!Aix::supports_monotonic_clock(), "time moving backwards");
+      } else {
+        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
+      }
+
+      if (millis <= 0) break;
+
+      if (newtime >= deadline) {
+        break;
+      }
+
+      prevtime = newtime;
+      slp->park(millis);
+    }
+    return OS_OK;
+  }
+}
+
+int os::naked_sleep() {
+  // %% make the sleep time an integer flag. for now use 1 millisec.
+  return os::sleep(Thread::current(), 1, false);
+}
+
+// Sleep forever; naked call to OS-specific sleep; use with CAUTION
+void os::infinite_sleep() {
+  while (true) {    // sleep forever ...
+    ::sleep(100);   // ... 100 seconds at a time
+  }
+}
+
+// Used to convert frequent JVM_Yield() to nops
+bool os::dont_yield() {
+  return DontYieldALot;
+}
+
+void os::yield() {
+  sched_yield();
+}
+
+os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN; }
+
+void os::yield_all(int attempts) {
+  // Yields to all threads, including threads with lower priorities
+  // Threads on Linux are all with same priority. The Solaris style
+  // os::yield_all() with nanosleep(1ms) is not necessary.
+  sched_yield();
+}
+
+// Called from the tight loops to possibly influence time-sharing heuristics
+void os::loop_breaker(int attempts) {
+  os::yield_all(attempts);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// thread priority support
+
+// From AIX manpage to pthread_setschedparam
+// (see: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?
+//    topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_setschedparam.htm):
+//
+// "If schedpolicy is SCHED_OTHER, then sched_priority must be in the
+// range from 40 to 80, where 40 is the least favored priority and 80
+// is the most favored."
+//
+// (Actually, I doubt this even has an impact on AIX, as we do kernel
+// scheduling there; however, this still leaves iSeries.)
+//
+// We use the same values for AIX and PASE.
+int os::java_to_os_priority[CriticalPriority + 1] = {
+  54,             // 0 Entry should never be used
+
+  55,             // 1 MinPriority
+  55,             // 2
+  56,             // 3
+
+  56,             // 4
+  57,             // 5 NormPriority
+  57,             // 6
+
+  58,             // 7
+  58,             // 8
+  59,             // 9 NearMaxPriority
+
+  60,             // 10 MaxPriority
+
+  60              // 11 CriticalPriority
+};
+
+OSReturn os::set_native_priority(Thread* thread, int newpri) {
+  if (!UseThreadPriorities) return OS_OK;
+  pthread_t thr = thread->osthread()->pthread_id();
+  int policy = SCHED_OTHER;
+  struct sched_param param;
+  param.sched_priority = newpri;
+  int ret = pthread_setschedparam(thr, policy, &param);
+
+  if (Verbose) {
+    if (ret == 0) {
+      fprintf(stderr, "changed priority of thread %d to %d\n", (int)thr, newpri);
+    } else {
+      fprintf(stderr, "Could not changed priority for thread %d to %d (error %d, %s)\n",
+              (int)thr, newpri, ret, strerror(ret));
+    }
+  }
+  return (ret == 0) ? OS_OK : OS_ERR;
+}
+
+OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) {
+  if (!UseThreadPriorities) {
+    *priority_ptr = java_to_os_priority[NormPriority];
+    return OS_OK;
+  }
+  pthread_t thr = thread->osthread()->pthread_id();
+  int policy = SCHED_OTHER;
+  struct sched_param param;
+  int ret = pthread_getschedparam(thr, &policy, &param);
+  *priority_ptr = param.sched_priority;
+
+  return (ret == 0) ? OS_OK : OS_ERR;
+}
+
+// Hint to the underlying OS that a task switch would not be good.
+// Void return because it's a hint and can fail.
+void os::hint_no_preempt() {}
+
+////////////////////////////////////////////////////////////////////////////////
+// suspend/resume support
+
+//  the low-level signal-based suspend/resume support is a remnant from the
+//  old VM-suspension that used to be for java-suspension, safepoints etc,
+//  within hotspot. Now there is a single use-case for this:
+//    - calling get_thread_pc() on the VMThread by the flat-profiler task
+//      that runs in the watcher thread.
+//  The remaining code is greatly simplified from the more general suspension
+//  code that used to be used.
+//
+//  The protocol is quite simple:
+//  - suspend:
+//      - sends a signal to the target thread
+//      - polls the suspend state of the osthread using a yield loop
+//      - target thread signal handler (SR_handler) sets suspend state
+//        and blocks in sigsuspend until continued
+//  - resume:
+//      - sets target osthread state to continue
+//      - sends signal to end the sigsuspend loop in the SR_handler
+//
+//  Note that the SR_lock plays no role in this suspend/resume protocol.
+//
+
+static void resume_clear_context(OSThread *osthread) {
+  osthread->set_ucontext(NULL);
+  osthread->set_siginfo(NULL);
+}
+
+static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) {
+  osthread->set_ucontext(context);
+  osthread->set_siginfo(siginfo);
+}
+
+//
+// Handler function invoked when a thread's execution is suspended or
+// resumed. We have to be careful that only async-safe functions are
+// called here (Note: most pthread functions are not async safe and
+// should be avoided.)
+//
+// Note: sigwait() is a more natural fit than sigsuspend() from an
+// interface point of view, but sigwait() prevents the signal hander
+// from being run. libpthread would get very confused by not having
+// its signal handlers run and prevents sigwait()'s use with the
+// mutex granting granting signal.
+//
+// Currently only ever called on the VMThread and JavaThreads (PC sampling).
+//
+static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
+  // Save and restore errno to avoid confusing native code with EINTR
+  // after sigsuspend.
+  int old_errno = errno;
+
+  Thread* thread = Thread::current();
+  OSThread* osthread = thread->osthread();
+  assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+
+  os::SuspendResume::State current = osthread->sr.state();
+  if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
+    suspend_save_context(osthread, siginfo, context);
+
+    // attempt to switch the state, we assume we had a SUSPEND_REQUEST
+    os::SuspendResume::State state = osthread->sr.suspended();
+    if (state == os::SuspendResume::SR_SUSPENDED) {
+      sigset_t suspend_set;  // signals for sigsuspend()
+
+      // get current set of blocked signals and unblock resume signal
+      pthread_sigmask(SIG_BLOCK, NULL, &suspend_set);
+      sigdelset(&suspend_set, SR_signum);
+
+      // wait here until we are resumed
+      while (1) {
+        sigsuspend(&suspend_set);
+
+        os::SuspendResume::State result = osthread->sr.running();
+        if (result == os::SuspendResume::SR_RUNNING) {
+          break;
+        }
+      }
+
+    } else if (state == os::SuspendResume::SR_RUNNING) {
+      // request was cancelled, continue
+    } else {
+      ShouldNotReachHere();
+    }
+
+    resume_clear_context(osthread);
+  } else if (current == os::SuspendResume::SR_RUNNING) {
+    // request was cancelled, continue
+  } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) {
+    // ignore
+  } else {
+    ShouldNotReachHere();
+  }
+
+  errno = old_errno;
+}
+
+
+static int SR_initialize() {
+  struct sigaction act;
+  char *s;
+  // Get signal number to use for suspend/resume
+  if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) {
+    int sig = ::strtol(s, 0, 10);
+    if (sig > 0 || sig < NSIG) {
+      SR_signum = sig;
+    }
+  }
+
+  assert(SR_signum > SIGSEGV && SR_signum > SIGBUS,
+        "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769");
+
+  sigemptyset(&SR_sigset);
+  sigaddset(&SR_sigset, SR_signum);
+
+  // Set up signal handler for suspend/resume.
+  act.sa_flags = SA_RESTART|SA_SIGINFO;
+  act.sa_handler = (void (*)(int)) SR_handler;
+
+  // SR_signum is blocked by default.
+  // 4528190 - We also need to block pthread restart signal (32 on all
+  // supported Linux platforms). Note that LinuxThreads need to block
+  // this signal for all threads to work properly. So we don't have
+  // to use hard-coded signal number when setting up the mask.
+  pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask);
+
+  if (sigaction(SR_signum, &act, 0) == -1) {
+    return -1;
+  }
+
+  // Save signal flag
+  os::Aix::set_our_sigflags(SR_signum, act.sa_flags);
+  return 0;
+}
+
+static int SR_finalize() {
+  return 0;
+}
+
+static int sr_notify(OSThread* osthread) {
+  int status = pthread_kill(osthread->pthread_id(), SR_signum);
+  assert_status(status == 0, status, "pthread_kill");
+  return status;
+}
+
+// "Randomly" selected value for how long we want to spin
+// before bailing out on suspending a thread, also how often
+// we send a signal to a thread we want to resume
+static const int RANDOMLY_LARGE_INTEGER = 1000000;
+static const int RANDOMLY_LARGE_INTEGER2 = 100;
+
+// returns true on success and false on error - really an error is fatal
+// but this seems the normal response to library errors
+static bool do_suspend(OSThread* osthread) {
+  assert(osthread->sr.is_running(), "thread should be running");
+  // mark as suspended and send signal
+
+  if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
+    // failed to switch, state wasn't running?
+    ShouldNotReachHere();
+    return false;
+  }
+
+  if (sr_notify(osthread) != 0) {
+    // try to cancel, switch to running
+
+    os::SuspendResume::State result = osthread->sr.cancel_suspend();
+    if (result == os::SuspendResume::SR_RUNNING) {
+      // cancelled
+      return false;
+    } else if (result == os::SuspendResume::SR_SUSPENDED) {
+      // somehow managed to suspend
+      return true;
+    } else {
+      ShouldNotReachHere();
+      return false;
+    }
+  }
+
+  // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
+
+  for (int n = 0; !osthread->sr.is_suspended(); n++) {
+    for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) {
+      os::yield_all(i);
+    }
+
+    // timeout, try to cancel the request
+    if (n >= RANDOMLY_LARGE_INTEGER) {
+      os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
+      if (cancelled == os::SuspendResume::SR_RUNNING) {
+        return false;
+      } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
+        return true;
+      } else {
+        ShouldNotReachHere();
+        return false;
+      }
+    }
+  }
+
+  guarantee(osthread->sr.is_suspended(), "Must be suspended");
+  return true;
+}
+
+static void do_resume(OSThread* osthread) {
+  //assert(osthread->sr.is_suspended(), "thread should be suspended");
+
+  if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
+    // failed to switch to WAKEUP_REQUEST
+    ShouldNotReachHere();
+    return;
+  }
+
+  while (!osthread->sr.is_running()) {
+    if (sr_notify(osthread) == 0) {
+      for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) {
+        for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) {
+          os::yield_all(i);
+        }
+      }
+    } else {
+      ShouldNotReachHere();
+    }
+  }
+
+  guarantee(osthread->sr.is_running(), "Must be running!");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// interrupt support
+
+void os::interrupt(Thread* thread) {
+  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
+    "possibility of dangling Thread pointer");
+
+  OSThread* osthread = thread->osthread();
+
+  if (!osthread->interrupted()) {
+    osthread->set_interrupted(true);
+    // More than one thread can get here with the same value of osthread,
+    // resulting in multiple notifications.  We do, however, want the store
+    // to interrupted() to be visible to other threads before we execute unpark().
+    OrderAccess::fence();
+    ParkEvent * const slp = thread->_SleepEvent;
+    if (slp != NULL) slp->unpark();
+  }
+
+  // For JSR166. Unpark even if interrupt status already was set
+  if (thread->is_Java_thread())
+    ((JavaThread*)thread)->parker()->unpark();
+
+  ParkEvent * ev = thread->_ParkEvent;
+  if (ev != NULL) ev->unpark();
+
+}
+
+bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
+  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
+    "possibility of dangling Thread pointer");
+
+  OSThread* osthread = thread->osthread();
+
+  bool interrupted = osthread->interrupted();
+
+  if (interrupted && clear_interrupted) {
+    osthread->set_interrupted(false);
+    // consider thread->_SleepEvent->reset() ... optional optimization
+  }
+
+  return interrupted;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+// signal handling (except suspend/resume)
+
+// This routine may be used by user applications as a "hook" to catch signals.
+// The user-defined signal handler must pass unrecognized signals to this
+// routine, and if it returns true (non-zero), then the signal handler must
+// return immediately. If the flag "abort_if_unrecognized" is true, then this
+// routine will never retun false (zero), but instead will execute a VM panic
+// routine kill the process.
+//
+// If this routine returns false, it is OK to call it again. This allows
+// the user-defined signal handler to perform checks either before or after
+// the VM performs its own checks. Naturally, the user code would be making
+// a serious error if it tried to handle an exception (such as a null check
+// or breakpoint) that the VM was generating for its own correct operation.
+//
+// This routine may recognize any of the following kinds of signals:
+//   SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1.
+// It should be consulted by handlers for any of those signals.
+//
+// The caller of this routine must pass in the three arguments supplied
+// to the function referred to in the "sa_sigaction" (not the "sa_handler")
+// field of the structure passed to sigaction(). This routine assumes that
+// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
+//
+// Note that the VM will print warnings if it detects conflicting signal
+// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
+//
+extern "C" JNIEXPORT int
+JVM_handle_aix_signal(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized);
+
+// Set thread signal mask (for some reason on AIX sigthreadmask() seems
+// to be the thing to call; documentation is not terribly clear about whether
+// pthread_sigmask also works, and if it does, whether it does the same.
+bool set_thread_signal_mask(int how, const sigset_t* set, sigset_t* oset) {
+  const int rc = ::pthread_sigmask(how, set, oset);
+  // return value semantics differ slightly for error case:
+  // pthread_sigmask returns error number, sigthreadmask -1 and sets global errno
+  // (so, pthread_sigmask is more theadsafe for error handling)
+  // But success is always 0.
+  return rc == 0 ? true : false;
+}
+
+// Function to unblock all signals which are, according
+// to POSIX, typical program error signals. If they happen while being blocked,
+// they typically will bring down the process immediately.
+bool unblock_program_error_signals() {
+  sigset_t set;
+  ::sigemptyset(&set);
+  ::sigaddset(&set, SIGILL);
+  ::sigaddset(&set, SIGBUS);
+  ::sigaddset(&set, SIGFPE);
+  ::sigaddset(&set, SIGSEGV);
+  return set_thread_signal_mask(SIG_UNBLOCK, &set, NULL);
+}
+
+// Renamed from 'signalHandler' to avoid collision with other shared libs.
+void javaSignalHandler(int sig, siginfo_t* info, void* uc) {
+  assert(info != NULL && uc != NULL, "it must be old kernel");
+
+  // Never leave program error signals blocked;
+  // on all our platforms they would bring down the process immediately when
+  // getting raised while being blocked.
+  unblock_program_error_signals();
+
+  JVM_handle_aix_signal(sig, info, uc, true);
+}
+
+
+// This boolean allows users to forward their own non-matching signals
+// to JVM_handle_aix_signal, harmlessly.
+bool os::Aix::signal_handlers_are_installed = false;
+
+// For signal-chaining
+struct sigaction os::Aix::sigact[MAXSIGNUM];
+unsigned int os::Aix::sigs = 0;
+bool os::Aix::libjsig_is_loaded = false;
+typedef struct sigaction *(*get_signal_t)(int);
+get_signal_t os::Aix::get_signal_action = NULL;
+
+struct sigaction* os::Aix::get_chained_signal_action(int sig) {
+  struct sigaction *actp = NULL;
+
+  if (libjsig_is_loaded) {
+    // Retrieve the old signal handler from libjsig
+    actp = (*get_signal_action)(sig);
+  }
+  if (actp == NULL) {
+    // Retrieve the preinstalled signal handler from jvm
+    actp = get_preinstalled_handler(sig);
+  }
+
+  return actp;
+}
+
+static bool call_chained_handler(struct sigaction *actp, int sig,
+                                 siginfo_t *siginfo, void *context) {
+  Unimplemented();
+  return true;
+}
+
+bool os::Aix::chained_handler(int sig, siginfo_t* siginfo, void* context) {
+  bool chained = false;
+  // signal-chaining
+  if (UseSignalChaining) {
+    struct sigaction *actp = get_chained_signal_action(sig);
+    if (actp != NULL) {
+      chained = call_chained_handler(actp, sig, siginfo, context);
+    }
+  }
+  return chained;
+}
+
+struct sigaction* os::Aix::get_preinstalled_handler(int sig) {
+  if ((((unsigned int)1 << sig) & sigs) != 0) {
+    return &sigact[sig];
+  }
+  return NULL;
+}
+
+void os::Aix::save_preinstalled_handler(int sig, struct sigaction& oldAct) {
+  assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+  sigact[sig] = oldAct;
+  sigs |= (unsigned int)1 << sig;
+}
+
+// for diagnostic
+int os::Aix::sigflags[MAXSIGNUM];
+
+int os::Aix::get_our_sigflags(int sig) {
+  assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+  return sigflags[sig];
+}
+
+void os::Aix::set_our_sigflags(int sig, int flags) {
+  assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+  sigflags[sig] = flags;
+}
+
+void os::Aix::set_signal_handler(int sig, bool set_installed) {
+  // Check for overwrite.
+  struct sigaction oldAct;
+  sigaction(sig, (struct sigaction*)NULL, &oldAct);
+
+  void* oldhand = oldAct.sa_sigaction
+    ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
+    : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
+  // Renamed 'signalHandler' to avoid collision with other shared libs.
+  if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) &&
+      oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) &&
+      oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)javaSignalHandler)) {
+    if (AllowUserSignalHandlers || !set_installed) {
+      // Do not overwrite; user takes responsibility to forward to us.
+      return;
+    } else if (UseSignalChaining) {
+      // save the old handler in jvm
+      save_preinstalled_handler(sig, oldAct);
+      // libjsig also interposes the sigaction() call below and saves the
+      // old sigaction on it own.
+    } else {
+      fatal(err_msg("Encountered unexpected pre-existing sigaction handler "
+                    "%#lx for signal %d.", (long)oldhand, sig));
+    }
+  }
+
+  struct sigaction sigAct;
+  sigfillset(&(sigAct.sa_mask));
+  if (!set_installed) {
+    sigAct.sa_handler = SIG_DFL;
+    sigAct.sa_flags = SA_RESTART;
+  } else {
+    // Renamed 'signalHandler' to avoid collision with other shared libs.
+    sigAct.sa_sigaction = javaSignalHandler;
+    sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
+  }
+  // Save flags, which are set by ours
+  assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+  sigflags[sig] = sigAct.sa_flags;
+
+  int ret = sigaction(sig, &sigAct, &oldAct);
+  assert(ret == 0, "check");
+
+  void* oldhand2 = oldAct.sa_sigaction
+                 ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
+                 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
+  assert(oldhand2 == oldhand, "no concurrent signal handler installation");
+}
+
+// install signal handlers for signals that HotSpot needs to
+// handle in order to support Java-level exception handling.
+void os::Aix::install_signal_handlers() {
+  if (!signal_handlers_are_installed) {
+    signal_handlers_are_installed = true;
+
+    // signal-chaining
+    typedef void (*signal_setting_t)();
+    signal_setting_t begin_signal_setting = NULL;
+    signal_setting_t end_signal_setting = NULL;
+    begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
+                             dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting"));
+    if (begin_signal_setting != NULL) {
+      end_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
+                             dlsym(RTLD_DEFAULT, "JVM_end_signal_setting"));
+      get_signal_action = CAST_TO_FN_PTR(get_signal_t,
+                            dlsym(RTLD_DEFAULT, "JVM_get_signal_action"));
+      libjsig_is_loaded = true;
+      assert(UseSignalChaining, "should enable signal-chaining");
+    }
+    if (libjsig_is_loaded) {
+      // Tell libjsig jvm is setting signal handlers
+      (*begin_signal_setting)();
+    }
+
+    set_signal_handler(SIGSEGV, true);
+    set_signal_handler(SIGPIPE, true);
+    set_signal_handler(SIGBUS, true);
+    set_signal_handler(SIGILL, true);
+    set_signal_handler(SIGFPE, true);
+    set_signal_handler(SIGTRAP, true);
+    set_signal_handler(SIGXFSZ, true);
+    set_signal_handler(SIGDANGER, true);
+
+    if (libjsig_is_loaded) {
+      // Tell libjsig jvm finishes setting signal handlers
+      (*end_signal_setting)();
+    }
+
+    // We don't activate signal checker if libjsig is in place, we trust ourselves
+    // and if UserSignalHandler is installed all bets are off.
+    // Log that signal checking is off only if -verbose:jni is specified.
+    if (CheckJNICalls) {
+      if (libjsig_is_loaded) {
+        tty->print_cr("Info: libjsig is activated, all active signal checking is disabled");
+        check_signals = false;
+      }
+      if (AllowUserSignalHandlers) {
+        tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
+        check_signals = false;
+      }
+      // need to initialize check_signal_done
+      ::sigemptyset(&check_signal_done);
+    }
+  }
+}
+
+static const char* get_signal_handler_name(address handler,
+                                           char* buf, int buflen) {
+  int offset;
+  bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset);
+  if (found) {
+    // skip directory names
+    const char *p1, *p2;
+    p1 = buf;
+    size_t len = strlen(os::file_separator());
+    while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len;
+    // The way os::dll_address_to_library_name is implemented on Aix
+    // right now, it always returns -1 for the offset which is not
+    // terribly informative.
+    // Will fix that. For now, omit the offset.
+    jio_snprintf(buf, buflen, "%s", p1);
+  } else {
+    jio_snprintf(buf, buflen, PTR_FORMAT, handler);
+  }
+  return buf;
+}
+
+static void print_signal_handler(outputStream* st, int sig,
+                                 char* buf, size_t buflen) {
+  struct sigaction sa;
+  sigaction(sig, NULL, &sa);
+
+  st->print("%s: ", os::exception_name(sig, buf, buflen));
+
+  address handler = (sa.sa_flags & SA_SIGINFO)
+    ? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
+    : CAST_FROM_FN_PTR(address, sa.sa_handler);
+
+  if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) {
+    st->print("SIG_DFL");
+  } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) {
+    st->print("SIG_IGN");
+  } else {
+    st->print("[%s]", get_signal_handler_name(handler, buf, buflen));
+  }
+
+  // Print readable mask.
+  st->print(", sa_mask[0]=");
+  os::Posix::print_signal_set_short(st, &sa.sa_mask);
+
+  address rh = VMError::get_resetted_sighandler(sig);
+  // May be, handler was resetted by VMError?
+  if (rh != NULL) {
+    handler = rh;
+    sa.sa_flags = VMError::get_resetted_sigflags(sig);
+  }
+
+  // Print textual representation of sa_flags.
+  st->print(", sa_flags=");
+  os::Posix::print_sa_flags(st, sa.sa_flags);
+
+  // Check: is it our handler?
+  if (handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)javaSignalHandler) ||
+      handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) {
+    // It is our signal handler.
+    // Check for flags, reset system-used one!
+    if ((int)sa.sa_flags != os::Aix::get_our_sigflags(sig)) {
+      st->print(", flags was changed from " PTR32_FORMAT ", consider using jsig library",
+                os::Aix::get_our_sigflags(sig));
+    }
+  }
+  st->cr();
+}
+
+
+#define DO_SIGNAL_CHECK(sig) \
+  if (!sigismember(&check_signal_done, sig)) \
+    os::Aix::check_signal_handler(sig)
+
+// This method is a periodic task to check for misbehaving JNI applications
+// under CheckJNI, we can add any periodic checks here
+
+void os::run_periodic_checks() {
+
+  if (check_signals == false) return;
+
+  // SEGV and BUS if overridden could potentially prevent
+  // generation of hs*.log in the event of a crash, debugging
+  // such a case can be very challenging, so we absolutely
+  // check the following for a good measure:
+  DO_SIGNAL_CHECK(SIGSEGV);
+  DO_SIGNAL_CHECK(SIGILL);
+  DO_SIGNAL_CHECK(SIGFPE);
+  DO_SIGNAL_CHECK(SIGBUS);
+  DO_SIGNAL_CHECK(SIGPIPE);
+  DO_SIGNAL_CHECK(SIGXFSZ);
+  if (UseSIGTRAP) {
+    DO_SIGNAL_CHECK(SIGTRAP);
+  }
+  DO_SIGNAL_CHECK(SIGDANGER);
+
+  // ReduceSignalUsage allows the user to override these handlers
+  // see comments at the very top and jvm_solaris.h
+  if (!ReduceSignalUsage) {
+    DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL);
+    DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL);
+    DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL);
+    DO_SIGNAL_CHECK(BREAK_SIGNAL);
+  }
+
+  DO_SIGNAL_CHECK(SR_signum);
+  DO_SIGNAL_CHECK(INTERRUPT_SIGNAL);
+}
+
+typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *);
+
+static os_sigaction_t os_sigaction = NULL;
+
+void os::Aix::check_signal_handler(int sig) {
+  char buf[O_BUFLEN];
+  address jvmHandler = NULL;
+
+  struct sigaction act;
+  if (os_sigaction == NULL) {
+    // only trust the default sigaction, in case it has been interposed
+    os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction");
+    if (os_sigaction == NULL) return;
+  }
+
+  os_sigaction(sig, (struct sigaction*)NULL, &act);
+
+  address thisHandler = (act.sa_flags & SA_SIGINFO)
+    ? CAST_FROM_FN_PTR(address, act.sa_sigaction)
+    : CAST_FROM_FN_PTR(address, act.sa_handler);
+
+
+  switch(sig) {
+  case SIGSEGV:
+  case SIGBUS:
+  case SIGFPE:
+  case SIGPIPE:
+  case SIGILL:
+  case SIGXFSZ:
+    // Renamed 'signalHandler' to avoid collision with other shared libs.
+    jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)javaSignalHandler);
+    break;
+
+  case SHUTDOWN1_SIGNAL:
+  case SHUTDOWN2_SIGNAL:
+  case SHUTDOWN3_SIGNAL:
+  case BREAK_SIGNAL:
+    jvmHandler = (address)user_handler();
+    break;
+
+  case INTERRUPT_SIGNAL:
+    jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL);
+    break;
+
+  default:
+    if (sig == SR_signum) {
+      jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler);
+    } else {
+      return;
+    }
+    break;
+  }
+
+  if (thisHandler != jvmHandler) {
+    tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN));
+    tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN));
+    tty->print_cr("  found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
+    // No need to check this sig any longer
+    sigaddset(&check_signal_done, sig);
+  } else if (os::Aix::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Aix::get_our_sigflags(sig)) {
+    tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
+    tty->print("expected:" PTR32_FORMAT, os::Aix::get_our_sigflags(sig));
+    tty->print_cr("  found:" PTR32_FORMAT, act.sa_flags);
+    // No need to check this sig any longer
+    sigaddset(&check_signal_done, sig);
+  }
+
+  // Dump all the signal
+  if (sigismember(&check_signal_done, sig)) {
+    print_signal_handlers(tty, buf, O_BUFLEN);
+  }
+}
+
+extern bool signal_name(int signo, char* buf, size_t len);
+
+const char* os::exception_name(int exception_code, char* buf, size_t size) {
+  if (0 < exception_code && exception_code <= SIGRTMAX) {
+    // signal
+    if (!signal_name(exception_code, buf, size)) {
+      jio_snprintf(buf, size, "SIG%d", exception_code);
+    }
+    return buf;
+  } else {
+    return NULL;
+  }
+}
+
+// To install functions for atexit system call
+extern "C" {
+  static void perfMemory_exit_helper() {
+    perfMemory_exit();
+  }
+}
+
+// This is called _before_ the most of global arguments have been parsed.
+void os::init(void) {
+  // This is basic, we want to know if that ever changes.
+  // (shared memory boundary is supposed to be a 256M aligned)
+  assert(SHMLBA == ((uint64_t)0x10000000ULL)/*256M*/, "unexpected");
+
+  // First off, we need to know whether we run on AIX or PASE, and
+  // the OS level we run on.
+  os::Aix::initialize_os_info();
+
+  // Scan environment (SPEC1170 behaviour, etc)
+  os::Aix::scan_environment();
+
+  // Check which pages are supported by AIX.
+  os::Aix::query_multipage_support();
+
+  // Next, we need to initialize libo4 and libperfstat libraries.
+  if (os::Aix::on_pase()) {
+    os::Aix::initialize_libo4();
+  } else {
+    os::Aix::initialize_libperfstat();
+  }
+
+  // Reset the perfstat information provided by ODM.
+  if (os::Aix::on_aix()) {
+    libperfstat::perfstat_reset();
+  }
+
+  // Now initialze basic system properties. Note that for some of the values we
+  // need libperfstat etc.
+  os::Aix::initialize_system_info();
+
+  // Initialize large page support.
+  if (UseLargePages) {
+    os::large_page_init();
+    if (!UseLargePages) {
+      // initialize os::_page_sizes
+      _page_sizes[0] = Aix::page_size();
+      _page_sizes[1] = 0;
+      if (Verbose) {
+        fprintf(stderr, "Large Page initialization failed: setting UseLargePages=0.\n");
+      }
+    }
+  } else {
+    // initialize os::_page_sizes
+    _page_sizes[0] = Aix::page_size();
+    _page_sizes[1] = 0;
+  }
+
+  // debug trace
+  if (Verbose) {
+    fprintf(stderr, "os::vm_page_size 0x%llX\n", os::vm_page_size());
+    fprintf(stderr, "os::large_page_size 0x%llX\n", os::large_page_size());
+    fprintf(stderr, "os::_page_sizes = ( ");
+    for (int i = 0; _page_sizes[i]; i ++) {
+      fprintf(stderr, " %s ", describe_pagesize(_page_sizes[i]));
+    }
+    fprintf(stderr, ")\n");
+  }
+
+  _initial_pid = getpid();
+
+  clock_tics_per_sec = sysconf(_SC_CLK_TCK);
+
+  init_random(1234567);
+
+  ThreadCritical::initialize();
+
+  // Main_thread points to the aboriginal thread.
+  Aix::_main_thread = pthread_self();
+
+  initial_time_count = os::elapsed_counter();
+  pthread_mutex_init(&dl_mutex, NULL);
+}
+
+// this is called _after_ the global arguments have been parsed
+jint os::init_2(void) {
+
+  if (Verbose) {
+    fprintf(stderr, "processor count: %d\n", os::_processor_count);
+    fprintf(stderr, "physical memory: %lu\n", Aix::_physical_memory);
+  }
+
+  // initially build up the loaded dll map
+  LoadedLibraries::reload();
+
+  const int page_size = Aix::page_size();
+  const int map_size = page_size;
+
+  address map_address = (address) MAP_FAILED;
+  const int prot  = PROT_READ;
+  const int flags = MAP_PRIVATE|MAP_ANONYMOUS;
+
+  // use optimized addresses for the polling page,
+  // e.g. map it to a special 32-bit address.
+  if (OptimizePollingPageLocation) {
+    // architecture-specific list of address wishes:
+    address address_wishes[] = {
+      // AIX: addresses lower than 0x30000000 don't seem to work on AIX.
+      // PPC64: all address wishes are non-negative 32 bit values where
+      // the lower 16 bits are all zero. we can load these addresses
+      // with a single ppc_lis instruction.
+      (address) 0x30000000, (address) 0x31000000,
+      (address) 0x32000000, (address) 0x33000000,
+      (address) 0x40000000, (address) 0x41000000,
+      (address) 0x42000000, (address) 0x43000000,
+      (address) 0x50000000, (address) 0x51000000,
+      (address) 0x52000000, (address) 0x53000000,
+      (address) 0x60000000, (address) 0x61000000,
+      (address) 0x62000000, (address) 0x63000000
+    };
+    int address_wishes_length = sizeof(address_wishes)/sizeof(address);
+
+    // iterate over the list of address wishes:
+    for (int i=0; i<address_wishes_length; i++) {
+      // try to map with current address wish.
+      // AIX: AIX needs MAP_FIXED if we provide an address and mmap will
+      // fail if the address is already mapped.
+      map_address = (address) ::mmap(address_wishes[i] - (ssize_t)page_size,
+                                     map_size, prot,
+                                     flags | MAP_FIXED,
+                                     -1, 0);
+      if (Verbose) {
+        fprintf(stderr, "SafePoint Polling Page address: %p (wish) => %p\n",
+                address_wishes[i], map_address + (ssize_t)page_size);
+      }
+
+      if (map_address + (ssize_t)page_size == address_wishes[i]) {
+        // map succeeded and map_address is at wished address, exit loop.
+        break;
+      }
+
+      if (map_address != (address) MAP_FAILED) {
+        // map succeeded, but polling_page is not at wished address, unmap and continue.
+        ::munmap(map_address, map_size);
+        map_address = (address) MAP_FAILED;
+      }
+      // map failed, continue loop.
+    }
+  } // end OptimizePollingPageLocation
+
+  if (map_address == (address) MAP_FAILED) {
+    map_address = (address) ::mmap(NULL, map_size, prot, flags, -1, 0);
+  }
+  guarantee(map_address != MAP_FAILED, "os::init_2: failed to allocate polling page");
+  os::set_polling_page(map_address);
+
+  if (!UseMembar) {
+    address mem_serialize_page = (address) ::mmap(NULL, Aix::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+    guarantee(mem_serialize_page != NULL, "mmap Failed for memory serialize page");
+    os::set_memory_serialize_page(mem_serialize_page);
+
+#ifndef PRODUCT
+    if (Verbose && PrintMiscellaneous)
+      tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page);
+#endif
+  }
+
+  // initialize suspend/resume support - must do this before signal_sets_init()
+  if (SR_initialize() != 0) {
+    perror("SR_initialize failed");
+    return JNI_ERR;
+  }
+
+  Aix::signal_sets_init();
+  Aix::install_signal_handlers();
+
+  // Check minimum allowable stack size for thread creation and to initialize
+  // the java system classes, including StackOverflowError - depends on page
+  // size. Add a page for compiler2 recursion in main thread.
+  // Add in 2*BytesPerWord times page size to account for VM stack during
+  // class initialization depending on 32 or 64 bit VM.
+  os::Aix::min_stack_allowed = MAX2(os::Aix::min_stack_allowed,
+            (size_t)(StackYellowPages+StackRedPages+StackShadowPages +
+                     2*BytesPerWord COMPILER2_PRESENT(+1)) * Aix::page_size());
+
+  size_t threadStackSizeInBytes = ThreadStackSize * K;
+  if (threadStackSizeInBytes != 0 &&
+      threadStackSizeInBytes < os::Aix::min_stack_allowed) {
+        tty->print_cr("\nThe stack size specified is too small, "
+                      "Specify at least %dk",
+                      os::Aix::min_stack_allowed / K);
+        return JNI_ERR;
+  }
+
+  // Make the stack size a multiple of the page size so that
+  // the yellow/red zones can be guarded.
+  // note that this can be 0, if no default stacksize was set
+  JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size()));
+
+  Aix::libpthread_init();
+
+  if (MaxFDLimit) {
+    // set the number of file descriptors to max. print out error
+    // if getrlimit/setrlimit fails but continue regardless.
+    struct rlimit nbr_files;
+    int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
+    if (status != 0) {
+      if (PrintMiscellaneous && (Verbose || WizardMode))
+        perror("os::init_2 getrlimit failed");
+    } else {
+      nbr_files.rlim_cur = nbr_files.rlim_max;
+      status = setrlimit(RLIMIT_NOFILE, &nbr_files);
+      if (status != 0) {
+        if (PrintMiscellaneous && (Verbose || WizardMode))
+          perror("os::init_2 setrlimit failed");
+      }
+    }
+  }
+
+  if (PerfAllowAtExitRegistration) {
+    // only register atexit functions if PerfAllowAtExitRegistration is set.
+    // atexit functions can be delayed until process exit time, which
+    // can be problematic for embedded VM situations. Embedded VMs should
+    // call DestroyJavaVM() to assure that VM resources are released.
+
+    // note: perfMemory_exit_helper atexit function may be removed in
+    // the future if the appropriate cleanup code can be added to the
+    // VM_Exit VMOperation's doit method.
+    if (atexit(perfMemory_exit_helper) != 0) {
+      warning("os::init_2 atexit(perfMemory_exit_helper) failed");
+    }
+  }
+
+  return JNI_OK;
+}
+
+// this is called at the end of vm_initialization
+void os::init_3(void) {
+  return;
+}
+
+// Mark the polling page as unreadable
+void os::make_polling_page_unreadable(void) {
+  if (!guard_memory((char*)_polling_page, Aix::page_size())) {
+    fatal("Could not disable polling page");
+  }
+};
+
+// Mark the polling page as readable
+void os::make_polling_page_readable(void) {
+  // Changed according to os_linux.cpp.
+  if (!checked_mprotect((char *)_polling_page, Aix::page_size(), PROT_READ)) {
+    fatal(err_msg("Could not enable polling page at " PTR_FORMAT, _polling_page));
+  }
+};
+
+int os::active_processor_count() {
+  int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
+  assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
+  return online_cpus;
+}
+
+void os::set_native_thread_name(const char *name) {
+  // Not yet implemented.
+  return;
+}
+
+bool os::distribute_processes(uint length, uint* distribution) {
+  // Not yet implemented.
+  return false;
+}
+
+bool os::bind_to_processor(uint processor_id) {
+  // Not yet implemented.
+  return false;
+}
+
+void os::SuspendedThreadTask::internal_do_task() {
+  if (do_suspend(_thread->osthread())) {
+    SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext());
+    do_task(context);
+    do_resume(_thread->osthread());
+  }
+}
+
+class PcFetcher : public os::SuspendedThreadTask {
+public:
+  PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
+  ExtendedPC result();
+protected:
+  void do_task(const os::SuspendedThreadTaskContext& context);
+private:
+  ExtendedPC _epc;
+};
+
+ExtendedPC PcFetcher::result() {
+  guarantee(is_done(), "task is not done yet.");
+  return _epc;
+}
+
+void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
+  Thread* thread = context.thread();
+  OSThread* osthread = thread->osthread();
+  if (osthread->ucontext() != NULL) {
+    _epc = os::Aix::ucontext_get_pc((ucontext_t *) context.ucontext());
+  } else {
+    // NULL context is unexpected, double-check this is the VMThread.
+    guarantee(thread->is_VM_thread(), "can only be called for VMThread");
+  }
+}
+
+// Suspends the target using the signal mechanism and then grabs the PC before
+// resuming the target. Used by the flat-profiler only
+ExtendedPC os::get_thread_pc(Thread* thread) {
+  // Make sure that it is called by the watcher for the VMThread.
+  assert(Thread::current()->is_Watcher_thread(), "Must be watcher");
+  assert(thread->is_VM_thread(), "Can only be called for VMThread");
+
+  PcFetcher fetcher(thread);
+  fetcher.run();
+  return fetcher.result();
+}
+
+// Not neede on Aix.
+// int os::Aix::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) {
+// }
+
+////////////////////////////////////////////////////////////////////////////////
+// debug support
+
+static address same_page(address x, address y) {
+  intptr_t page_bits = -os::vm_page_size();
+  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
+    return x;
+  else if (x > y)
+    return (address)(intptr_t(y) | ~page_bits) + 1;
+  else
+    return (address)(intptr_t(y) & page_bits);
+}
+
+bool os::find(address addr, outputStream* st) {
+  Unimplemented();
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// misc
+
+// This does not do anything on Aix. This is basically a hook for being
+// able to use structured exception handling (thread-local exception filters)
+// on, e.g., Win32.
+void
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+                         JavaCallArguments* args, Thread* thread) {
+  f(value, method, args, thread);
+}
+
+void os::print_statistics() {
+}
+
+int os::message_box(const char* title, const char* message) {
+  int i;
+  fdStream err(defaultStream::error_fd());
+  for (i = 0; i < 78; i++) err.print_raw("=");
+  err.cr();
+  err.print_raw_cr(title);
+  for (i = 0; i < 78; i++) err.print_raw("-");
+  err.cr();
+  err.print_raw_cr(message);
+  for (i = 0; i < 78; i++) err.print_raw("=");
+  err.cr();
+
+  char buf[16];
+  // Prevent process from exiting upon "read error" without consuming all CPU
+  while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); }
+
+  return buf[0] == 'y' || buf[0] == 'Y';
+}
+
+int os::stat(const char *path, struct stat *sbuf) {
+  char pathbuf[MAX_PATH];
+  if (strlen(path) > MAX_PATH - 1) {
+    errno = ENAMETOOLONG;
+    return -1;
+  }
+  os::native_path(strcpy(pathbuf, path));
+  return ::stat(pathbuf, sbuf);
+}
+
+bool os::check_heap(bool force) {
+  return true;
+}
+
+// int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) {
+//   return ::vsnprintf(buf, count, format, args);
+// }
+
+// Is a (classpath) directory empty?
+bool os::dir_is_empty(const char* path) {
+  Unimplemented();
+  return false;
+}
+
+// This code originates from JDK's sysOpen and open64_w
+// from src/solaris/hpi/src/system_md.c
+
+#ifndef O_DELETE
+#define O_DELETE 0x10000
+#endif
+
+// Open a file. Unlink the file immediately after open returns
+// if the specified oflag has the O_DELETE flag set.
+// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c
+
+int os::open(const char *path, int oflag, int mode) {
+
+  if (strlen(path) > MAX_PATH - 1) {
+    errno = ENAMETOOLONG;
+    return -1;
+  }
+  int fd;
+  int o_delete = (oflag & O_DELETE);
+  oflag = oflag & ~O_DELETE;
+
+  fd = ::open64(path, oflag, mode);
+  if (fd == -1) return -1;
+
+  //If the open succeeded, the file might still be a directory
+  {
+    struct stat64 buf64;
+    int ret = ::fstat64(fd, &buf64);
+    int st_mode = buf64.st_mode;
+
+    if (ret != -1) {
+      if ((st_mode & S_IFMT) == S_IFDIR) {
+        errno = EISDIR;
+        ::close(fd);
+        return -1;
+      }
+    } else {
+      ::close(fd);
+      return -1;
+    }
+  }
+
+  // All file descriptors that are opened in the JVM and not
+  // specifically destined for a subprocess should have the
+  // close-on-exec flag set. If we don't set it, then careless 3rd
+  // party native code might fork and exec without closing all
+  // appropriate file descriptors (e.g. as we do in closeDescriptors in
+  // UNIXProcess.c), and this in turn might:
+  //
+  // - cause end-of-file to fail to be detected on some file
+  //   descriptors, resulting in mysterious hangs, or
+  //
+  // - might cause an fopen in the subprocess to fail on a system
+  //   suffering from bug 1085341.
+  //
+  // (Yes, the default setting of the close-on-exec flag is a Unix
+  // design flaw.)
+  //
+  // See:
+  // 1085341: 32-bit stdio routines should support file descriptors >255
+  // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
+  // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
+#ifdef FD_CLOEXEC
+  {
+    int flags = ::fcntl(fd, F_GETFD);
+    if (flags != -1)
+      ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+  }
+#endif
+
+  if (o_delete != 0) {
+    ::unlink(path);
+  }
+  return fd;
+}
+
+
+// create binary file, rewriting existing file if required
+int os::create_binary_file(const char* path, bool rewrite_existing) {
+  Unimplemented();
+  return 0;
+}
+
+// return current position of file pointer
+jlong os::current_file_offset(int fd) {
+  return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR);
+}
+
+// move file pointer to the specified offset
+jlong os::seek_to_file_offset(int fd, jlong offset) {
+  return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
+}
+
+// This code originates from JDK's sysAvailable
+// from src/solaris/hpi/src/native_threads/src/sys_api_td.c
+
+int os::available(int fd, jlong *bytes) {
+  jlong cur, end;
+  int mode;
+  struct stat64 buf64;
+
+  if (::fstat64(fd, &buf64) >= 0) {
+    mode = buf64.st_mode;
+    if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
+      // XXX: is the following call interruptible? If so, this might
+      // need to go through the INTERRUPT_IO() wrapper as for other
+      // blocking, interruptible calls in this file.
+      int n;
+      if (::ioctl(fd, FIONREAD, &n) >= 0) {
+        *bytes = n;
+        return 1;
+      }
+    }
+  }
+  if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) {
+    return 0;
+  } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) {
+    return 0;
+  } else if (::lseek64(fd, cur, SEEK_SET) == -1) {
+    return 0;
+  }
+  *bytes = end - cur;
+  return 1;
+}
+
+int os::socket_available(int fd, jint *pbytes) {
+  // Linux doc says EINTR not returned, unlike Solaris
+  int ret = ::ioctl(fd, FIONREAD, pbytes);
+
+  //%% note ioctl can return 0 when successful, JVM_SocketAvailable
+  // is expected to return 0 on failure and 1 on success to the jdk.
+  return (ret < 0) ? 0 : 1;
+}
+
+// Map a block of memory.
+char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
+                        char *addr, size_t bytes, bool read_only,
+                        bool allow_exec) {
+  Unimplemented();
+  return NULL;
+}
+
+
+// Remap a block of memory.
+char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
+                          char *addr, size_t bytes, bool read_only,
+                          bool allow_exec) {
+  // same as map_memory() on this OS
+  return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
+                        allow_exec);
+}
+
+// Unmap a block of memory.
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
+  return munmap(addr, bytes) == 0;
+}
+
+// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
+// are used by JVM M&M and JVMTI to get user+sys or user CPU time
+// of a thread.
+//
+// current_thread_cpu_time() and thread_cpu_time(Thread*) returns
+// the fast estimate available on the platform.
+
+jlong os::current_thread_cpu_time() {
+  // return user + sys since the cost is the same
+  const jlong n = os::thread_cpu_time(Thread::current(), true /* user + sys */);
+  assert(n >= 0, "negative CPU time");
+  return n;
+}
+
+jlong os::thread_cpu_time(Thread* thread) {
+  // consistent with what current_thread_cpu_time() returns
+  const jlong n = os::thread_cpu_time(thread, true /* user + sys */);
+  assert(n >= 0, "negative CPU time");
+  return n;
+}
+
+jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
+  const jlong n = os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
+  assert(n >= 0, "negative CPU time");
+  return n;
+}
+
+static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* p_user_time) {
+  bool error = false;
+
+  jlong sys_time = 0;
+  jlong user_time = 0;
+
+  // reimplemented using getthrds64().
+  //
+  // goes like this:
+  // For the thread in question, get the kernel thread id. Then get the
+  // kernel thread statistics using that id.
+  //
+  // This only works of course when no pthread scheduling is used,
+  // ie there is a 1:1 relationship to kernel threads.
+  // On AIX, see AIXTHREAD_SCOPE variable.
+
+  pthread_t pthtid = thread->osthread()->pthread_id();
+
+  // retrieve kernel thread id for the pthread:
+  tid64_t tid = 0;
+  struct __pthrdsinfo pinfo;
+  // I just love those otherworldly IBM APIs which force me to hand down
+  // dummy buffers for stuff I dont care for...
+  char dummy[1];
+  int dummy_size = sizeof(dummy);
+  if (pthread_getthrds_np(&pthtid, PTHRDSINFO_QUERY_TID, &pinfo, sizeof(pinfo),
+                          dummy, &dummy_size) == 0) {
+    tid = pinfo.__pi_tid;
+  } else {
+    tty->print_cr("pthread_getthrds_np failed.");
+    error = true;
+  }
+
+  // retrieve kernel timing info for that kernel thread
+  if (!error) {
+    struct thrdentry64 thrdentry;
+    if (getthrds64(getpid(), &thrdentry, sizeof(thrdentry), &tid, 1) == 1) {
+      sys_time = thrdentry.ti_ru.ru_stime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_stime.tv_usec * 1000LL;
+      user_time = thrdentry.ti_ru.ru_utime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_utime.tv_usec * 1000LL;
+    } else {
+      tty->print_cr("pthread_getthrds_np failed.");
+      error = true;
+    }
+  }
+
+  if (p_sys_time) {
+    *p_sys_time = sys_time;
+  }
+
+  if (p_user_time) {
+    *p_user_time = user_time;
+  }
+
+  if (error) {
+    return false;
+  }
+
+  return true;
+}
+
+jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
+  jlong sys_time;
+  jlong user_time;
+
+  if (!thread_cpu_time_unchecked(thread, &sys_time, &user_time)) {
+    return -1;
+  }
+
+  return user_sys_cpu_time ? sys_time + user_time : user_time;
+}
+
+void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
+  info_ptr->max_value = ALL_64_BITS;       // will not wrap in less than 64 bits
+  info_ptr->may_skip_backward = false;     // elapsed time not wall time
+  info_ptr->may_skip_forward = false;      // elapsed time not wall time
+  info_ptr->kind = JVMTI_TIMER_TOTAL_CPU;  // user+system time is returned
+}
+
+void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
+  info_ptr->max_value = ALL_64_BITS;       // will not wrap in less than 64 bits
+  info_ptr->may_skip_backward = false;     // elapsed time not wall time
+  info_ptr->may_skip_forward = false;      // elapsed time not wall time
+  info_ptr->kind = JVMTI_TIMER_TOTAL_CPU;  // user+system time is returned
+}
+
+bool os::is_thread_cpu_time_supported() {
+  return true;
+}
+
+// System loadavg support. Returns -1 if load average cannot be obtained.
+// For now just return the system wide load average (no processor sets).
+int os::loadavg(double values[], int nelem) {
+
+  // Implemented using libperfstat on AIX.
+
+  guarantee(nelem >= 0 && nelem <= 3, "argument error");
+  guarantee(values, "argument error");
+
+  if (os::Aix::on_pase()) {
+    Unimplemented();
+    return -1;
+  } else {
+    // AIX: use libperfstat
+    //
+    // See also:
+    // http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/perfstat_cputot.htm
+    // /usr/include/libperfstat.h:
+
+    // Use the already AIX version independent get_cpuinfo.
+    os::Aix::cpuinfo_t ci;
+    if (os::Aix::get_cpuinfo(&ci)) {
+      for (int i = 0; i < nelem; i++) {
+        values[i] = ci.loadavg[i];
+      }
+    } else {
+      return -1;
+    }
+    return nelem;
+  }
+}
+
+void os::pause() {
+  char filename[MAX_PATH];
+  if (PauseAtStartupFile && PauseAtStartupFile[0]) {
+    jio_snprintf(filename, MAX_PATH, PauseAtStartupFile);
+  } else {
+    jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id());
+  }
+
+  int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+  if (fd != -1) {
+    struct stat buf;
+    ::close(fd);
+    while (::stat(filename, &buf) == 0) {
+      (void)::poll(NULL, 0, 100);
+    }
+  } else {
+    jio_fprintf(stderr,
+      "Could not open pause file '%s', continuing immediately.\n", filename);
+  }
+}
+
+bool os::Aix::is_primordial_thread() {
+  if (pthread_self() == (pthread_t)1) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// OS recognitions (PASE/AIX, OS level) call this before calling any
+// one of Aix::on_pase(), Aix::os_version() static
+void os::Aix::initialize_os_info() {
+
+  assert(_on_pase == -1 && _os_version == -1, "already called.");
+
+  struct utsname uts;
+  memset(&uts, 0, sizeof(uts));
+  strcpy(uts.sysname, "?");
+  if (::uname(&uts) == -1) {
+    fprintf(stderr, "uname failed (%d)\n", errno);
+    guarantee(0, "Could not determine whether we run on AIX or PASE");
+  } else {
+    if (Verbose) {
+      fprintf(stderr,"uname says: sysname \"%s\" version \"%s\" release \"%s\" "
+              "node \"%s\" machine \"%s\"\n",
+              uts.sysname, uts.version, uts.release, uts.nodename, uts.machine);
+    }
+    const int major = atoi(uts.version);
+    assert(major > 0, "invalid OS version");
+    const int minor = atoi(uts.release);
+    assert(minor > 0, "invalid OS release");
+    _os_version = (major << 8) | minor;
+    if (strcmp(uts.sysname, "OS400") == 0) {
+      Unimplemented();
+    } else if (strcmp(uts.sysname, "AIX") == 0) {
+      // We run on AIX. We do not support versions older than AIX 5.3.
+      _on_pase = 0;
+      if (_os_version < 0x0503) {
+        fprintf(stderr, "AIX release older than AIX 5.3 not supported.\n");
+        assert(false, "AIX release too old.");
+      } else {
+        if (Verbose) {
+          fprintf(stderr, "We run on AIX %d.%d\n", major, minor);
+        }
+      }
+    } else {
+      assert(false, "unknown OS");
+    }
+  }
+
+  guarantee(_on_pase != -1 && _os_version, "Could not determine AIX/OS400 release");
+
+} // end: os::Aix::initialize_os_info()
+
+// 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().
+void os::Aix::scan_environment() {
+
+  char* p;
+  int rc;
+
+  // Warn explicity if EXTSHM=ON is used. That switch changes how
+  // System V shared memory behaves. One effect is that page size of
+  // shared memory cannot be change dynamically, effectivly preventing
+  // large pages from working.
+  // This switch was needed on AIX 32bit, but on AIX 64bit the general
+  // recommendation is (in OSS notes) to switch it off.
+  p = ::getenv("EXTSHM");
+  if (Verbose) {
+    fprintf(stderr, "EXTSHM=%s.\n", p ? p : "<unset>");
+  }
+  if (p && strcmp(p, "ON") == 0) {
+    fprintf(stderr, "Unsupported setting: EXTSHM=ON. Large Page support will be disabled.\n");
+    _extshm = 1;
+  } else {
+    _extshm = 0;
+  }
+
+  // SPEC1170 behaviour: will change the behaviour of a number of POSIX APIs.
+  // Not tested, not supported.
+  //
+  // Note that it might be worth the trouble to test and to require it, if only to
+  // get useful return codes for mprotect.
+  //
+  // Note: Setting XPG_SUS_ENV in the process is too late. Must be set earlier (before
+  // exec() ? before loading the libjvm ? ....)
+  p = ::getenv("XPG_SUS_ENV");
+  if (Verbose) {
+    fprintf(stderr, "XPG_SUS_ENV=%s.\n", p ? p : "<unset>");
+  }
+  if (p && strcmp(p, "ON") == 0) {
+    _xpg_sus_mode = 1;
+    fprintf(stderr, "Unsupported setting: XPG_SUS_ENV=ON\n");
+    // This is not supported. Worst of all, it changes behaviour of mmap MAP_FIXED to
+    // clobber address ranges. If we ever want to support that, we have to do some
+    // testing first.
+    guarantee(false, "XPG_SUS_ENV=ON not supported");
+  } else {
+    _xpg_sus_mode = 0;
+  }
+
+  // Switch off AIX internal (pthread) guard pages. This has
+  // immediate effect for any pthread_create calls which follow.
+  p = ::getenv("AIXTHREAD_GUARDPAGES");
+  if (Verbose) {
+    fprintf(stderr, "AIXTHREAD_GUARDPAGES=%s.\n", p ? p : "<unset>");
+    fprintf(stderr, "setting AIXTHREAD_GUARDPAGES=0.\n");
+  }
+  rc = ::putenv("AIXTHREAD_GUARDPAGES=0");
+  guarantee(rc == 0, "");
+
+} // end: os::Aix::scan_environment()
+
+// PASE: initialize the libo4 library (AS400 PASE porting library).
+void os::Aix::initialize_libo4() {
+  Unimplemented();
+}
+
+// AIX: initialize the libperfstat library (we load this dynamically
+// because it is only available on AIX.
+void os::Aix::initialize_libperfstat() {
+
+  assert(os::Aix::on_aix(), "AIX only");
+
+  if (!libperfstat::init()) {
+    fprintf(stderr, "libperfstat initialization failed.\n");
+    assert(false, "libperfstat initialization failed");
+  } else {
+    if (Verbose) {
+      fprintf(stderr, "libperfstat initialized.\n");
+    }
+  }
+} // end: os::Aix::initialize_libperfstat
+
+/////////////////////////////////////////////////////////////////////////////
+// thread stack
+
+// function to query the current stack size using pthread_getthrds_np
+//
+// ! do not change anything here unless you know what you are doing !
+static void query_stack_dimensions(address* p_stack_base, size_t* p_stack_size) {
+
+  // This only works when invoked on a pthread. As we agreed not to use
+  // primordial threads anyway, I assert here
+  guarantee(!os::Aix::is_primordial_thread(), "not allowed on the primordial thread");
+
+  // information about this api can be found (a) in the pthread.h header and
+  // (b) in http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_getthrds_np.htm
+  //
+  // The use of this API to find out the current stack is kind of undefined.
+  // But after a lot of tries and asking IBM about it, I concluded that it is safe
+  // enough for cases where I let the pthread library create its stacks. For cases
+  // where I create an own stack and pass this to pthread_create, it seems not to
+  // work (the returned stack size in that case is 0).
+
+  pthread_t tid = pthread_self();
+  struct __pthrdsinfo pinfo;
+  char dummy[1]; // we only need this to satisfy the api and to not get E
+  int dummy_size = sizeof(dummy);
+
+  memset(&pinfo, 0, sizeof(pinfo));
+
+  const int rc = pthread_getthrds_np (&tid, PTHRDSINFO_QUERY_ALL, &pinfo,
+                                      sizeof(pinfo), dummy, &dummy_size);
+
+  if (rc != 0) {
+    fprintf(stderr, "pthread_getthrds_np failed (%d)\n", rc);
+    guarantee(0, "pthread_getthrds_np failed");
+  }
+
+  guarantee(pinfo.__pi_stackend, "returned stack base invalid");
+
+  // the following can happen when invoking pthread_getthrds_np on a pthread running on a user provided stack
+  // (when handing down a stack to pthread create, see pthread_attr_setstackaddr).
+  // Not sure what to do here - I feel inclined to forbid this use case completely.
+  guarantee(pinfo.__pi_stacksize, "returned stack size invalid");
+
+  // On AIX, stacks are not necessarily page aligned so round the base and size accordingly
+  if (p_stack_base) {
+    (*p_stack_base) = (address) align_size_up((intptr_t)pinfo.__pi_stackend, os::Aix::stack_page_size());
+  }
+
+  if (p_stack_size) {
+    (*p_stack_size) = pinfo.__pi_stacksize - os::Aix::stack_page_size();
+  }
+
+#ifndef PRODUCT
+  if (Verbose) {
+    fprintf(stderr,
+            "query_stack_dimensions() -> real stack_base=" INTPTR_FORMAT ", real stack_addr=" INTPTR_FORMAT
+            ", real stack_size=" INTPTR_FORMAT
+            ", stack_base=" INTPTR_FORMAT ", stack_size=" INTPTR_FORMAT "\n",
+            (intptr_t)pinfo.__pi_stackend, (intptr_t)pinfo.__pi_stackaddr, pinfo.__pi_stacksize,
+            (intptr_t)align_size_up((intptr_t)pinfo.__pi_stackend, os::Aix::stack_page_size()),
+            pinfo.__pi_stacksize - os::Aix::stack_page_size());
+  }
+#endif
+
+} // end query_stack_dimensions
+
+// get the current stack base from the OS (actually, the pthread library)
+address os::current_stack_base() {
+  address p;
+  query_stack_dimensions(&p, 0);
+  return p;
+}
+
+// get the current stack size from the OS (actually, the pthread library)
+size_t os::current_stack_size() {
+  size_t s;
+  query_stack_dimensions(0, &s);
+  return s;
+}
+
+// Refer to the comments in os_solaris.cpp park-unpark.
+//
+// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can
+// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable.
+// For specifics regarding the bug see GLIBC BUGID 261237 :
+//    http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html.
+// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future
+// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar
+// is used. (The simple C test-case provided in the GLIBC bug report manifests the
+// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos()
+// and monitorenter when we're using 1-0 locking. All those operations may result in
+// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version
+// of libpthread avoids the problem, but isn't practical.
+//
+// Possible remedies:
+//
+// 1.   Establish a minimum relative wait time. 50 to 100 msecs seems to work.
+//      This is palliative and probabilistic, however. If the thread is preempted
+//      between the call to compute_abstime() and pthread_cond_timedwait(), more
+//      than the minimum period may have passed, and the abstime may be stale (in the
+//      past) resultin in a hang. Using this technique reduces the odds of a hang
+//      but the JVM is still vulnerable, particularly on heavily loaded systems.
+//
+// 2.   Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead
+//      of the usual flag-condvar-mutex idiom. The write side of the pipe is set
+//      NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo)
+//      reduces to poll()+read(). This works well, but consumes 2 FDs per extant
+//      thread.
+//
+// 3.   Embargo pthread_cond_timedwait() and implement a native "chron" thread
+//      that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing
+//      a timeout request to the chron thread and then blocking via pthread_cond_wait().
+//      This also works well. In fact it avoids kernel-level scalability impediments
+//      on certain platforms that don't handle lots of active pthread_cond_timedwait()
+//      timers in a graceful fashion.
+//
+// 4.   When the abstime value is in the past it appears that control returns
+//      correctly from pthread_cond_timedwait(), but the condvar is left corrupt.
+//      Subsequent timedwait/wait calls may hang indefinitely. Given that, we
+//      can avoid the problem by reinitializing the condvar -- by cond_destroy()
+//      followed by cond_init() -- after all calls to pthread_cond_timedwait().
+//      It may be possible to avoid reinitialization by checking the return
+//      value from pthread_cond_timedwait(). In addition to reinitializing the
+//      condvar we must establish the invariant that cond_signal() is only called
+//      within critical sections protected by the adjunct mutex. This prevents
+//      cond_signal() from "seeing" a condvar that's in the midst of being
+//      reinitialized or that is corrupt. Sadly, this invariant obviates the
+//      desirable signal-after-unlock optimization that avoids futile context switching.
+//
+//      I'm also concerned that some versions of NTPL might allocate an auxilliary
+//      structure when a condvar is used or initialized. cond_destroy() would
+//      release the helper structure. Our reinitialize-after-timedwait fix
+//      put excessive stress on malloc/free and locks protecting the c-heap.
+//
+// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag.
+// It may be possible to refine (4) by checking the kernel and NTPL verisons
+// and only enabling the work-around for vulnerable environments.
+
+// utility to compute the abstime argument to timedwait:
+// millis is the relative timeout time
+// abstime will be the absolute timeout time
+// TODO: replace compute_abstime() with unpackTime()
+
+static struct timespec* compute_abstime(timespec* abstime, jlong millis) {
+  if (millis < 0) millis = 0;
+  struct timeval now;
+  int status = gettimeofday(&now, NULL);
+  assert(status == 0, "gettimeofday");
+  jlong seconds = millis / 1000;
+  millis %= 1000;
+  if (seconds > 50000000) { // see man cond_timedwait(3T)
+    seconds = 50000000;
+  }
+  abstime->tv_sec = now.tv_sec  + seconds;
+  long       usec = now.tv_usec + millis * 1000;
+  if (usec >= 1000000) {
+    abstime->tv_sec += 1;
+    usec -= 1000000;
+  }
+  abstime->tv_nsec = usec * 1000;
+  return abstime;
+}
+
+
+// Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
+// Conceptually TryPark() should be equivalent to park(0).
+
+int os::PlatformEvent::TryPark() {
+  for (;;) {
+    const int v = _Event;
+    guarantee ((v == 0) || (v == 1), "invariant");
+    if (Atomic::cmpxchg (0, &_Event, v) == v) return v;
+  }
+}
+
+void os::PlatformEvent::park() {       // AKA "down()"
+  // Invariant: Only the thread associated with the Event/PlatformEvent
+  // may call park().
+  // TODO: assert that _Assoc != NULL or _Assoc == Self
+  int v;
+  for (;;) {
+    v = _Event;
+    if (Atomic::cmpxchg (v-1, &_Event, v) == v) break;
+  }
+  guarantee (v >= 0, "invariant");
+  if (v == 0) {
+    // Do this the hard way by blocking ...
+    int status = pthread_mutex_lock(_mutex);
+    assert_status(status == 0, status, "mutex_lock");
+    guarantee (_nParked == 0, "invariant");
+    ++ _nParked;
+    while (_Event < 0) {
+      status = pthread_cond_wait(_cond, _mutex);
+      assert_status(status == 0 || status == ETIMEDOUT, status, "cond_timedwait");
+    }
+    -- _nParked;
+
+    // In theory we could move the ST of 0 into _Event past the unlock(),
+    // but then we'd need a MEMBAR after the ST.
+    _Event = 0;
+    status = pthread_mutex_unlock(_mutex);
+    assert_status(status == 0, status, "mutex_unlock");
+  }
+  guarantee (_Event >= 0, "invariant");
+}
+
+int os::PlatformEvent::park(jlong millis) {
+  guarantee (_nParked == 0, "invariant");
+
+  int v;
+  for (;;) {
+    v = _Event;
+    if (Atomic::cmpxchg (v-1, &_Event, v) == v) break;
+  }
+  guarantee (v >= 0, "invariant");
+  if (v != 0) return OS_OK;
+
+  // We do this the hard way, by blocking the thread.
+  // Consider enforcing a minimum timeout value.
+  struct timespec abst;
+  compute_abstime(&abst, millis);
+
+  int ret = OS_TIMEOUT;
+  int status = pthread_mutex_lock(_mutex);
+  assert_status(status == 0, status, "mutex_lock");
+  guarantee (_nParked == 0, "invariant");
+  ++_nParked;
+
+  // Object.wait(timo) will return because of
+  // (a) notification
+  // (b) timeout
+  // (c) thread.interrupt
+  //
+  // Thread.interrupt and object.notify{All} both call Event::set.
+  // That is, we treat thread.interrupt as a special case of notification.
+  // The underlying Solaris implementation, cond_timedwait, admits
+  // spurious/premature wakeups, but the JLS/JVM spec prevents the
+  // JVM from making those visible to Java code. As such, we must
+  // filter out spurious wakeups. We assume all ETIME returns are valid.
+  //
+  // TODO: properly differentiate simultaneous notify+interrupt.
+  // In that case, we should propagate the notify to another waiter.
+
+  while (_Event < 0) {
+    status = pthread_cond_timedwait(_cond, _mutex, &abst);
+    assert_status(status == 0 || status == ETIMEDOUT,
+          status, "cond_timedwait");
+    if (!FilterSpuriousWakeups) break;         // previous semantics
+    if (status == ETIMEDOUT) break;
+    // We consume and ignore EINTR and spurious wakeups.
+  }
+  --_nParked;
+  if (_Event >= 0) {
+     ret = OS_OK;
+  }
+  _Event = 0;
+  status = pthread_mutex_unlock(_mutex);
+  assert_status(status == 0, status, "mutex_unlock");
+  assert (_nParked == 0, "invariant");
+  return ret;
+}
+
+void os::PlatformEvent::unpark() {
+  int v, AnyWaiters;
+  for (;;) {
+    v = _Event;
+    if (v > 0) {
+      // The LD of _Event could have reordered or be satisfied
+      // by a read-aside from this processor's write buffer.
+      // To avoid problems execute a barrier and then
+      // ratify the value.
+      OrderAccess::fence();
+      if (_Event == v) return;
+      continue;
+    }
+    if (Atomic::cmpxchg (v+1, &_Event, v) == v) break;
+  }
+  if (v < 0) {
+    // Wait for the thread associated with the event to vacate
+    int status = pthread_mutex_lock(_mutex);
+    assert_status(status == 0, status, "mutex_lock");
+    AnyWaiters = _nParked;
+
+    if (AnyWaiters != 0) {
+      // We intentional signal *after* dropping the lock
+      // to avoid a common class of futile wakeups.
+      status = pthread_cond_signal(_cond);
+      assert_status(status == 0, status, "cond_signal");
+    }
+    // Mutex should be locked for pthread_cond_signal(_cond).
+    status = pthread_mutex_unlock(_mutex);
+    assert_status(status == 0, status, "mutex_unlock");
+  }
+
+  // Note that we signal() _after dropping the lock for "immortal" Events.
+  // This is safe and avoids a common class of futile wakeups. In rare
+  // circumstances this can cause a thread to return prematurely from
+  // cond_{timed}wait() but the spurious wakeup is benign and the victim will
+  // simply re-test the condition and re-park itself.
+}
+
+
+// JSR166
+// -------------------------------------------------------
+
+//
+// The solaris and linux implementations of park/unpark are fairly
+// conservative for now, but can be improved. They currently use a
+// mutex/condvar pair, plus a a count.
+// Park decrements count if > 0, else does a condvar wait. Unpark
+// sets count to 1 and signals condvar. Only one thread ever waits
+// on the condvar. Contention seen when trying to park implies that someone
+// is unparking you, so don't wait. And spurious returns are fine, so there
+// is no need to track notifications.
+//
+
+#define MAX_SECS 100000000
+//
+// This code is common to linux and solaris and will be moved to a
+// common place in dolphin.
+//
+// The passed in time value is either a relative time in nanoseconds
+// or an absolute time in milliseconds. Either way it has to be unpacked
+// into suitable seconds and nanoseconds components and stored in the
+// given timespec structure.
+// Given time is a 64-bit value and the time_t used in the timespec is only
+// a signed-32-bit value (except on 64-bit Linux) we have to watch for
+// overflow if times way in the future are given. Further on Solaris versions
+// prior to 10 there is a restriction (see cond_timedwait) that the specified
+// number of seconds, in abstime, is less than current_time + 100,000,000.
+// As it will be 28 years before "now + 100000000" will overflow we can
+// ignore overflow and just impose a hard-limit on seconds using the value
+// of "now + 100,000,000". This places a limit on the timeout of about 3.17
+// years from "now".
+//
+
+static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
+  assert (time > 0, "convertTime");
+
+  struct timeval now;
+  int status = gettimeofday(&now, NULL);
+  assert(status == 0, "gettimeofday");
+
+  time_t max_secs = now.tv_sec + MAX_SECS;
+
+  if (isAbsolute) {
+    jlong secs = time / 1000;
+    if (secs > max_secs) {
+      absTime->tv_sec = max_secs;
+    }
+    else {
+      absTime->tv_sec = secs;
+    }
+    absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
+  }
+  else {
+    jlong secs = time / NANOSECS_PER_SEC;
+    if (secs >= MAX_SECS) {
+      absTime->tv_sec = max_secs;
+      absTime->tv_nsec = 0;
+    }
+    else {
+      absTime->tv_sec = now.tv_sec + secs;
+      absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
+      if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
+        absTime->tv_nsec -= NANOSECS_PER_SEC;
+        ++absTime->tv_sec; // note: this must be <= max_secs
+      }
+    }
+  }
+  assert(absTime->tv_sec >= 0, "tv_sec < 0");
+  assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs");
+  assert(absTime->tv_nsec >= 0, "tv_nsec < 0");
+  assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec");
+}
+
+void Parker::park(bool isAbsolute, jlong time) {
+  // Optional fast-path check:
+  // Return immediately if a permit is available.
+  if (_counter > 0) {
+      _counter = 0;
+      OrderAccess::fence();
+      return;
+  }
+
+  Thread* thread = Thread::current();
+  assert(thread->is_Java_thread(), "Must be JavaThread");
+  JavaThread *jt = (JavaThread *)thread;
+
+  // Optional optimization -- avoid state transitions if there's an interrupt pending.
+  // Check interrupt before trying to wait
+  if (Thread::is_interrupted(thread, false)) {
+    return;
+  }
+
+  // Next, demultiplex/decode time arguments
+  timespec absTime;
+  if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all
+    return;
+  }
+  if (time > 0) {
+    unpackTime(&absTime, isAbsolute, time);
+  }
+
+
+  // Enter safepoint region
+  // Beware of deadlocks such as 6317397.
+  // The per-thread Parker:: mutex is a classic leaf-lock.
+  // In particular a thread must never block on the Threads_lock while
+  // holding the Parker:: mutex. If safepoints are pending both the
+  // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
+  ThreadBlockInVM tbivm(jt);
+
+  // Don't wait if cannot get lock since interference arises from
+  // unblocking. Also. check interrupt before trying wait
+  if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) {
+    return;
+  }
+
+  int status;
+  if (_counter > 0) { // no wait needed
+    _counter = 0;
+    status = pthread_mutex_unlock(_mutex);
+    assert (status == 0, "invariant");
+    OrderAccess::fence();
+    return;
+  }
+
+#ifdef ASSERT
+  // Don't catch signals while blocked; let the running threads have the signals.
+  // (This allows a debugger to break into the running thread.)
+  sigset_t oldsigs;
+  sigset_t* allowdebug_blocked = os::Aix::allowdebug_blocked_signals();
+  pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs);
+#endif
+
+  OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+  jt->set_suspend_equivalent();
+  // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
+
+  if (time == 0) {
+    status = pthread_cond_wait (_cond, _mutex);
+  } else {
+    status = pthread_cond_timedwait (_cond, _mutex, &absTime);
+    if (status != 0 && WorkAroundNPTLTimedWaitHang) {
+      pthread_cond_destroy (_cond);
+      pthread_cond_init    (_cond, NULL);
+    }
+  }
+  assert_status(status == 0 || status == EINTR ||
+                status == ETIME || status == ETIMEDOUT,
+                status, "cond_timedwait");
+
+#ifdef ASSERT
+  pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
+#endif
+
+  _counter = 0;
+  status = pthread_mutex_unlock(_mutex);
+  assert_status(status == 0, status, "invariant");
+  // If externally suspended while waiting, re-suspend
+  if (jt->handle_special_suspend_equivalent_condition()) {
+    jt->java_suspend_self();
+  }
+
+  OrderAccess::fence();
+}
+
+void Parker::unpark() {
+  int s, status;
+  status = pthread_mutex_lock(_mutex);
+  assert (status == 0, "invariant");
+  s = _counter;
+  _counter = 1;
+  if (s < 1) {
+    if (WorkAroundNPTLTimedWaitHang) {
+      status = pthread_cond_signal (_cond);
+      assert (status == 0, "invariant");
+      status = pthread_mutex_unlock(_mutex);
+      assert (status == 0, "invariant");
+    } else {
+      status = pthread_mutex_unlock(_mutex);
+      assert (status == 0, "invariant");
+      status = pthread_cond_signal (_cond);
+      assert (status == 0, "invariant");
+    }
+  } else {
+    pthread_mutex_unlock(_mutex);
+    assert (status == 0, "invariant");
+  }
+}
+
+
+extern char** environ;
+
+// Run the specified command in a separate process. Return its exit value,
+// or -1 on failure (e.g. can't fork a new process).
+// Unlike system(), this function can be called from signal handler. It
+// doesn't block SIGINT et al.
+int os::fork_and_exec(char* cmd) {
+  Unimplemented();
+  return 0;
+}
+
+// is_headless_jre()
+//
+// Test for the existence of xawt/libmawt.so or libawt_xawt.so
+// in order to report if we are running in a headless jre.
+//
+// Since JDK8 xawt/libmawt.so is moved into the same directory
+// as libawt.so, and renamed libawt_xawt.so
+bool os::is_headless_jre() {
+  struct stat statbuf;
+  char buf[MAXPATHLEN];
+  char libmawtpath[MAXPATHLEN];
+  const char *xawtstr  = "/xawt/libmawt.so";
+  const char *new_xawtstr = "/libawt_xawt.so";
+
+  char *p;
+
+  // Get path to libjvm.so
+  os::jvm_path(buf, sizeof(buf));
+
+  // Get rid of libjvm.so
+  p = strrchr(buf, '/');
+  if (p == NULL) return false;
+  else *p = '\0';
+
+  // Get rid of client or server
+  p = strrchr(buf, '/');
+  if (p == NULL) return false;
+  else *p = '\0';
+
+  // check xawt/libmawt.so
+  strcpy(libmawtpath, buf);
+  strcat(libmawtpath, xawtstr);
+  if (::stat(libmawtpath, &statbuf) == 0) return false;
+
+  // check libawt_xawt.so
+  strcpy(libmawtpath, buf);
+  strcat(libmawtpath, new_xawtstr);
+  if (::stat(libmawtpath, &statbuf) == 0) return false;
+
+  return true;
+}
+
+// Get the default path to the core file
+// Returns the length of the string
+int os::get_core_path(char* buffer, size_t bufferSize) {
+  const char* p = get_current_directory(buffer, bufferSize);
+
+  if (p == NULL) {
+    assert(p != NULL, "failed to get current directory");
+    return 0;
+  }
+
+  return strlen(buffer);
+}
diff -r 4acea56cea4c src/os/aix/vm/os_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/os_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 1999, 2010, 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();
+
+  // 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
diff -r 4acea56cea4c src/os/aix/vm/os_aix.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/os_aix.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1999, 2011, 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
diff -r 4acea56cea4c src/os/aix/vm/os_share_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/os_share_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999, 2010, 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
diff -r 4acea56cea4c src/os/aix/vm/perfMemory_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/perfMemory_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,1026 @@
+/*
+ * Copyright (c) 2001, 2010, 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 "classfile/vmSymbols.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/oop.inline.hpp"
+#include "os_aix.inline.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/perfMemory.hpp"
+#include "utilities/exceptions.hpp"
+
+// put OS-includes here
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <errno.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# include <signal.h>
+# include <pwd.h>
+
+static char* backing_store_file_name = NULL;  // name of the backing store
+                                              // file, if successfully created.
+
+// Standard Memory Implementation Details
+
+// create the PerfData memory region in standard memory.
+//
+static char* create_standard_memory(size_t size) {
+
+  // allocate an aligned chuck of memory
+  char* mapAddress = os::reserve_memory(size);
+
+  if (mapAddress == NULL) {
+    return NULL;
+  }
+
+  // commit memory
+  if (!os::commit_memory(mapAddress, size)) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("Could not commit PerfData memory\n");
+    }
+    os::release_memory(mapAddress, size);
+    return NULL;
+  }
+
+  return mapAddress;
+}
+
+// delete the PerfData memory region
+//
+static void delete_standard_memory(char* addr, size_t size) {
+
+  // there are no persistent external resources to cleanup for standard
+  // memory. since DestroyJavaVM does not support unloading of the JVM,
+  // cleanup of the memory resource is not performed. The memory will be
+  // reclaimed by the OS upon termination of the process.
+  //
+  return;
+}
+
+// save the specified memory region to the given file
+//
+// Note: this function might be called from signal handler (by os::abort()),
+// don't allocate heap memory.
+//
+static void save_memory_to_file(char* addr, size_t size) {
+
+  const char* destfile = PerfMemory::get_perfdata_file_path();
+  assert(destfile[0] != '\0', "invalid PerfData file path");
+
+  int result;
+
+  RESTARTABLE(::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE),
+              result);;
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("Could not create Perfdata save file: %s: %s\n",
+              destfile, strerror(errno));
+    }
+  } else {
+    int fd = result;
+
+    for (size_t remaining = size; remaining > 0;) {
+
+      RESTARTABLE(::write(fd, addr, remaining), result);
+      if (result == OS_ERR) {
+        if (PrintMiscellaneous && Verbose) {
+          warning("Could not write Perfdata save file: %s: %s\n",
+                  destfile, strerror(errno));
+        }
+        break;
+      }
+
+      remaining -= (size_t)result;
+      addr += result;
+    }
+
+    RESTARTABLE(::close(fd), result);
+    if (PrintMiscellaneous && Verbose) {
+      if (result == OS_ERR) {
+        warning("Could not close %s: %s\n", destfile, strerror(errno));
+      }
+    }
+  }
+  FREE_C_HEAP_ARRAY(char, destfile, mtInternal);
+}
+
+
+// Shared Memory Implementation Details
+
+// Note: the solaris and linux shared memory implementation uses the mmap
+// interface with a backing store file to implement named shared memory.
+// Using the file system as the name space for shared memory allows a
+// common name space to be supported across a variety of platforms. It
+// also provides a name space that Java applications can deal with through
+// simple file apis.
+//
+// The solaris and linux implementations store the backing store file in
+// a user specific temporary directory located in the /tmp file system,
+// which is always a local file system and is sometimes a RAM based file
+// system.
+
+// return the user specific temporary directory name.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_tmp_dir(const char* user) {
+
+  const char* tmpdir = os::get_temp_directory();
+  const char* perfdir = PERFDATA_NAME;
+  size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
+  char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
+
+  // construct the path name to user specific tmp directory
+  snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
+
+  return dirname;
+}
+
+// convert the given file name into a process id. if the file
+// does not meet the file naming constraints, return 0.
+//
+static pid_t filename_to_pid(const char* filename) {
+
+  // a filename that doesn't begin with a digit is not a
+  // candidate for conversion.
+  //
+  if (!isdigit(*filename)) {
+    return 0;
+  }
+
+  // check if file name can be converted to an integer without
+  // any leftover characters.
+  //
+  char* remainder = NULL;
+  errno = 0;
+  pid_t pid = (pid_t)strtol(filename, &remainder, 10);
+
+  if (errno != 0) {
+    return 0;
+  }
+
+  // check for left over characters. If any, then the filename is
+  // not a candidate for conversion.
+  //
+  if (remainder != NULL && *remainder != '\0') {
+    return 0;
+  }
+
+  // successful conversion, return the pid
+  return pid;
+}
+
+
+// check if the given path is considered a secure directory for
+// the backing store files. Returns true if the directory exists
+// and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_directory_secure(const char* path) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::lstat(path, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // the path exists, now check it's mode
+  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
+    // the path represents a link or some non-directory file type,
+    // which is not what we expected. declare it insecure.
+    //
+    return false;
+  }
+  else {
+    // we have an existing directory, check if the permissions are safe.
+    //
+    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+      // the directory is open for writing and could be subjected
+      // to a symlnk attack. declare it insecure.
+      //
+      return false;
+    }
+  }
+  return true;
+}
+
+
+// return the user name for the given user id
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_name(uid_t uid) {
+
+  struct passwd pwent;
+
+  // determine the max pwbuf size from sysconf, and hardcode
+  // a default if this not available through sysconf.
+  //
+  long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+  if (bufsize == -1)
+    bufsize = 1024;
+
+  char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
+
+  // POSIX interface to getpwuid_r is used on LINUX
+  struct passwd* p;
+  int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p);
+
+  if (result != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
+    if (PrintMiscellaneous && Verbose) {
+      if (result != 0) {
+        warning("Could not retrieve passwd entry: %s\n",
+                strerror(result));
+      }
+      else if (p == NULL) {
+        // this check is added to protect against an observed problem
+        // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0,
+        // indicating success, but has p == NULL. This was observed when
+        // inserting a file descriptor exhaustion fault prior to the call
+        // getpwuid_r() call. In this case, error is set to the appropriate
+        // error condition, but this is undocumented behavior. This check
+        // is safe under any condition, but the use of errno in the output
+        // message may result in an erroneous message.
+        // Bug Id 89052 was opened with RedHat.
+        //
+        warning("Could not retrieve passwd entry: %s\n",
+                strerror(errno));
+      }
+      else {
+        warning("Could not determine user name: %s\n",
+                p->pw_name == NULL ? "pw_name = NULL" :
+                                     "pw_name zero length");
+      }
+    }
+    FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
+    return NULL;
+  }
+
+  char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal);
+  strcpy(user_name, p->pw_name);
+
+  FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
+  return user_name;
+}
+
+// return the name of the user that owns the process identified by vmid.
+//
+// This method uses a slow directory search algorithm to find the backing
+// store file for the specified vmid and returns the user name, as determined
+// by the user name suffix of the hsperfdata_<username> directory name.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_name_slow(int vmid, TRAPS) {
+
+  // short circuit the directory search if the process doesn't even exist.
+  if (kill(vmid, 0) == OS_ERR) {
+    if (errno == ESRCH) {
+      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found");
+    }
+    else /* EPERM */ {
+      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+    }
+  }
+
+  // directory search
+  char* oldest_user = NULL;
+  time_t oldest_ctime = 0;
+
+  const char* tmpdirname = os::get_temp_directory();
+
+  DIR* tmpdirp = os::opendir(tmpdirname);
+
+  if (tmpdirp == NULL) {
+    return NULL;
+  }
+
+  // for each entry in the directory that matches the pattern hsperfdata_*,
+  // open the directory and check if the file for the given vmid exists.
+  // The file with the expected name and the latest creation date is used
+  // to determine the user name for the process id.
+  //
+  struct dirent* dentry;
+  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
+  errno = 0;
+  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+
+    // check if the directory entry is a hsperfdata file
+    if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
+      continue;
+    }
+
+    char* usrdir_name = NEW_C_HEAP_ARRAY(char,
+                              strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
+    strcpy(usrdir_name, tmpdirname);
+    strcat(usrdir_name, "/");
+    strcat(usrdir_name, dentry->d_name);
+
+    DIR* subdirp = os::opendir(usrdir_name);
+
+    if (subdirp == NULL) {
+      FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
+      continue;
+    }
+
+    // Since we don't create the backing store files in directories
+    // pointed to by symbolic links, we also don't follow them when
+    // looking for the files. We check for a symbolic link after the
+    // call to opendir in order to eliminate a small window where the
+    // symlink can be exploited.
+    //
+    if (!is_directory_secure(usrdir_name)) {
+      FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
+      os::closedir(subdirp);
+      continue;
+    }
+
+    struct dirent* udentry;
+    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
+    errno = 0;
+    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+
+      if (filename_to_pid(udentry->d_name) == vmid) {
+        struct stat statbuf;
+        int result;
+
+        char* filename = NEW_C_HEAP_ARRAY(char,
+                            strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);
+
+        strcpy(filename, usrdir_name);
+        strcat(filename, "/");
+        strcat(filename, udentry->d_name);
+
+        // don't follow symbolic links for the file
+        RESTARTABLE(::lstat(filename, &statbuf), result);
+        if (result == OS_ERR) {
+           FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+           continue;
+        }
+
+        // skip over files that are not regular files.
+        if (!S_ISREG(statbuf.st_mode)) {
+          FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+          continue;
+        }
+
+        // compare and save filename with latest creation time
+        if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) {
+
+          if (statbuf.st_ctime > oldest_ctime) {
+            char* user = strchr(dentry->d_name, '_') + 1;
+
+            if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal);
+            oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
+
+            strcpy(oldest_user, user);
+            oldest_ctime = statbuf.st_ctime;
+          }
+        }
+
+        FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+      }
+    }
+    os::closedir(subdirp);
+    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
+    FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
+  }
+  os::closedir(tmpdirp);
+  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
+
+  return(oldest_user);
+}
+
+// return the name of the user that owns the JVM indicated by the given vmid.
+//
+static char* get_user_name(int vmid, TRAPS) {
+  return get_user_name_slow(vmid, CHECK_NULL);
+}
+
+// return the file name of the backing store file for the named
+// shared memory region for the given user name and vmid.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_sharedmem_filename(const char* dirname, int vmid) {
+
+  // add 2 for the file separator and a null terminator.
+  size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
+
+  char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
+  snprintf(name, nbytes, "%s/%d", dirname, vmid);
+
+  return name;
+}
+
+
+// remove file
+//
+// this method removes the file specified by the given path
+//
+static void remove_file(const char* path) {
+
+  int result;
+
+  // if the file is a directory, the following unlink will fail. since
+  // we don't expect to find directories in the user temp directory, we
+  // won't try to handle this situation. even if accidentially or
+  // maliciously planted, the directory's presence won't hurt anything.
+  //
+  RESTARTABLE(::unlink(path), result);
+  if (PrintMiscellaneous && Verbose && result == OS_ERR) {
+    if (errno != ENOENT) {
+      warning("Could not unlink shared memory backing"
+              " store file %s : %s\n", path, strerror(errno));
+    }
+  }
+}
+
+
+// remove file
+//
+// this method removes the file with the given file name in the
+// named directory.
+//
+static void remove_file(const char* dirname, const char* filename) {
+
+  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
+  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
+
+  strcpy(path, dirname);
+  strcat(path, "/");
+  strcat(path, filename);
+
+  remove_file(path);
+
+  FREE_C_HEAP_ARRAY(char, path, mtInternal);
+}
+
+
+// cleanup stale shared memory resources
+//
+// This method attempts to remove all stale shared memory files in
+// the named user temporary directory. It scans the named directory
+// for files matching the pattern ^$[0-9]*$. For each file found, the
+// process id is extracted from the file name and a test is run to
+// determine if the process is alive. If the process is not alive,
+// any stale file resources are removed.
+//
+static void cleanup_sharedmem_resources(const char* dirname) {
+
+  // open the user temp directory
+  DIR* dirp = os::opendir(dirname);
+
+  if (dirp == NULL) {
+    // directory doesn't exist, so there is nothing to cleanup
+    return;
+  }
+
+  if (!is_directory_secure(dirname)) {
+    // the directory is not a secure directory
+    return;
+  }
+
+  // for each entry in the directory that matches the expected file
+  // name pattern, determine if the file resources are stale and if
+  // so, remove the file resources. Note, instrumented HotSpot processes
+  // for this user may start and/or terminate during this search and
+  // remove or create new files in this directory. The behavior of this
+  // loop under these conditions is dependent upon the implementation of
+  // opendir/readdir.
+  //
+  struct dirent* entry;
+  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+  errno = 0;
+  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+
+    pid_t pid = filename_to_pid(entry->d_name);
+
+    if (pid == 0) {
+
+      if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
+
+        // attempt to remove all unexpected files, except "." and ".."
+        remove_file(dirname, entry->d_name);
+      }
+
+      errno = 0;
+      continue;
+    }
+
+    // we now have a file name that converts to a valid integer
+    // that could represent a process id . if this process id
+    // matches the current process id or the process is not running,
+    // then remove the stale file resources.
+    //
+    // process liveness is detected by sending signal number 0 to
+    // the process id (see kill(2)). if kill determines that the
+    // process does not exist, then the file resources are removed.
+    // if kill determines that that we don't have permission to
+    // signal the process, then the file resources are assumed to
+    // be stale and are removed because the resources for such a
+    // process should be in a different user specific directory.
+    //
+    if ((pid == os::current_process_id()) ||
+        (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
+
+        remove_file(dirname, entry->d_name);
+    }
+    errno = 0;
+  }
+  os::closedir(dirp);
+  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
+}
+
+// make the user specific temporary directory. Returns true if
+// the directory exists and is secure upon return. Returns false
+// if the directory exists but is either a symlink, is otherwise
+// insecure, or if an error occurred.
+//
+static bool make_user_tmp_dir(const char* dirname) {
+
+  // create the directory with 0755 permissions. note that the directory
+  // will be owned by euid::egid, which may not be the same as uid::gid.
+  //
+  if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
+    if (errno == EEXIST) {
+      // The directory already exists and was probably created by another
+      // JVM instance. However, this could also be the result of a
+      // deliberate symlink. Verify that the existing directory is safe.
+      //
+      if (!is_directory_secure(dirname)) {
+        // directory is not secure
+        if (PrintMiscellaneous && Verbose) {
+          warning("%s directory is insecure\n", dirname);
+        }
+        return false;
+      }
+    }
+    else {
+      // we encountered some other failure while attempting
+      // to create the directory
+      //
+      if (PrintMiscellaneous && Verbose) {
+        warning("could not create directory %s: %s\n",
+                dirname, strerror(errno));
+      }
+      return false;
+    }
+  }
+  return true;
+}
+
+// create the shared memory file resources
+//
+// This method creates the shared memory file with the given size
+// This method also creates the user specific temporary directory, if
+// it does not yet exist.
+//
+static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) {
+
+  // make the user temporary directory
+  if (!make_user_tmp_dir(dirname)) {
+    // could not make/find the directory or the found directory
+    // was not secure
+    return -1;
+  }
+
+  int result;
+
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not create file %s: %s\n", filename, strerror(errno));
+    }
+    return -1;
+  }
+
+  // save the file descriptor
+  int fd = result;
+
+  // set the file size
+  RESTARTABLE(::ftruncate(fd, (off_t)size), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not set shared memory file size: %s\n", strerror(errno));
+    }
+    RESTARTABLE(::close(fd), result);
+    return -1;
+  }
+
+  return fd;
+}
+
+// open the shared memory file for the given user and vmid. returns
+// the file descriptor for the open file or -1 if the file could not
+// be opened.
+//
+static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
+
+  // open the file
+  int result;
+  RESTARTABLE(::open(filename, oflags), result);
+  if (result == OS_ERR) {
+    if (errno == ENOENT) {
+      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found");
+    }
+    else if (errno == EACCES) {
+      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied");
+    }
+    else {
+      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+    }
+  }
+
+  return result;
+}
+
+// create a named shared memory region. returns the address of the
+// memory region on success or NULL on failure. A return value of
+// NULL will ultimately disable the shared memory feature.
+//
+// On Solaris and Linux, the name space for shared memory objects
+// is the file system name space.
+//
+// A monitoring application attaching to a JVM does not need to know
+// the file system name of the shared memory object. However, it may
+// be convenient for applications to discover the existence of newly
+// created and terminating JVMs by watching the file system name space
+// for files being created or removed.
+//
+static char* mmap_create_shared(size_t size) {
+
+  int result;
+  int fd;
+  char* mapAddress;
+
+  int vmid = os::current_process_id();
+
+  char* user_name = get_user_name(geteuid());
+
+  if (user_name == NULL)
+    return NULL;
+
+  char* dirname = get_user_tmp_dir(user_name);
+  char* filename = get_sharedmem_filename(dirname, vmid);
+
+  // cleanup any stale shared memory files
+  cleanup_sharedmem_resources(dirname);
+
+  assert(((size > 0) && (size % os::vm_page_size() == 0)),
+         "unexpected PerfMemory region size");
+
+  fd = create_sharedmem_resources(dirname, filename, size);
+
+  FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
+  FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+
+  if (fd == -1) {
+    FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+    return NULL;
+  }
+
+  mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+  // attempt to close the file - restart it if it was interrupted,
+  // but ignore other failures
+  RESTARTABLE(::close(fd), result);
+  assert(result != OS_ERR, "could not close file");
+
+  if (mapAddress == MAP_FAILED) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("mmap failed -  %s\n", strerror(errno));
+    }
+    remove_file(filename);
+    FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+    return NULL;
+  }
+
+  // save the file name for use in delete_shared_memory()
+  backing_store_file_name = filename;
+
+  // clear the shared memory region
+  (void)::memset((void*) mapAddress, 0, size);
+
+  return mapAddress;
+}
+
+// release a named shared memory region
+//
+static void unmap_shared(char* addr, size_t bytes) {
+  // Do not rely on os::reserve_memory/os::release_memory to use mmap.
+  // Use os::reserve_memory/os::release_memory for PerfDisableSharedMem=1, mmap/munmap for PerfDisableSharedMem=0
+  if (::munmap(addr, bytes) == -1) {
+    warning("perfmemory: munmap failed (%d)\n", errno);
+  }
+}
+
+// create the PerfData memory region in shared memory.
+//
+static char* create_shared_memory(size_t size) {
+
+  // create the shared memory region.
+  return mmap_create_shared(size);
+}
+
+// delete the shared PerfData memory region
+//
+static void delete_shared_memory(char* addr, size_t size) {
+
+  // cleanup the persistent shared memory resources. since DestroyJavaVM does
+  // not support unloading of the JVM, unmapping of the memory resource is
+  // not performed. The memory will be reclaimed by the OS upon termination of
+  // the process. The backing store file is deleted from the file system.
+
+  assert(!PerfDisableSharedMem, "shouldn't be here");
+
+  if (backing_store_file_name != NULL) {
+    remove_file(backing_store_file_name);
+    // Don't.. Free heap memory could deadlock os::abort() if it is called
+    // from signal handler. OS will reclaim the heap memory.
+    // FREE_C_HEAP_ARRAY(char, backing_store_file_name, mtInternal);
+    backing_store_file_name = NULL;
+  }
+}
+
+// return the size of the file for the given file descriptor
+// or 0 if it is not a valid size for a shared memory file
+//
+static size_t sharedmem_filesize(int fd, TRAPS) {
+
+  struct stat statbuf;
+  int result;
+
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed: %s\n", strerror(errno));
+    }
+    THROW_MSG_0(vmSymbols::java_io_IOException(),
+                "Could not determine PerfMemory size");
+  }
+
+  if ((statbuf.st_size == 0) ||
+     ((size_t)statbuf.st_size % os::vm_page_size() != 0)) {
+    THROW_MSG_0(vmSymbols::java_lang_Exception(),
+                "Invalid PerfMemory size");
+  }
+
+  return (size_t)statbuf.st_size;
+}
+
+// attach to a named shared memory region.
+//
+static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) {
+
+  char* mapAddress;
+  int result;
+  int fd;
+  size_t size;
+  const char* luser = NULL;
+
+  int mmap_prot;
+  int file_flags;
+
+  ResourceMark rm;
+
+  // map the high level access mode to the appropriate permission
+  // constructs for the file and the shared memory mapping.
+  if (mode == PerfMemory::PERF_MODE_RO) {
+    mmap_prot = PROT_READ;
+    file_flags = O_RDONLY;
+  }
+  else if (mode == PerfMemory::PERF_MODE_RW) {
+#ifdef LATER
+    mmap_prot = PROT_READ | PROT_WRITE;
+    file_flags = O_RDWR;
+#else
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Unsupported access mode");
+#endif
+  }
+  else {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Illegal access mode");
+  }
+
+  if (user == NULL || strlen(user) == 0) {
+    luser = get_user_name(vmid, CHECK);
+  }
+  else {
+    luser = user;
+  }
+
+  if (luser == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Could not map vmid to user Name");
+  }
+
+  char* dirname = get_user_tmp_dir(luser);
+
+  // since we don't follow symbolic links when creating the backing
+  // store file, we don't follow them when attaching either.
+  //
+  if (!is_directory_secure(dirname)) {
+    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Process not found");
+  }
+
+  char* filename = get_sharedmem_filename(dirname, vmid);
+
+  // copy heap memory to resource memory. the open_sharedmem_file
+  // method below need to use the filename, but could throw an
+  // exception. using a resource array prevents the leak that
+  // would otherwise occur.
+  char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1);
+  strcpy(rfilename, filename);
+
+  // free the c heap resources that are no longer needed
+  if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+  FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+  FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+
+  // open the shared memory file for the give vmid
+  fd = open_sharedmem_file(rfilename, file_flags, CHECK);
+  assert(fd != OS_ERR, "unexpected value");
+
+  if (*sizep == 0) {
+    size = sharedmem_filesize(fd, CHECK);
+    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
+  }
+
+  mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
+
+  // attempt to close the file - restart if it gets interrupted,
+  // but ignore other failures
+  RESTARTABLE(::close(fd), result);
+  assert(result != OS_ERR, "could not close file");
+
+  if (mapAddress == MAP_FAILED) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("mmap failed: %s\n", strerror(errno));
+    }
+    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
+              "Could not map PerfMemory");
+  }
+
+  *addr = mapAddress;
+  *sizep = size;
+
+  if (PerfTraceMemOps) {
+    tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at "
+               INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress);
+  }
+}
+
+
+
+
+// create the PerfData memory region
+//
+// This method creates the memory region used to store performance
+// data for the JVM. The memory may be created in standard or
+// shared memory.
+//
+void PerfMemory::create_memory_region(size_t size) {
+
+  if (PerfDisableSharedMem) {
+    // do not share the memory for the performance data.
+    _start = create_standard_memory(size);
+  }
+  else {
+    _start = create_shared_memory(size);
+    if (_start == NULL) {
+
+      // creation of the shared memory region failed, attempt
+      // to create a contiguous, non-shared memory region instead.
+      //
+      if (PrintMiscellaneous && Verbose) {
+        warning("Reverting to non-shared PerfMemory region.\n");
+      }
+      PerfDisableSharedMem = true;
+      _start = create_standard_memory(size);
+    }
+  }
+
+  if (_start != NULL) _capacity = size;
+
+}
+
+// delete the PerfData memory region
+//
+// This method deletes the memory region used to store performance
+// data for the JVM. The memory region indicated by the <address, size>
+// tuple will be inaccessible after a call to this method.
+//
+void PerfMemory::delete_memory_region() {
+
+  assert((start() != NULL && capacity() > 0), "verify proper state");
+
+  // If user specifies PerfDataSaveFile, it will save the performance data
+  // to the specified file name no matter whether PerfDataSaveToFile is specified
+  // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag
+  // -XX:+PerfDataSaveToFile.
+  if (PerfDataSaveToFile || PerfDataSaveFile != NULL) {
+    save_memory_to_file(start(), capacity());
+  }
+
+  if (PerfDisableSharedMem) {
+    delete_standard_memory(start(), capacity());
+  }
+  else {
+    delete_shared_memory(start(), capacity());
+  }
+}
+
+// attach to the PerfData memory region for another JVM
+//
+// This method returns an <address, size> tuple that points to
+// a memory buffer that is kept reasonably synchronized with
+// the PerfData memory region for the indicated JVM. This
+// buffer may be kept in synchronization via shared memory
+// or some other mechanism that keeps the buffer updated.
+//
+// If the JVM chooses not to support the attachability feature,
+// this method should throw an UnsupportedOperation exception.
+//
+// This implementation utilizes named shared memory to map
+// the indicated process's PerfData memory region into this JVMs
+// address space.
+//
+void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPS) {
+
+  if (vmid == 0 || vmid == os::current_process_id()) {
+     *addrp = start();
+     *sizep = capacity();
+     return;
+  }
+
+  mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK);
+}
+
+// detach from the PerfData memory region of another JVM
+//
+// This method detaches the PerfData memory region of another
+// JVM, specified as an <address, size> tuple of a buffer
+// in this process's address space. This method may perform
+// arbitrary actions to accomplish the detachment. The memory
+// region specified by <address, size> will be inaccessible after
+// a call to this method.
+//
+// If the JVM chooses not to support the attachability feature,
+// this method should throw an UnsupportedOperation exception.
+//
+// This implementation utilizes named shared memory to detach
+// the indicated process's PerfData memory region from this
+// process's address space.
+//
+void PerfMemory::detach(char* addr, size_t bytes, TRAPS) {
+
+  assert(addr != 0, "address sanity check");
+  assert(bytes > 0, "capacity sanity check");
+
+  if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) {
+    // prevent accidental detachment of this process's PerfMemory region
+    return;
+  }
+
+  unmap_shared(addr, bytes);
+}
+
+char* PerfMemory::backing_store_filename() {
+  return backing_store_file_name;
+}
diff -r 4acea56cea4c src/os/aix/vm/porting_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/porting_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "asm/assembler.hpp"
+#include "loadlib_aix.hpp"
+#include "porting_aix.hpp"
+#include "utilities/debug.hpp"
+
+#include <demangle.h>
+#include <sys/debug.h>
+
+//////////////////////////////////
+// Provide implementation for dladdr based on LoadedLibraries pool and
+// traceback table scan (see getFuncName).
+
+// Search traceback table in stack,
+// return procedure name from trace back table.
+#define MAX_FUNC_SEARCH_LEN 0x10000
+// Any PC below this value is considered toast.
+#define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024)
+
+#define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2))
+
+// Align a pointer without having to cast.
+inline char* align_ptr_up(char* ptr, intptr_t alignment) {
+  return (char*) align_size_up((intptr_t)ptr, alignment);
+}
+
+// Trace if verbose to tty.
+// I use these now instead of the Xtrace system because the latter is
+// not available at init time, hence worthless. Until we fix this, all
+// tracing here is done with -XX:+Verbose.
+#define trcVerbose(fmt, ...) { \
+  if (Verbose) { \
+    fprintf(stderr, fmt, ##__VA_ARGS__); \
+    fputc('\n', stderr); fflush(stderr); \
+  } \
+}
+#define ERRBYE(s) { trcVerbose(s); return -1; }
+
+// Unfortunately, the interface of dladdr makes the implementator
+// responsible for maintaining memory for function name/library
+// name. I guess this is because most OS's keep those values as part
+// of the mapped executable image ready to use. On AIX, this doesn't
+// work, so I have to keep the returned strings. For now, I do this in
+// a primitive string map. Should this turn out to be a performance
+// problem, a better hashmap has to be used.
+class fixed_strings {
+  struct node {
+    char* v;
+    node* next;
+  };
+
+  node* first;
+
+  public:
+
+  fixed_strings() : first(0) {}
+  ~fixed_strings() {
+    node* n = first;
+    while (n) {
+      node* p = n;
+      n = n->next;
+      free(p->v);
+      delete p;
+    }
+  }
+
+  char* intern(const char* s) {
+    for (node* n = first; n; n = n->next) {
+      if (strcmp(n->v, s) == 0) {
+        return n->v;
+      }
+    }
+    node* p = new node;
+    p->v = strdup(s);
+    p->next = first;
+    first = p;
+    return p->v;
+  }
+};
+
+static fixed_strings dladdr_fixed_strings;
+
+// Given a code pointer, returns the function name and the displacement.
+// Function looks for the traceback table at the end of the function.
+extern "C" int getFuncName(
+    codeptr_t pc,                    // [in] program counter
+    char* p_name, size_t namelen,    // [out] optional: function name ("" if not available)
+    int* p_displacement,             // [out] optional: displacement (-1 if not available)
+    const struct tbtable** p_tb,     // [out] optional: ptr to traceback table to get further
+                                     //                 information (NULL if not available)
+    char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
+  ) {
+  struct tbtable* tb = 0;
+  unsigned int searchcount = 0;
+
+  // initialize output parameters
+  if (p_name && namelen > 0) {
+    *p_name = '\0';
+  }
+  if (p_errmsg && errmsglen > 0) {
+    *p_errmsg = '\0';
+  }
+  if (p_displacement) {
+    *p_displacement = -1;
+  }
+  if (p_tb) {
+    *p_tb = NULL;
+  }
+
+  // weed out obvious bogus states
+  if (pc < MINIMUM_VALUE_FOR_PC) {
+    ERRBYE("invalid program counter");
+  }
+
+  codeptr_t pc2 = pc;
+
+  // make sure the pointer is word aligned.
+  pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4);
+
+  // Find start of traceback table.
+  // (starts after code, is marked by word-aligned (32bit) zeros)
+  while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) {
+    pc2++;
+  }
+  if (*pc2 != 0) {
+    ERRBYE("could not find traceback table within 5000 bytes of program counter");
+  }
+  //
+  // Set up addressability to the traceback table
+  //
+  tb = (struct tbtable*) (pc2 + 1);
+
+  // Is this really a traceback table? No way to be sure but
+  // some indicators we can check.
+  if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) {
+    // Language specifiers, go from 0 (C) to 14 (Objective C).
+    // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm.
+    ERRBYE("not a traceback table");
+  }
+
+  // Existence of fields in the tbtable extension are contingent upon
+  // specific fields in the base table.  Check for their existence so
+  // that we can address the function name if it exists.
+  pc2 = (codeptr_t) tb +
+    sizeof(struct tbtable_short)/sizeof(int);
+  if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0)
+    pc2++;
+
+  if (tb->tb.has_tboff == TRUE) {
+
+    // I want to know the displacement
+    const unsigned int tb_offset = *pc2;
+    codeptr_t start_of_procedure =
+    (codeptr_t)(((char*)tb) - 4 - tb_offset);  // (-4 to omit leading 0000)
+
+    // Weed out the cases where we did find the wrong traceback table.
+    if (pc < start_of_procedure) {
+      ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter");
+    }
+
+    // return the displacement
+    if (p_displacement) {
+      (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure);
+    }
+
+    pc2++;
+  } else {
+    // return -1 for displacement
+    if (p_displacement) {
+      (*p_displacement) = -1;
+    }
+  }
+
+  if (tb->tb.int_hndl == TRUE)
+    pc2++;
+
+  if (tb->tb.has_ctl == TRUE)
+    pc2 += (*pc2) + 1; // don't care
+
+  //
+  // return function name if it exists.
+  //
+  if (p_name && namelen > 0) {
+    if (tb->tb.name_present) {
+      char buf[256];
+      const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1);
+      memcpy(buf, (char*)pc2 + sizeof(short), l);
+      buf[l] = '\0';
+
+      p_name[0] = '\0';
+
+      // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
+      char* rest;
+      Name* const name = Demangle(buf, rest);
+      if (name) {
+        const char* const demangled_name = name->Text();
+        if (demangled_name) {
+          strncpy(p_name, demangled_name, namelen-1);
+          p_name[namelen-1] = '\0';
+        }
+        delete name;
+      }
+
+      // Fallback: if demangling did not work, just provide the unmangled name.
+      if (p_name[0] == '\0') {
+        strncpy(p_name, buf, namelen-1);
+        p_name[namelen-1] = '\0';
+      }
+
+    } else {
+      strncpy(p_name, "<nameless function>", namelen-1);
+      p_name[namelen-1] = '\0';
+    }
+  }
+  // Return traceback table, if user wants it.
+  if (p_tb) {
+    (*p_tb) = tb;
+  }
+
+  return 0;
+}
+
+// Special implementation of dladdr for Aix based on LoadedLibraries
+// Note: dladdr returns non-zero for ok, 0 for error!
+// Note: dladdr is not posix, but a non-standard GNU extension. So this tries to
+//   fulfill the contract of dladdr on Linux (see http://linux.die.net/man/3/dladdr)
+// Note: addr may be both an AIX function descriptor or a real code pointer
+//   to the entry of a function.
+extern "C"
+int dladdr(void* addr, Dl_info* info) {
+
+  if (!addr) {
+    return 0;
+  }
+
+  assert(info, "");
+
+  int rc = 0;
+
+  const char* const ZEROSTRING = "";
+
+  // Always return a string, even if a "" one. Linux dladdr manpage
+  // does not say anything about returning NULL
+  info->dli_fname = ZEROSTRING;
+  info->dli_sname = ZEROSTRING;
+  info->dli_saddr = NULL;
+
+  address p = (address) addr;
+  const LoadedLibraryModule* lib = NULL;
+
+  enum { noclue, code, data } type = noclue;
+
+  trcVerbose("dladdr(%p)...", p);
+
+  // Note: input address may be a function. I accept both a pointer to
+  // the entry of a function and a pointer to the function decriptor.
+  // (see ppc64 ABI)
+  lib = LoadedLibraries::find_for_text_address(p);
+  if (lib) {
+    type = code;
+  }
+
+  if (!lib) {
+    // Not a pointer into any text segment. Is it a function descriptor?
+    const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p;
+    p = pfd->entry();
+    if (p) {
+      lib = LoadedLibraries::find_for_text_address(p);
+      if (lib) {
+        type = code;
+      }
+    }
+  }
+
+  if (!lib) {
+    // Neither direct code pointer nor function descriptor. A data ptr?
+    p = (address)addr;
+    lib = LoadedLibraries::find_for_data_address(p);
+    if (lib) {
+      type = data;
+    }
+  }
+
+  // If we did find the shared library this address belongs to (either
+  // code or data segment) resolve library path and, if possible, the
+  // symbol name.
+  if (lib) {
+    const char* const interned_libpath =
+      dladdr_fixed_strings.intern(lib->get_fullpath());
+    if (interned_libpath) {
+      info->dli_fname = interned_libpath;
+    }
+
+    if (type == code) {
+
+      // For code symbols resolve function name and displacement. Use
+      // displacement to calc start of function.
+      char funcname[256] = "";
+      int displacement = 0;
+
+      if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
+                      NULL, NULL, 0) == 0) {
+        if (funcname[0] != '\0') {
+          const char* const interned = dladdr_fixed_strings.intern(funcname);
+          info->dli_sname = interned;
+          trcVerbose("... function name: %s ...", interned);
+        }
+
+        // From the displacement calculate the start of the function.
+        if (displacement != -1) {
+          info->dli_saddr = p - displacement;
+        } else {
+          info->dli_saddr = p;
+        }
+      } else {
+
+        // No traceback table found. Just assume the pointer is it.
+        info->dli_saddr = p;
+
+      }
+
+    } else if (type == data) {
+
+      // For data symbols.
+      info->dli_saddr = p;
+
+    } else {
+      ShouldNotReachHere();
+    }
+
+    rc = 1; // success: return 1 [sic]
+
+  }
+
+  // sanity checks.
+  if (rc) {
+    assert(info->dli_fname, "");
+    assert(info->dli_sname, "");
+    assert(info->dli_saddr, "");
+  }
+
+  return rc; // error: return 0 [sic]
+
+}
diff -r 4acea56cea4c src/os/aix/vm/porting_aix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/porting_aix.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stddef.h>
+
+// Header file to contain porting-relevant code which does not have a
+// home anywhere else and which can not go into os_<platform>.h because
+// that header is included inside the os class definition, hence all
+// its content is part of the os class.
+
+// Aix' own version of dladdr().
+// This function tries to mimick dladdr(3) on Linux
+// (see http://linux.die.net/man/3/dladdr)
+// dladdr(3) is not POSIX but a GNU extension, and is not available on AIX.
+//
+// Differences between AIX dladdr and Linux dladdr:
+//
+// 1) Dl_info.dli_fbase: can never work, is disabled.
+//   A loaded image on AIX is divided in multiple segments, at least two
+//   (text and data) but potentially also far more. This is because the loader may
+//   load each member into an own segment, as for instance happens with the libC.a
+// 2) Dl_info.dli_sname: This only works for code symbols (functions); for data, a
+//   zero-length string is returned ("").
+// 3) Dl_info.dli_saddr: For code, this will return the entry point of the function,
+//   not the function descriptor.
+
+typedef struct {
+  const char *dli_fname; // file path of loaded library
+  // void *dli_fbase;
+  const char *dli_sname; // symbol name; "" if not known
+  void *dli_saddr;       // address of *entry* of function; not function descriptor;
+} Dl_info;
+
+// Note: we export this to use it inside J2se too
+#ifdef __cplusplus
+extern "C"
+#endif
+int dladdr(void *addr, Dl_info *info);
+
+
+// The semantics in this file are thus that codeptr_t is a *real code ptr*.
+// This means that any function taking codeptr_t as arguments will assume
+// a real codeptr and won't handle function descriptors (eg getFuncName),
+// whereas functions taking address as args will deal with function
+// descriptors (eg os::dll_address_to_library_name).
+typedef unsigned int* codeptr_t;
+
+// helper function - given a program counter, tries to locate the traceback table and
+// returns info from it (like, most importantly, function name, displacement of the
+// pc inside the function, and the traceback table itself.
+#ifdef __cplusplus
+extern "C"
+#endif
+int getFuncName(
+      codeptr_t pc,                    // [in] program counter
+      char* p_name, size_t namelen,    // [out] optional: user provided buffer for the function name
+      int* p_displacement,             // [out] optional: displacement
+      const struct tbtable** p_tb,     // [out] optional: ptr to traceback table to get further information
+      char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
+    );
diff -r 4acea56cea4c src/os/aix/vm/threadCritical_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/threadCritical_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001, 2010, 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()");
+  }
+}
diff -r 4acea56cea4c src/os/aix/vm/thread_aix.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/thread_aix.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2002, 2011, 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
diff -r 4acea56cea4c src/os/aix/vm/vmError_aix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/vmError_aix.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2003, 2010, 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);
+}
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 1997, 2010, 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
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002, 2010, 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
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP
+#define OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP
+
+#include "runtime/orderAccess.hpp"
+#include "vm_version_ppc.hpp"
+
+// Implementation of class OrderAccess.
+
+// 
+// Machine barrier instructions:
+// 
+// - ppc_sync            Two-way memory barrier, aka fence.
+// - ppc_lwsync          orders  Store|Store,
+//                                Load|Store,
+//                                Load|Load,
+//                       but not Store|Load
+// - ppc_eieio           orders  Store|Store
+// - ppc_isync           Invalidates speculatively executed instructions,
+//                       but isync may complete before storage accesses
+//                       associated with instructions preceding isync have
+//                       been performed.
+// 
+// Semantic barrier instructions:
+// (as defined in orderAccess.hpp)
+// 
+// - ppc_release         orders Store|Store,       (maps to ppc_lwsync)
+//                               Load|Store
+// - ppc_acquire         orders  Load|Store,       (maps to ppc_lwsync)
+//                               Load|Load
+// - ppc_fence           orders Store|Store,       (maps to ppc_sync)
+//                               Load|Store,
+//                               Load|Load,
+//                              Store|Load
+//
+
+#define inlasm_ppc_sync()     __asm__ __volatile__ ("sync"   : : : "memory");
+#define inlasm_ppc_lwsync()   __asm__ __volatile__ ("lwsync" : : : "memory");
+#define inlasm_ppc_eieio()    __asm__ __volatile__ ("eieio"  : : : "memory");
+#define inlasm_ppc_isync()    __asm__ __volatile__ ("isync"  : : : "memory");
+#define inlasm_ppc_release()  inlasm_ppc_lwsync();
+#define inlasm_ppc_acquire()  inlasm_ppc_lwsync();
+// Use twi-isync for load_acquire (faster than lwsync).
+// ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"):
+// #define inlasm_ppc_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
+#define inlasm_ppc_acquire_reg(X) inlasm_ppc_lwsync();
+#define inlasm_ppc_fence()    inlasm_ppc_sync();
+
+inline void     OrderAccess::loadload()   { inlasm_ppc_lwsync();  }
+inline void     OrderAccess::storestore() { inlasm_ppc_lwsync();  }
+inline void     OrderAccess::loadstore()  { inlasm_ppc_lwsync();  }
+inline void     OrderAccess::storeload()  { inlasm_ppc_fence();   }
+
+inline void     OrderAccess::acquire()    { inlasm_ppc_acquire(); }
+inline void     OrderAccess::release()    { inlasm_ppc_release(); }
+inline void     OrderAccess::fence()      { inlasm_ppc_fence();   }
+
+inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { register jbyte t = *p;   inlasm_ppc_acquire_reg(t); return t; }
+inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { register jshort t = *p;  inlasm_ppc_acquire_reg(t); return t; }
+inline jint     OrderAccess::load_acquire(volatile jint*    p) { register jint t = *p;    inlasm_ppc_acquire_reg(t); return t; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { register jlong t = *p;   inlasm_ppc_acquire_reg(t); return t; }
+inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { register jubyte t = *p;  inlasm_ppc_acquire_reg(t); return t; }
+inline jushort  OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_ppc_acquire_reg(t); return t; }
+inline juint    OrderAccess::load_acquire(volatile juint*   p) { register juint t = *p;   inlasm_ppc_acquire_reg(t); return t; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p) { return (julong)load_acquire((volatile jlong*)p); }
+inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { register jfloat t = *p;  inlasm_ppc_acquire(); return t; }
+inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_ppc_acquire(); return t; }
+
+inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t*   p) { return (intptr_t)load_acquire((volatile jlong*)p); }
+inline void*    OrderAccess::load_ptr_acquire(volatile void*       p) { return (void*)   load_acquire((volatile jlong*)p); }
+inline void*    OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*)   load_acquire((volatile jlong*)p); }
+
+inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; }
+
+inline void     OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; }
+inline void     OrderAccess::release_store_ptr(volatile void*     p, void*    v) { inlasm_ppc_release(); *(void* volatile *)p = v; }
+
+inline void     OrderAccess::store_fence(jbyte*   p, jbyte   v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jshort*  p, jshort  v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jint*    p, jint    v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jlong*   p, jlong   v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jubyte*  p, jubyte  v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(juint*   p, juint   v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(julong*  p, julong  v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jfloat*  p, jfloat  v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_ppc_fence(); }
+
+inline void     OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::store_ptr_fence(void**    p, void*    v) { *p = v; inlasm_ppc_fence(); }
+
+inline void     OrderAccess::release_store_fence(volatile jbyte*   p, jbyte   v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jshort*  p, jshort  v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jint*    p, jint    v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile juint*   p, juint   v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+
+inline void     OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); }
+inline void     OrderAccess::release_store_ptr_fence(volatile void*     p, void*    v) { inlasm_ppc_release(); *(void* volatile *)p = v; inlasm_ppc_fence(); }
+
+#undef inlasm_ppc_sync
+#undef inlasm_ppc_lwsync
+#undef inlasm_ppc_eieio
+#undef inlasm_ppc_isync
+#undef inlasm_ppc_release
+#undef inlasm_ppc_acquire
+#undef inlasm_ppc_fence
+
+#endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// no precompiled headers
+#include "assembler_ppc.inline.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/icBuffer.hpp"
+#include "code/vtableStubs.hpp"
+#include "interpreter/interpreter.hpp"
+#include "jvm_aix.h"
+#include "memory/allocation.inline.hpp"
+#include "mutex_aix.inline.hpp"
+#include "nativeInst_ppc.hpp"
+#include "os_share_aix.hpp"
+#include "prims/jniFastGetField.hpp"
+#include "prims/jvm.h"
+#include "prims/jvm_misc.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/extendedPC.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/java.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/timer.hpp"
+#include "thread_aix.inline.hpp"
+#include "utilities/events.hpp"
+#include "utilities/vmError.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif
+#ifdef COMPILER2
+#include "opto/runtime.hpp"
+#endif
+
+// put OS-includes here
+# include <ucontext.h>
+
+address os::current_stack_pointer() {
+  address csp;
+
+#if !defined(USE_XLC_BUILTINS)
+  // inline assembly for `ppc_mr regno(csp), PPC_SP':
+  __asm__ __volatile__ ("mr %0, 1":"=r"(csp):);
+#else
+  csp = (address) __builtin_frame_address(0);
+#endif
+
+  return csp;
+}
+
+char* os::non_memory_address_word() {
+  // Must never look like an address returned by reserve_memory,
+  // even in its subfields (as defined by the CPU immediate fields,
+  // if the CPU splits constants across multiple instructions).
+
+  return (char*) -1;
+}
+
+// OS specific thread initialization
+//
+// Calculate and store the limits of the memory stack.
+void os::initialize_thread(Thread *thread) { }
+
+// Frame information (pc, sp, fp) retrieved via ucontext
+// always looks like a C-frame according to the frame
+// conventions in frame_ppc64.hpp.
+address os::Aix::ucontext_get_pc(ucontext_t * uc) {
+  return (address)uc->uc_mcontext.jmp_context.iar;
+}
+
+intptr_t* os::Aix::ucontext_get_sp(ucontext_t * uc) {
+  // gpr1 holds the stack pointer on aix
+  return (intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/];
+}
+
+intptr_t* os::Aix::ucontext_get_fp(ucontext_t * uc) {
+  return NULL;
+}
+
+void os::Aix::ucontext_set_pc(ucontext_t* uc, address new_pc) {
+  uc->uc_mcontext.jmp_context.iar = (uint64_t) new_pc;
+}
+
+ExtendedPC os::fetch_frame_from_context(void* ucVoid,
+                                        intptr_t** ret_sp, intptr_t** ret_fp) {
+
+  ExtendedPC  epc;
+  ucontext_t* uc = (ucontext_t*)ucVoid;
+
+  if (uc != NULL) {
+    epc = ExtendedPC(os::Aix::ucontext_get_pc(uc));
+    if (ret_sp) *ret_sp = os::Aix::ucontext_get_sp(uc);
+    if (ret_fp) *ret_fp = os::Aix::ucontext_get_fp(uc);
+  } else {
+    // construct empty ExtendedPC for return value checking
+    epc = ExtendedPC(NULL);
+    if (ret_sp) *ret_sp = (intptr_t *)NULL;
+    if (ret_fp) *ret_fp = (intptr_t *)NULL;
+  }
+
+  return epc;
+}
+
+frame os::fetch_frame_from_context(void* ucVoid) {
+  intptr_t* sp;
+  intptr_t* fp;
+  ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
+  // Avoid crash during crash if pc broken.
+  if (epc.pc()) {
+    frame fr(sp, epc.pc());
+    return fr;
+  }
+  frame fr(sp);
+  return fr;
+}
+
+frame os::get_sender_for_C_frame(frame* fr) {
+  if (*fr->sp() == NULL) {
+    // fr is the last C frame
+    return frame(NULL, NULL);
+  }
+  return frame(fr->sender_sp(), fr->sender_pc());
+}
+
+
+frame os::current_frame() {
+  intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer());
+  // hack.
+  frame topframe(csp, (address)0x8);
+  // return sender of current topframe which hopefully has pc != NULL.
+  return os::get_sender_for_C_frame(&topframe);
+}
+
+// Utility functions
+
+extern "C" JNIEXPORT int
+JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) {
+
+  ucontext_t* uc = (ucontext_t*) ucVoid;
+
+  Thread* t = ThreadLocalStorage::get_thread_slow();   // slow & steady
+
+  SignalHandlerMark shm(t);
+
+  // Note: it's not uncommon that JNI code uses signal/sigset to install
+  // then restore certain signal handler (e.g. to temporarily block SIGPIPE,
+  // or have a SIGILL handler when detecting CPU type). When that happens,
+  // JVM_handle_aix_signal() might be invoked with junk info/ucVoid. To
+  // avoid unnecessary crash when libjsig is not preloaded, try handle signals
+  // that do not require siginfo/ucontext first.
+
+  if (sig == SIGPIPE) {
+    if (os::Aix::chained_handler(sig, info, ucVoid)) {
+      return 1;
+    } else {
+      if (PrintMiscellaneous && (WizardMode || Verbose)) {
+        warning("Ignoring SIGPIPE - see bug 4229104");
+      }
+      return 1;
+    }
+  }
+
+  JavaThread* thread = NULL;
+  VMThread* vmthread = NULL;
+  if (os::Aix::signal_handlers_are_installed) {
+    if (t != NULL) {
+      if(t->is_Java_thread()) {
+        thread = (JavaThread*)t;
+      }
+      else if(t->is_VM_thread()) {
+        vmthread = (VMThread *)t;
+      }
+    }
+  }
+
+  // Decide if this trap can be handled by a stub.
+  address stub = NULL;
+
+  // retrieve program counter
+  address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL;
+
+  // retrieve crash address
+  address const addr = info ? (const address) info->si_addr : NULL;
+
+  // SafeFetch 32 handling:
+  // - make it work if _thread is null
+  // - make it use the standard os::...::ucontext_get/set_pc APIs
+  if (uc) {
+    address const pc = os::Aix::ucontext_get_pc(uc);
+    if (pc && StubRoutines::is_safefetch_fault(pc)) {
+      os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
+      return true;
+    }
+  }
+
+  // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
+  // space falls below 30%. This is only a chance for the process to gracefully abort.
+  // We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
+  if (sig == SIGDANGER) {
+    goto report_and_die;
+  }
+
+  if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
+    goto run_chained_handler;
+  }
+
+  // If we are a java thread...
+  if (thread != NULL) {
+
+    // Handle ALL stack overflow variations here
+    if (sig == SIGSEGV && (addr < thread->stack_base() &&
+                           addr >= thread->stack_base() - thread->stack_size())) {
+      // stack overflow
+      //
+      // If we are in a yellow zone and we are inside java, we disable the yellow zone and
+      // throw a stack overflow exception.
+      // If we are in native code or VM C code, we report-and-die. The original coding tried
+      // to continue with yellow zone disabled, but that doesn't buy us much and prevents
+      // hs_err_pid files.
+      if (thread->in_stack_yellow_zone(addr)) {
+        thread->disable_stack_yellow_zone();
+        if (thread->thread_state() == _thread_in_Java) {
+          // Throw a stack overflow exception.
+          // Guard pages will be reenabled while unwinding the stack.
+          stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
+          goto run_stub;
+        } else {
+          // Thread was in the vm or native code. Return and try to finish.
+          return 1;
+        }
+      } else if (thread->in_stack_red_zone(addr)) {
+        // Fatal red zone violation. Disable the guard pages and fall through
+        // to handle_unexpected_exception way down below.
+        thread->disable_stack_red_zone();
+        tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+        goto report_and_die;
+      } else {
+        // this means a segv happened inside our stack, but not in
+        // the guarded zone. I'd like to know when this happens,
+        tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone.");
+        goto report_and_die;
+      }
+
+    } // end handle SIGSEGV inside stack boundaries
+
+    if (thread->thread_state() == _thread_in_Java) {
+      // Java thread running in Java code
+
+      // The following signals are used for communicating VM events:
+      //
+      // SIGILL: the compiler generates illegal opcodes
+      //   at places where it wishes to interrupt the VM:
+      //   Safepoints, Unreachable Code, Entry points of Zombie methods,
+      //    This results in a SIGILL with (*pc) == inserted illegal instruction.
+      //
+      //   (so, SIGILLs with a pc inside the zero page are real errors)
+      //
+      // SIGTRAP:
+      //   The ppc trap instruction raises a SIGTRAP and is very efficient if it
+      //   does not trap. It is used for conditional branches that are expected
+      //   to be never taken. These are:
+      //     - zombie methods
+      //     - IC (inline cache) misses.
+      //     - null checks leading to UncommonTraps.
+      //     - range checks leading to Uncommon Traps.
+      //   On Aix, these are especially null checks, as the ImplicitNullCheck
+      //   optimization works only in rare cases, as the page at address 0 is only
+      //   write protected.      //
+      //   Note: !UseSIGTRAP is used to prevent SIGTRAPS altogether, to facilitate debugging.
+      //
+      // SIGSEGV:
+      //   used for safe point polling:
+      //     To notify all threads that they have to reach a safe point, safe point polling is used:
+      //     All threads poll a certain mapped memory page. Normally, this page has read access.
+      //     If the VM wants to inform the threads about impending safe points, it puts this
+      //     page to read only ("poisens" the page), and the threads then reach a safe point.
+      //   used for null checks:
+      //     If the compiler finds a store it uses it for a null check. Unfortunately this
+      //     happens rarely.  In heap based and disjoint base compressd oop modes also loads
+      //     are used for null checks.
+
+      // A VM-related SIGILL may only occur if we are not in the zero page.
+      // On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else
+      // in the zero page, because it is filled with 0x0. We ignore
+      // explicit SIGILLs in the zero page.
+      if (sig == SIGILL && (pc < (address) 0x200)) {
+        if (TraceTraps)
+          tty->print_raw_cr("SIGILL happened inside zero page.");
+        goto report_and_die;
+      }
+
+      // Handle signal from NativeJump::patch_verified_entry().
+      if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) ||
+          (!TrapBasedNotEntrantChecks && sig == SIGILL  && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) {
+        if (TraceTraps)
+          tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");
+        stub = SharedRuntime::get_handle_wrong_method_stub();
+        goto run_stub;
+      }
+
+      else if (sig == SIGSEGV && os::is_poll_address(addr)) {
+        if (TraceTraps)
+          tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc);
+        stub = SharedRuntime::get_poll_stub(pc);
+        goto run_stub;
+      }
+
+      // SIGTRAP-based ic miss check in compiled code
+      else if (sig == SIGTRAP && TrapBasedICMissChecks &&
+               nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {
+        if (TraceTraps)
+          tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
+        stub = SharedRuntime::get_ic_miss_stub();
+        goto run_stub;
+      }
+
+#ifdef COMPILER2
+      // SIGTRAP-based implicit null check in compiled code.
+      else if (sig == SIGTRAP && TrapBasedNullChecks &&
+               nativeInstruction_at(pc)->is_sigtrap_null_check()) {
+        if (TraceTraps)
+          tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
+        stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
+        goto run_stub;
+      }
+#endif
+
+      // SIGSEGV-based implicit null check in compiled code.
+      else if (sig == SIGSEGV && ImplicitNullChecks &&
+               CodeCache::contains((void*) pc) &&
+               !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
+        if (TraceTraps)
+          tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc);
+        stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
+      }
+
+#ifdef COMPILER2
+      // SIGTRAP-based implicit range check in compiled code.
+      else if (sig == SIGTRAP && TrapBasedRangeChecks &&
+               nativeInstruction_at(pc)->is_sigtrap_range_check()) {
+        if (TraceTraps)
+          tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
+        stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
+        goto run_stub;
+      }
+#endif
+
+      else if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
+        if (TraceTraps) {
+          tty->print_raw_cr("Fix SIGFPE handler, trying divide by zero handler.");
+        }
+        stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
+        goto run_stub;
+      }
+
+      else if (sig == SIGBUS) {
+        // BugId 4454115: A read from a MappedByteBuffer can fault here if the
+        // underlying file has been truncated. Do not crash the VM in such a case.
+        CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
+        nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
+        if (nm != NULL && nm->has_unsafe_access()) {
+          // We don't really need a stub here! Just set the pending exeption and
+          // continue at the next instruction after the faulting read. Returning
+          // garbage from this read is ok.
+          thread->set_pending_unsafe_access_error();
+          uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
+          return 1;
+        }
+      }
+    }
+
+    else { // thread->thread_state() != _thread_in_Java
+      // Detect CPU features. This is only done at the very start of the VM. Later, the
+      // VM_Version::is_determine_features_test_running() flag should be false.
+
+      if (sig == SIGILL && VM_Version::is_determine_features_test_running()) {
+        // SIGILL must be caused by VM_Version::determine_features().
+        *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL,
+                        // flushing of icache is not necessary.
+        stub = pc + 4;  // continue with next instruction.
+        goto run_stub;
+      }
+      else if (thread->thread_state() == _thread_in_vm &&
+               sig == SIGBUS && thread->doing_unsafe_access()) {
+        // We don't really need a stub here! Just set the pending exeption and
+        // continue at the next instruction after the faulting read. Returning
+        // garbage from this read is ok.
+        thread->set_pending_unsafe_access_error();
+        uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
+        return 1;
+      }
+    }
+
+    // Check to see if we caught the safepoint code in the
+    // process of write protecting the memory serialization page.
+    // It write enables the page immediately after protecting it
+    // so we can just return to retry the write.
+    if ((sig == SIGSEGV) &&
+        os::is_memory_serialize_page(thread, addr)) {
+      // Synchronization problem in the pseudo memory barrier code (bug id 6546278)
+      // Block current thread until the memory serialize page permission restored.
+      os::block_on_serialize_page_trap();
+      return true;
+    }
+  }
+
+run_stub:
+
+  // One of the above code blocks ininitalized the stub, so we want to
+  // delegate control to that stub.
+  if (stub != NULL) {
+    // Save all thread context in case we need to restore it.
+    if (thread != NULL) thread->set_saved_exception_pc(pc);
+    uc->uc_mcontext.jmp_context.iar = (unsigned long)stub;
+    return 1;
+  }
+
+run_chained_handler:
+
+  // signal-chaining
+  if (os::Aix::chained_handler(sig, info, ucVoid)) {
+    return 1;
+  }
+  if (!abort_if_unrecognized) {
+    // caller wants another chance, so give it to him
+    return 0;
+  }
+
+report_and_die:
+
+  // Use sigthreadmask instead of sigprocmask on AIX and unmask current signal.
+  sigset_t newset;
+  sigemptyset(&newset);
+  sigaddset(&newset, sig);
+  sigthreadmask(SIG_UNBLOCK, &newset, NULL);
+
+  VMError err(t, sig, pc, info, ucVoid);
+  err.report_and_die();
+
+  ShouldNotReachHere();
+  return 0;
+}
+
+void os::Aix::init_thread_fpu_state(void) {
+#if !defined(USE_XLC_BUILTINS)
+  // Disable FP exceptions.
+  __asm__ __volatile__ ("mtfsfi 6,0");
+#else
+  __mtfsfi(6, 0);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// thread stack
+
+size_t os::Aix::min_stack_allowed = 768*K;
+
+// Aix is always in floating stack mode. The stack size for a new
+// thread can be set via pthread_attr_setstacksize().
+bool os::Aix::supports_variable_stack_size() { return true; }
+
+// return default stack size for thr_type
+size_t os::Aix::default_stack_size(os::ThreadType thr_type) {
+  // default stack size (compiler thread needs larger stack)
+  // Notice that the setting for compiler threads here have no impact
+  // because of the strange 'fallback logic' in os::create_thread().
+  // Better set CompilerThreadStackSize in globals_<os_cpu>.hpp if you want to
+  // specify a different stack size for compiler threads!
+  size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
+  return s;
+}
+
+size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
+  return 2 * page_size();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// helper functions for fatal error handler
+
+void os::print_context(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  ucontext_t* uc = (ucontext_t*)context;
+
+  st->print_cr("Registers:");
+  st->print("pc =" INTPTR_FORMAT "  ", uc->uc_mcontext.jmp_context.iar);
+  st->print("lr =" INTPTR_FORMAT "  ", uc->uc_mcontext.jmp_context.lr);
+  st->print("ctr=" INTPTR_FORMAT "  ", uc->uc_mcontext.jmp_context.ctr);
+  st->cr();
+  for (int i = 0; i < 32; i++) {
+    st->print("r%-2d=" INTPTR_FORMAT "  ", i, uc->uc_mcontext.jmp_context.gpr[i]);
+    if (i % 3 == 2) st->cr();
+  }
+  st->cr();
+  st->cr();
+
+  intptr_t *sp = (intptr_t *)os::Aix::ucontext_get_sp(uc);
+  st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
+  print_hex_dump(st, (address)sp, (address)(sp + 128), sizeof(intptr_t));
+  st->cr();
+
+  // Note: it may be unsafe to inspect memory near pc. For example, pc may
+  // point to garbage if entry point in an nmethod is corrupted. Leave
+  // this at the end, and hope for the best.
+  address pc = os::Aix::ucontext_get_pc(uc);
+  st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
+  print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4);
+  st->cr();
+
+  // Try to decode the instructions.
+  st->print_cr("Decoded instructions: (pc=" PTR_FORMAT ")", pc);
+  st->print("<TODO: PPC port - print_context>");
+  // TODO: PPC port Disassembler::decode(pc, 16, 16, st);
+  st->cr();
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+  st->print("Not ported - print_register_info\n");
+}
+
+extern "C" {
+  int SpinPause() {
+    return 0;
+  }
+}
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+  assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+}
+#endif
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002, 2010, 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
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP
+#define OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP
+
+#include "runtime/prefetch.hpp"
+
+
+inline void Prefetch::read(void *loc, intx interval) {
+#if !defined(USE_XLC_BUILTINS)
+  __asm__ __volatile__ (
+    "   dcbt   0, %0       \n"
+    :
+    : /*%0*/"r" ( ((address)loc) +((long)interval) )
+    //:
+    );
+#else
+  __dcbt(((address)loc) +((long)interval));
+#endif
+}
+
+inline void Prefetch::write(void *loc, intx interval) {
+#if !defined(USE_XLC_PREFETCH_WRITE_BUILTIN)
+  __asm__ __volatile__ (
+    "   dcbtst 0, %0       \n"
+    :
+    : /*%0*/"r" ( ((address)loc) +((long)interval) )
+    //:
+    );
+#else
+  __dcbtst( ((address)loc) +((long)interval) );
+#endif
+}
+
+#endif // OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1997, 2010, 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);
+}
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP
+#define OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP
+
+  // Processor dependent parts of ThreadLocalStorage
+
+public:
+  static Thread* thread() {
+    return (Thread *) os::thread_local_storage_at(thread_index());
+  }
+
+#endif // OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/frame.inline.hpp"
+#include "thread_aix.inline.hpp"
+
+// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
+bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
+  Unimplemented();
+  return false;
+}
+
+void JavaThread::cache_global_variables() { }
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP
+#define OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP
+
+ private:
+  void pd_initialize() {
+    _anchor.clear();
+    _last_interpreter_fp = NULL;
+  }
+
+  // The `last' frame is the youngest Java frame on the thread's stack.
+  frame pd_last_frame() {
+    assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
+
+    intptr_t* sp = last_Java_sp();
+    address pc = _anchor.last_Java_pc();
+
+    // Last_Java_pc ist not set, if we come here from compiled code.
+    if (pc == NULL)
+      pc =  (address) *(sp + 2);
+
+    return frame(sp, pc);
+  }
+
+ public:
+  void set_base_of_stack_pointer(intptr_t* base_sp) {}
+  intptr_t* base_of_stack_pointer()   { return NULL; }
+  void record_base_of_stack_pointer() {}
+
+  // These routines are only used on cpu architectures that
+  // have separate register stacks (Itanium).
+  static bool register_stack_overflow() { return false; }
+  static void enable_register_stack_guard() {}
+  static void disable_register_stack_guard() {}
+
+  bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
+                                           bool isInJava);
+
+  // -Xprof support
+  //
+  // In order to find the last Java fp from an async profile
+  // tick, we store the current interpreter fp in the thread.
+  // This value is only valid while we are in the C++ interpreter
+  // and profiling.
+ protected:
+  intptr_t *_last_interpreter_fp;
+
+ public:
+  static ByteSize last_interpreter_fp_offset() {
+    return byte_offset_of(JavaThread, _last_interpreter_fp);
+  }
+
+  intptr_t* last_interpreter_fp() { return _last_interpreter_fp; }
+
+#endif // OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP
diff -r 4acea56cea4c src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP
+#define OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP
+
+// These are the OS and CPU-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
+                                                                                                                                     \
+  /******************************/                                                                                                   \
+  /* Threads (NOTE: incomplete) */                                                                                                   \
+  /******************************/                                                                                                   \
+  nonstatic_field(OSThread,                      _thread_id,                                      pid_t)                             \
+  nonstatic_field(OSThread,                      _pthread_id,                                     pthread_t)
+
+
+#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+                                                                          \
+  /**********************/                                                \
+  /* Posix Thread IDs   */                                                \
+  /**********************/                                                \
+                                                                          \
+  declare_integer_type(pid_t)                                             \
+  declare_unsigned_integer_type(pthread_t)
+
+#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+
+#endif // OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP
diff -r 4acea56cea4c src/share/vm/utilities/globalDefinitions_xlc.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/utilities/globalDefinitions_xlc.hpp	Wed Jun 26 15:35:51 2013 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP
+#define SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP
+
+#include "prims/jni.h"
+
+// This file holds compiler-dependent includes,
+// globally used constants & types, class (forward)
+// declarations and a few frequently used utility functions.
+
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#include <math.h>
+#ifndef FP_PZERO
+// Linux doesn't have positive/negative zero
+#define FP_PZERO FP_ZERO
+#endif
+#if (!defined fpclass)
+#define fpclass fpclassify
+#endif
+
+#include <time.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+#include <limits.h>
+#include <errno.h>
+
+#include <stdint.h>
+
+// Use XLC compiler builtins instead of inline assembler
+#define USE_XLC_BUILTINS
+#ifdef USE_XLC_BUILTINS
+#include <builtins.h>
+  #if __IBMCPP__ < 1000
+  // the funtion prototype for __dcbtst(void *) is missing in XLC V8.0
+  // I could compile a little test, where I provided the prototype.
+  // The generated code was correct there. This is the prototype:
+  // extern "builtin" void __dcbtst (void *);
+  // For now we don't make use of it when compiling with XLC V8.0
+  #else
+  // __IBMCPP__ >= 1000
+  // XLC V10 provides the prototype for __dcbtst (void *);
+  #define USE_XLC_PREFETCH_WRITE_BUILTIN
+  #endif
+#endif // USE_XLC_BUILTINS
+
+// NULL vs NULL_WORD:
+// On Linux NULL is defined as a special type '__null'. Assigning __null to
+// integer variable will cause gcc warning. Use NULL_WORD in places where a
+// pointer is stored as integer value.  On some platforms, sizeof(intptr_t) >
+// sizeof(void*), so here we want something which is integer type, but has the
+// same size as a pointer.
+#ifdef __GNUC__
+  #error XLC and __GNUC__?
+#else
+  #define NULL_WORD  NULL
+#endif
+
+// AIX also needs a 64 bit NULL to work as a null address pointer.
+// Most system includes on AIX would define it as an int 0 if not already defined with one
+// exception: /usr/include/dirent.h will unconditionally redefine NULL to int 0 again.
+// In this case you need to copy the following defines to a position after #include <dirent.h>
+// (see jmv_aix.h).
+#ifdef AIX
+  #ifdef _LP64
+    #undef NULL
+    #define NULL 0L
+  #else
+    #ifndef NULL
+      #define NULL 0
+    #endif
+  #endif
+#endif // AIX
+
+// Compiler-specific primitive types
+// All defs of int (uint16_6 etc) are defined in AIX' /usr/include/stdint.h
+
+// Additional Java basic types
+
+typedef uint8_t  jubyte;
+typedef uint16_t jushort;
+typedef uint32_t juint;
+typedef uint64_t julong;
+
+//----------------------------------------------------------------------------------------------------
+// Special (possibly not-portable) casts
+// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
+// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar
+
+inline jint    jint_cast   (jfloat  x)           { return *(jint*   )&x; }
+inline jlong   jlong_cast  (jdouble x)           { return *(jlong*  )&x; }
+
+inline jfloat  jfloat_cast (jint    x)           { return *(jfloat* )&x; }
+inline jdouble jdouble_cast(jlong   x)           { return *(jdouble*)&x; }
+
+//----------------------------------------------------------------------------------------------------
+// Constant for jlong (specifying an long long canstant is C++ compiler specific)
+
+// Build a 64bit integer constant
+#define CONST64(x)  (x ## LL)
+#define UCONST64(x) (x ## ULL)
+
+const jlong min_jlong = CONST64(0x8000000000000000);
+const jlong max_jlong = CONST64(0x7fffffffffffffff);
+
+//----------------------------------------------------------------------------------------------------
+// Debugging
+
+#define DEBUG_EXCEPTION ::abort();
+
+extern "C" void breakpoint();
+#define BREAKPOINT ::breakpoint()
+
+// checking for nanness
+#ifdef AIX
+inline int g_isnan(float  f) { return isnan(f); }
+inline int g_isnan(double f) { return isnan(f); }
+#else
+#error "missing platform-specific definition here"
+#endif
+
+// Checking for finiteness
+
+inline int g_isfinite(jfloat  f)                 { return finite(f); }
+inline int g_isfinite(jdouble f)                 { return finite(f); }
+
+
+// Wide characters
+
+inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
+
+
+// Portability macros
+#define PRAGMA_INTERFACE             #pragma interface
+#define PRAGMA_IMPLEMENTATION        #pragma implementation
+#define VALUE_OBJ_CLASS_SPEC
+
+// Formatting.
+#ifdef _LP64
+#define FORMAT64_MODIFIER "l"
+#else // !_LP64
+#define FORMAT64_MODIFIER "ll"
+#endif // _LP64
+
+// Cannot use xlc's offsetof as implementation of hotspot's
+// offset_of(), because xlc warns about applying offsetof() to non-POD
+// object and xlc cannot compile the expression offsetof(DataLayout,
+// _cells[index]) in DataLayout::cell_offset() .  Therefore we define
+// offset_of as it is defined for gcc.
+#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16)
+
+// Some constant sizes used throughout the AIX port
+#define SIZE_1K   ((uint64_t)         0x400ULL)
+#define SIZE_4K   ((uint64_t)        0x1000ULL)
+#define SIZE_64K  ((uint64_t)       0x10000ULL)
+#define SIZE_1M   ((uint64_t)      0x100000ULL)
+#define SIZE_4M   ((uint64_t)      0x400000ULL)
+#define SIZE_8M   ((uint64_t)      0x800000ULL)
+#define SIZE_16M  ((uint64_t)     0x1000000ULL)
+#define SIZE_256M ((uint64_t)    0x10000000ULL)
+#define SIZE_1G   ((uint64_t)    0x40000000ULL)
+#define SIZE_2G   ((uint64_t)    0x80000000ULL)
+#define SIZE_4G   ((uint64_t)   0x100000000ULL)
+#define SIZE_16G  ((uint64_t)   0x400000000ULL)
+#define SIZE_32G  ((uint64_t)   0x800000000ULL)
+#define SIZE_64G  ((uint64_t)  0x1000000000ULL)
+#define SIZE_1T   ((uint64_t) 0x10000000000ULL)
+
+
+#endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP