changeset 10042:ce87b1141c12

8143125: [aix] Further Developments for AIX Summary: Port newest AIX port developemnts to OpenJDK. Reviewed-by: goetz, simonis
author stuefe
date Mon, 16 Nov 2015 10:58:14 +0100
parents 0a209712389c
children 62bf6e152564
files src/os/aix/vm/globals_aix.hpp src/os/aix/vm/libo4.cpp src/os/aix/vm/libo4.hpp src/os/aix/vm/libperfstat_aix.cpp src/os/aix/vm/libperfstat_aix.hpp src/os/aix/vm/loadlib_aix.cpp src/os/aix/vm/misc_aix.cpp src/os/aix/vm/misc_aix.hpp src/os/aix/vm/osThread_aix.cpp src/os/aix/vm/osThread_aix.hpp src/os/aix/vm/os_aix.cpp src/os/aix/vm/os_aix.hpp src/os/aix/vm/os_aix.inline.hpp src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp
diffstat 14 files changed, 1719 insertions(+), 438 deletions(-) [+]
line wrap: on
line diff
--- a/src/os/aix/vm/globals_aix.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/globals_aix.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -29,37 +29,61 @@
 //
 // Defines Aix specific flags. They are not available on other platforms.
 //
+// (Please keep the switches sorted alphabetically.)
 #define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
                                                                                     \
+  /* Whether to allow the VM to run if EXTSHM=ON. EXTSHM is an environment */       \
+  /* variable used on AIX to activate certain hacks which allow more shm segments */\
+  /* for 32bit processes. For 64bit processes, it is pointless and may have */      \
+  /* harmful side effects (e.g. for some reasonn prevents allocation of 64k pages */\
+  /* via shmctl). */                                                                \
+  /* Per default we quit with an error if that variable is found; for certain */    \
+  /* customer scenarios, we may want to be able to run despite that variable. */    \
+  product(bool, AllowExtshm, false,                                                 \
+          "Allow VM to run with EXTSHM=ON.")                                        \
+                                                                                    \
+  product(intx, AttachListenerTimeout, 1000,                                        \
+          "Timeout in ms the attach listener waits for a request")                  \
+          range(0, 2147483)                                                         \
+                                                                                    \
+  /*  Maximum expected size of the data segment. That correlates with the      */   \
+  /*  to the maximum C Heap consumption we expect.                             */   \
+  /*  We need to know this because we need to leave "breathing space" for the  */   \
+  /*  data segment when placing the java heap. If that space is too small, we  */   \
+  /*  reduce our chance of getting a low heap address (needed for compressed   */   \
+  /*  Oops).                                                                   */   \
+  product(uintx, MaxExpectedDataSegmentSize, (SIZE_4G * 2),                         \
+          "Maximum expected Data Segment Size.")                                    \
+                                                                                    \
+  /* Use optimized addresses for the polling page.                             */   \
+  product(bool, OptimizePollingPageLocation, true,                                  \
+             "Optimize the location of the polling page used for Safepoints")       \
+                                                                                    \
   /* Use 64K pages for virtual memory (shmat). */                                   \
   product(bool, Use64KPages, true,                                                  \
           "Use 64K pages if available.")                                            \
                                                                                     \
-  /* 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.")                                         \
+  /*  If VM uses 64K paged memory (shmat) for virtual memory: threshold below  */   \
+  /*  which virtual memory allocations are done with 4K memory (mmap). This is */   \
+  /*  mainly for test purposes.                                                */   \
+  develop(uintx, Use64KPagesThreshold, 0,                                           \
+          "4K/64K page allocation threshold.")                                      \
                                                                                     \
-  /*  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")               \
-             range(0, 2147483)                                                      \
+  /* Normally AIX commits memory on touch, but sometimes it is helpful to have */   \
+  /* explicit commit behaviour. This flag, if true, causes the VM to touch     */   \
+  /* memory on os::commit_memory() (which normally is a noop).                 */   \
+  product(bool, UseExplicitCommit, false,                                           \
+          "Explicit commit for virtual memory.")                                    \
                                                                                     \
 
-// 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.
 //
+
+// UseLargePages means nothing, for now, on AIX.
+// Use Use64KPages or Use16MPages instead.
 define_pd_global(bool, UseLargePages, false);
 define_pd_global(bool, UseLargePagesIndividualAllocation, false);
 define_pd_global(bool, UseOSErrorReporting, false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/libo4.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012, 2015 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.
+ *
+ */
+
+// This is only a stub. Will flesh out later when/if we add further support
+// for PASE.
+
+#include "libo4.hpp"
+
+bool libo4::init() { return false; }
+void libo4::cleanup() {}
+bool libo4::get_memory_info (unsigned long long* p_virt_total, unsigned long long* p_real_total,
+  unsigned long long* p_real_free, unsigned long long* p_pgsp_total, unsigned long long* p_pgsp_free) {
+  return false;
+}
+bool libo4::get_load_avg (double* p_avg1, double* p_avg5, double* p_avg15) { return false; }
+bool libo4::realpath (const char* file_name, char* resolved_name, int resolved_name_len) { return false; }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/aix/vm/libo4.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012, 2015 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.
+ *
+ */
+
+// A C++ wrapper around the libo4 porting library. The libo4 porting library
+// is a set of bridge functions into native AS/400 functionality.
+
+#ifndef OS_AIX_VM_LIBO4_HPP
+#define OS_AIX_VM_LIBO4_HPP
+
+
+class libo4 {
+public:
+
+  // Initialize the libo4 porting library.
+  // Returns true if succeeded, false if error.
+  static bool init();
+
+  // cleanup of the libo4 porting library.
+  static void cleanup();
+
+  // returns a number of memory statistics from the
+  // AS/400.
+  //
+  // Specify NULL for numbers you are not interested in.
+  //
+  // returns false if an error happened. Activate OsMisc trace for
+  // trace output.
+  //
+  static bool get_memory_info (unsigned long long* p_virt_total, unsigned long long* p_real_total,
+    unsigned long long* p_real_free, unsigned long long* p_pgsp_total, unsigned long long* p_pgsp_free);
+
+  // returns information about system load
+  // (similar to "loadavg()" under other Unices)
+  //
+  // Specify NULL for numbers you are not interested in.
+  //
+  // returns false if an error happened. Activate OsMisc trace for
+  // trace output.
+  //
+  static bool get_load_avg (double* p_avg1, double* p_avg5, double* p_avg15);
+
+  // this is a replacement for the "realpath()" API which does not really work
+  // on PASE
+  //
+  // Specify NULL for numbers you are not interested in.
+  //
+  // returns false if an error happened. Activate OsMisc trace for
+  // trace output.
+  //
+  static bool realpath (const char* file_name,
+      char* resolved_name, int resolved_name_len);
+
+};
+
+#endif // OS_AIX_VM_LIBO4_HPP
+
--- a/src/os/aix/vm/libperfstat_aix.cpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/libperfstat_aix.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2015 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
@@ -22,49 +22,50 @@
  *
  */
 
-#include "runtime/arguments.hpp"
 #include "libperfstat_aix.hpp"
+#include "misc_aix.hpp"
 
-// For dlopen and friends
-#include <fcntl.h>
+#include <dlfcn.h>
+#include <sys/systemcfg.h>
 
-// handle to the libperfstat
+// 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,
+typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* 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 int (*fun_perfstat_partition_total_t) (perfstat_id_t *name,
+    PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff, int sizeof_userbuff,
+    int desired_number);
+
+typedef int (*fun_perfstat_wpar_total_t) (perfstat_id_wpar_t *name,
+    PERFSTAT_WPAR_TOTAL_T_LATEST* userbuff, int sizeof_userbuff,
+    int desired_number);
+
 typedef void (*fun_perfstat_reset_t) ();
 
+typedef cid_t (*fun_wpar_getcid_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_partition_total_t g_fun_perfstat_partition_total = NULL;
+static fun_perfstat_wpar_total_t    g_fun_perfstat_wpar_total = NULL;
 static fun_perfstat_reset_t         g_fun_perfstat_reset = NULL;
+static fun_wpar_getcid_t            g_fun_wpar_getcid = NULL;
 
 bool libperfstat::init() {
 
-  if (g_initialized) {
-    return true;
-  }
-
-  g_initialized = false;
-
-  // dynamically load the libperfstat porting library.
+  // 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());
-    }
+    trcVerbose("Cannot load libperfstat.a (dlerror: %s)", dlerror());
     return false;
   }
 
-  // resolve function pointers
+  // Resolve function pointers
 
 #define RESOLVE_FUN_NO_ERROR(name) \
   g_fun_##name = (fun_##name##_t) dlsym(g_libhandle, #name);
@@ -72,26 +73,28 @@
 #define RESOLVE_FUN(name) \
   RESOLVE_FUN_NO_ERROR(name) \
   if (!g_fun_##name) { \
-    if (Verbose) { \
-      fprintf(stderr, "Cannot resolve " #name "() from libperfstat.a\n" \
+    trcVerbose("Cannot resolve " #name "() from libperfstat.a\n" \
                       "   (dlerror: %s)", dlerror()); \
-      } \
     return false; \
   }
 
+  // These functions may or may not be there depending on the OS release.
+  RESOLVE_FUN_NO_ERROR(perfstat_partition_total);
+  RESOLVE_FUN_NO_ERROR(perfstat_wpar_total);
+  RESOLVE_FUN_NO_ERROR(wpar_getcid);
+
+  // These functions are required for every release.
   RESOLVE_FUN(perfstat_cpu_total);
   RESOLVE_FUN(perfstat_memory_total);
   RESOLVE_FUN(perfstat_reset);
 
-  g_initialized = true;
+  trcVerbose("libperfstat loaded.");
 
   return true;
 }
 
 void libperfstat::cleanup() {
 
-  g_initialized = false;
-
   if (g_libhandle) {
     dlclose(g_libhandle);
     g_libhandle = NULL;
@@ -99,26 +102,250 @@
 
   g_fun_perfstat_cpu_total = NULL;
   g_fun_perfstat_memory_total = NULL;
+  g_fun_perfstat_partition_total = NULL;
+  g_fun_perfstat_wpar_total = NULL;
   g_fun_perfstat_reset = NULL;
+  g_fun_wpar_getcid = 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, "");
+  if (g_fun_perfstat_memory_total == NULL) {
+    return -1;
+  }
   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 libperfstat::perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff,
                                     int sizeof_userbuff, int desired_number) {
-  assert(g_initialized, "libperfstat not initialized");
-  assert(g_fun_perfstat_cpu_total, "");
+  if (g_fun_perfstat_cpu_total == NULL) {
+    return -1;
+  }
   return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number);
 }
 
+int libperfstat::perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff,
+                                          int sizeof_userbuff, int desired_number) {
+  if (g_fun_perfstat_partition_total == NULL) {
+    return -1;
+  }
+  return g_fun_perfstat_partition_total(name, userbuff, sizeof_userbuff, desired_number);
+}
+
+int libperfstat::perfstat_wpar_total(perfstat_id_wpar_t *name, PERFSTAT_WPAR_TOTAL_T_LATEST* userbuff,
+                                     int sizeof_userbuff, int desired_number) {
+  if (g_fun_perfstat_wpar_total == NULL) {
+    return -1;
+  }
+  return g_fun_perfstat_wpar_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();
+  if (g_fun_perfstat_reset != NULL) {
+    g_fun_perfstat_reset();
+  }
 }
+
+cid_t libperfstat::wpar_getcid() {
+  if (g_fun_wpar_getcid == NULL) {
+    return (cid_t) -1;
+  }
+  return g_fun_wpar_getcid();
+}
+
+
+//////////////////// convenience functions, release-independent /////////////////////////////
+
+// Excerpts from systemcfg.h definitions newer than AIX 5.3 (our oldest build platform)
+
+#define PV_6 0x100000          /* Power PC 6 */
+#define PV_6_1 0x100001        /* Power PC 6 DD1.x */
+#define PV_7 0x200000          /* Power PC 7 */
+#define PV_5_Compat 0x0F8000   /* Power PC 5 */
+#define PV_6_Compat 0x108000   /* Power PC 6 */
+#define PV_7_Compat 0x208000   /* Power PC 7 */
+#define PV_8 0x300000          /* Power PC 8 */
+#define PV_8_Compat 0x308000   /* Power PC 8 */
+
+
+// Retrieve global cpu information.
+bool libperfstat::get_cpuinfo(cpuinfo_t* pci) {
+
+  assert(pci, "get_cpuinfo: invalid parameter");
+  memset(pci, 0, sizeof(cpuinfo_t));
+
+  PERFSTAT_CPU_TOTAL_T_LATEST psct;
+  memset (&psct, '\0', sizeof(psct));
+
+  if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(PERFSTAT_CPU_TOTAL_T_LATEST), 1)) {
+    if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(perfstat_cpu_total_t_61), 1)) {
+      if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(perfstat_cpu_total_t_53), 1)) {
+          trcVerbose("perfstat_cpu_total() failed (errno=%d)", errno);
+          return false;
+      }
+    }
+  }
+
+  // Global cpu information.
+  strcpy (pci->description, psct.description);
+  pci->processorHZ = psct.processorHZ;
+  pci->ncpus = psct.ncpus;
+  for (int i = 0; i < 3; i++) {
+    pci->loadavg[i] = (double) psct.loadavg[i] / (1 << SBITS);
+  }
+
+  pci->user_clock_ticks = psct.user;
+  pci->sys_clock_ticks  = psct.sys;
+  pci->idle_clock_ticks = psct.idle;
+  pci->wait_clock_ticks = psct.wait;
+
+  // Get the processor version from _system_configuration.
+  switch (_system_configuration.version) {
+  case PV_8:
+    strcpy(pci->version, "Power PC 8");
+    break;
+  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;
+  case PV_8_Compat:
+    strcpy(pci->version, "PV_8_Compat");
+    break;
+  default:
+    strcpy(pci->version, "unknown");
+  }
+
+  return true;
+}
+
+// Retrieve partition information.
+bool libperfstat::get_partitioninfo(partitioninfo_t* ppi) {
+
+  assert(ppi, "get_partitioninfo: invalid parameter");
+  memset(ppi, 0, sizeof(partitioninfo_t));
+
+  PERFSTAT_PARTITON_TOTAL_T_LATEST pspt;
+  memset(&pspt, '\0', sizeof(pspt));
+
+  bool ame_details = true;
+
+  if (-1 == libperfstat::perfstat_partition_total(NULL, &pspt, sizeof(PERFSTAT_PARTITON_TOTAL_T_LATEST), 1)) {
+    if (-1 == libperfstat::perfstat_partition_total(NULL, &pspt, sizeof(perfstat_partition_total_t_71), 1)) {
+      ame_details = false;
+      if (-1 == libperfstat::perfstat_partition_total(NULL, &pspt, sizeof(perfstat_partition_total_t_61), 1)) {
+        if (-1 == libperfstat::perfstat_partition_total(NULL, &pspt, sizeof(perfstat_partition_total_t_53), 1)) {
+          if (-1 == libperfstat::perfstat_partition_total(NULL, &pspt, sizeof(perfstat_partition_total_t_53_5), 1)) {
+            trcVerbose("perfstat_partition_total() failed (errno=%d)", errno);
+            return false;
+          }
+        }
+      }
+    }
+  }
+
+  // partition type info
+  ppi->shared_enabled = pspt.type.b.shared_enabled;
+  ppi->smt_capable = pspt.type.b.smt_capable;
+  ppi->smt_enabled = pspt.type.b.smt_enabled;
+  ppi->lpar_capable = pspt.type.b.lpar_capable;
+  ppi->lpar_enabled = pspt.type.b.lpar_enabled;
+  ppi->dlpar_capable = pspt.type.b.dlpar_capable;
+  ppi->capped = pspt.type.b.capped;
+  ppi->kernel_is_64 = pspt.type.b.kernel_is_64;
+  ppi->pool_util_authority = pspt.type.b.pool_util_authority;
+  ppi->donate_capable = pspt.type.b.donate_capable;
+  ppi->donate_enabled = pspt.type.b.donate_enabled;
+  ppi->ams_capable = pspt.type.b.ams_capable;
+  ppi->ams_enabled = pspt.type.b.ams_enabled;
+  ppi->power_save = pspt.type.b.power_save;
+  ppi->ame_enabled = pspt.type.b.ame_enabled;
+
+  // partition total info
+  ppi->online_cpus = pspt.online_cpus;
+  ppi->entitled_proc_capacity = pspt.entitled_proc_capacity;
+  ppi->var_proc_capacity_weight = pspt.var_proc_capacity_weight;
+  ppi->phys_cpus_pool = pspt.phys_cpus_pool;
+  ppi->pool_id = pspt.pool_id;
+  ppi->entitled_pool_capacity = pspt.entitled_pool_capacity;
+  strcpy(ppi->name, pspt.name);
+
+  // Added values to ppi that we need for later computation of cpu utilization
+  // ( pool authorization needed for pool_idle_time ??? )
+  ppi->timebase_last   = pspt.timebase_last;
+  ppi->pool_idle_time  = pspt.pool_idle_time;
+  ppi->pcpu_tics_user  = pspt.puser;
+  ppi->pcpu_tics_sys   = pspt.psys;
+  ppi->pcpu_tics_idle  = pspt.pidle;
+  ppi->pcpu_tics_wait  = pspt.pwait;
+
+  // Additional AME information.
+  if (ame_details) {
+    ppi->true_memory = pspt.true_memory * 4096;
+    ppi->expanded_memory = pspt.expanded_memory * 4096;
+    ppi->target_memexp_factr = pspt.target_memexp_factr;
+    ppi->current_memexp_factr = pspt.current_memexp_factr;
+    ppi->cmcs_total_time = pspt.cmcs_total_time;
+  }
+
+  return true;
+}
+
+// Retrieve wpar information.
+bool libperfstat::get_wparinfo(wparinfo_t* pwi) {
+
+  assert(pwi, "get_wparinfo: invalid parameter");
+  memset(pwi, 0, sizeof(wparinfo_t));
+
+  if (libperfstat::wpar_getcid() <= 0) {
+    return false;
+  }
+
+  PERFSTAT_WPAR_TOTAL_T_LATEST pswt;
+  memset (&pswt, '\0', sizeof(pswt));
+
+  if (-1 == libperfstat::perfstat_wpar_total(NULL, &pswt, sizeof(PERFSTAT_WPAR_TOTAL_T_LATEST), 1)) {
+    if (-1 == libperfstat::perfstat_wpar_total(NULL, &pswt, sizeof(perfstat_wpar_total_t_61), 1)) {
+      trcVerbose("perfstat_wpar_total() failed (errno=%d)", errno);
+      return false;
+    }
+  }
+
+  // WPAR type info.
+  pwi->app_wpar = pswt.type.b.app_wpar;
+  pwi->cpu_rset = pswt.type.b.cpu_rset;
+  pwi->cpu_xrset = pswt.type.b.cpu_xrset;
+  pwi->cpu_limits = pswt.type.b.cpu_limits;
+  pwi->mem_limits = pswt.type.b.mem_limits;
+  // WPAR total info.
+  strcpy(pwi->name, pswt.name);
+  pwi->wpar_id = pswt.wpar_id;
+  pwi->cpu_limit = pswt.cpu_limit;
+  pwi->mem_limit = pswt.mem_limit;
+
+  return true;
+}
--- a/src/os/aix/vm/libperfstat_aix.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/libperfstat_aix.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -22,7 +22,7 @@
  *
  */
 
-// encapsulates the libperfstat library.
+// 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
@@ -32,7 +32,732 @@
 #ifndef OS_AIX_VM_LIBPERFSTAT_AIX_HPP
 #define OS_AIX_VM_LIBPERFSTAT_AIX_HPP
 
-#include <libperfstat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// These are excerpts from the AIX 5.3, 6.1, 7.1 libperfstat.h -
+// this is all we need from libperfstat.h and I want to avoid having to include <libperfstat.h>
+//
+// Note: I define all structures as if I were to include libperfstat.h on an AIX 5.2
+// build machine.
+//
+// The ratio behind that is that if I would build on an AIX 5.2 build machine,
+// include libperfstat.h and hard-link against libperfstat.a, the program should
+// work without recompilation on all newer AIX versions.
+//
+
+#define IDENTIFIER_LENGTH 64    /* length of strings included in the structures */
+
+
+typedef struct { /* structure element identifier */
+  char name[IDENTIFIER_LENGTH]; /* name of the identifier */
+} perfstat_id_t;
+
+#define CEC_ID_LEN 40           /* CEC identifier length */
+#define MAXCORRALNAMELEN 25     /* length of the wpar name */
+#define FIRST_WPARNAME ""       /* pseudo-name for the first WPAR */
+#define FIRST_WPARID -1         /* pseudo-id for the first WPAR */
+
+typedef unsigned short cid_t;   /* workload partition identifier */
+
+typedef struct { /* Virtual memory utilization */
+  u_longlong_t virt_total;    /* total virtual memory (in 4KB pages) */
+  u_longlong_t real_total;    /* total real memory (in 4KB pages) */
+  u_longlong_t real_free;     /* free real memory (in 4KB pages) */
+  u_longlong_t real_pinned;   /* real memory which is pinned (in 4KB pages) */
+  u_longlong_t real_inuse;    /* real memory which is in use (in 4KB pages) */
+  u_longlong_t pgbad;         /* number of bad pages */
+  u_longlong_t pgexct;        /* number of page faults */
+  u_longlong_t pgins;         /* number of pages paged in */
+  u_longlong_t pgouts;        /* number of pages paged out */
+  u_longlong_t pgspins;       /* number of page ins from paging space */
+  u_longlong_t pgspouts;      /* number of page outs from paging space */
+  u_longlong_t scans;         /* number of page scans by clock */
+  u_longlong_t cycles;        /* number of page replacement cycles */
+  u_longlong_t pgsteals;      /* number of page steals */
+  u_longlong_t numperm;       /* number of frames used for files (in 4KB pages) */
+  u_longlong_t pgsp_total;    /* total paging space (in 4KB pages) */
+  u_longlong_t pgsp_free;     /* free paging space (in 4KB pages) */
+  u_longlong_t pgsp_rsvd;     /* reserved paging space (in 4KB pages) */
+  u_longlong_t real_system;   /* real memory used by system segments (in 4KB pages). This is the sum of all the used pages in segment marked for system usage.
+                               * Since segment classifications are not always guaranteed to be accurate, this number is only an approximation. */
+  u_longlong_t real_user;     /* real memory used by non-system segments (in 4KB pages). This is the sum of all pages used in segments not marked for system usage.
+                               * Since segment classifications are not always guaranteed to be accurate, this number is only an approximation. */
+  u_longlong_t real_process;  /* real memory used by process segments (in 4KB pages). This is real_total-real_free-numperm-real_system. Since real_system is an
+                               * approximation, this number is too. */
+  u_longlong_t virt_active;   /* Active virtual pages. Virtual pages are considered active if they have been accessed */
+
+} perfstat_memory_total_t;
+
+typedef struct { /* global cpu information AIX 5.3 < TL10 */
+  int ncpus;                            /* number of active logical processors */
+  int ncpus_cfg;                        /* number of configured processors */
+  char description[IDENTIFIER_LENGTH];  /* processor description (type/official name) */
+  u_longlong_t processorHZ;             /* processor speed in Hz */
+  u_longlong_t user;                    /* raw total number of clock ticks spent in user mode */
+  u_longlong_t sys;                     /* raw total number of clock ticks spent in system mode */
+  u_longlong_t idle;                    /* raw total number of clock ticks spent idle */
+  u_longlong_t wait;                    /* raw total number of clock ticks spent waiting for I/O */
+  u_longlong_t pswitch;                 /* number of process switches (change in currently running process) */
+  u_longlong_t syscall;                 /* number of system calls executed */
+  u_longlong_t sysread;                 /* number of read system calls executed */
+  u_longlong_t syswrite;                /* number of write system calls executed */
+  u_longlong_t sysfork;                 /* number of forks system calls executed */
+  u_longlong_t sysexec;                 /* number of execs system calls executed */
+  u_longlong_t readch;                  /* number of characters tranferred with read system call */
+  u_longlong_t writech;                 /* number of characters tranferred with write system call */
+  u_longlong_t devintrs;                /* number of device interrupts */
+  u_longlong_t softintrs;               /* number of software interrupts */
+  time_t lbolt;                         /* number of ticks since last reboot */
+  u_longlong_t 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>. */
+  u_longlong_t runque;                  /* length of the run queue (processes ready) */
+  u_longlong_t swpque;                  /* ength of the swap queue (processes waiting to be paged in) */
+  u_longlong_t bread;                   /* number of blocks read */
+  u_longlong_t bwrite;                  /* number of blocks written */
+  u_longlong_t lread;                   /* number of logical read requests */
+  u_longlong_t lwrite;                  /* number of logical write requests */
+  u_longlong_t phread;                  /* number of physical reads (reads on raw devices) */
+  u_longlong_t phwrite;                 /* number of physical writes (writes on raw devices) */
+  u_longlong_t runocc;                  /* updated whenever runque is updated, i.e. the runqueue is occupied.
+                                               * This can be used to compute the simple average of ready processes  */
+  u_longlong_t swpocc;                  /* updated whenever swpque is updated. i.e. the swpqueue is occupied.
+                                               * This can be used to compute the simple average processes waiting to be paged in */
+  u_longlong_t iget;                    /* number of inode lookups */
+  u_longlong_t namei;                   /* number of vnode lookup from a path name */
+  u_longlong_t dirblk;                  /* number of 512-byte block reads by the directory search routine to locate an entry for a file */
+  u_longlong_t msg;                     /* number of IPC message operations */
+  u_longlong_t sema;                    /* number of IPC semaphore operations */
+  u_longlong_t rcvint;                  /* number of tty receive interrupts */
+  u_longlong_t xmtint;                  /* number of tyy transmit interrupts */
+  u_longlong_t mdmint;                  /* number of modem interrupts */
+  u_longlong_t tty_rawinch;             /* number of raw input characters  */
+  u_longlong_t tty_caninch;             /* number of canonical input characters (always zero) */
+  u_longlong_t tty_rawoutch;            /* number of raw output characters */
+  u_longlong_t ksched;                  /* number of kernel processes created */
+  u_longlong_t koverf;                  /* kernel process creation attempts where:
+                                               * -the user has forked to their maximum limit
+                                               * -the configuration limit of processes has been reached */
+  u_longlong_t kexit;                   /* number of kernel processes that became zombies */
+  u_longlong_t rbread;                  /* number of remote read requests */
+  u_longlong_t rcread;                  /* number of cached remote reads */
+  u_longlong_t rbwrt;                   /* number of remote writes */
+  u_longlong_t rcwrt;                   /* number of cached remote writes */
+  u_longlong_t traps;                   /* number of traps */
+  int ncpus_high;                       /* index of highest processor online */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t decrintrs;               /* number of decrementer tics interrupts */
+  u_longlong_t mpcrintrs;               /* number of mpc's received interrupts */
+  u_longlong_t mpcsintrs;               /* number of mpc's sent interrupts */
+  u_longlong_t phantintrs;              /* number of phantom interrupts */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  short iowait;                         /* number of processes that are asleep waiting for buffered I/O */
+  short physio;                         /* number of processes waiting for raw I/O */
+  longlong_t twait;                     /* number of threads that are waiting for filesystem direct(cio) */
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds) */
+} perfstat_cpu_total_t_53;
+
+typedef struct { /* global cpu information AIX 6.1|5.3 > TL09 */
+  int ncpus;                            /* number of active logical processors */
+  int ncpus_cfg;                        /* number of configured processors */
+  char description[IDENTIFIER_LENGTH];  /* processor description (type/official name) */
+  u_longlong_t processorHZ;             /* processor speed in Hz */
+  u_longlong_t user;                    /* raw total number of clock ticks spent in user mode */
+  u_longlong_t sys;                     /* raw total number of clock ticks spent in system mode */
+  u_longlong_t idle;                    /* raw total number of clock ticks spent idle */
+  u_longlong_t wait;                    /* raw total number of clock ticks spent waiting for I/O */
+  u_longlong_t pswitch;                 /* number of process switches (change in currently running process) */
+  u_longlong_t syscall;                 /* number of system calls executed */
+  u_longlong_t sysread;                 /* number of read system calls executed */
+  u_longlong_t syswrite;                /* number of write system calls executed */
+  u_longlong_t sysfork;                 /* number of forks system calls executed */
+  u_longlong_t sysexec;                 /* number of execs system calls executed */
+  u_longlong_t readch;                  /* number of characters tranferred with read system call */
+  u_longlong_t writech;                 /* number of characters tranferred with write system call */
+  u_longlong_t devintrs;                /* number of device interrupts */
+  u_longlong_t softintrs;               /* number of software interrupts */
+  time_t lbolt;                         /* number of ticks since last reboot */
+  u_longlong_t 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>. */
+  u_longlong_t runque;                  /* length of the run queue (processes ready) */
+  u_longlong_t swpque;                  /* length of the swap queue (processes waiting to be paged in) */
+  u_longlong_t bread;                   /* number of blocks read */
+  u_longlong_t bwrite;                  /* number of blocks written */
+  u_longlong_t lread;                   /* number of logical read requests */
+  u_longlong_t lwrite;                  /* number of logical write requests */
+  u_longlong_t phread;                  /* number of physical reads (reads on raw devices) */
+  u_longlong_t phwrite;                 /* number of physical writes (writes on raw devices) */
+  u_longlong_t runocc;                  /* updated whenever runque is updated, i.e. the runqueue is occupied.
+                                               * This can be used to compute the simple average of ready processes  */
+  u_longlong_t swpocc;                  /* updated whenever swpque is updated. i.e. the swpqueue is occupied.
+                                               * This can be used to compute the simple average processes waiting to be paged in */
+  u_longlong_t iget;                    /* number of inode lookups */
+  u_longlong_t namei;                   /* number of vnode lookup from a path name */
+  u_longlong_t dirblk;                  /* number of 512-byte block reads by the directory search routine to locate an entry for a file */
+  u_longlong_t msg;                     /* number of IPC message operations */
+  u_longlong_t sema;                    /* number of IPC semaphore operations */
+  u_longlong_t rcvint;                  /* number of tty receive interrupts */
+  u_longlong_t xmtint;                  /* number of tyy transmit interrupts */
+  u_longlong_t mdmint;                  /* number of modem interrupts */
+  u_longlong_t tty_rawinch;             /* number of raw input characters  */
+  u_longlong_t tty_caninch;             /* number of canonical input characters (always zero) */
+  u_longlong_t tty_rawoutch;            /* number of raw output characters */
+  u_longlong_t ksched;                  /* number of kernel processes created */
+  u_longlong_t koverf;                  /* kernel process creation attempts where:
+                                               * -the user has forked to their maximum limit
+                                               * -the configuration limit of processes has been reached */
+  u_longlong_t kexit;                   /* number of kernel processes that became zombies */
+  u_longlong_t rbread;                  /* number of remote read requests */
+  u_longlong_t rcread;                  /* number of cached remote reads */
+  u_longlong_t rbwrt;                   /* number of remote writes */
+  u_longlong_t rcwrt;                   /* number of cached remote writes */
+  u_longlong_t traps;                   /* number of traps */
+  int ncpus_high;                       /* index of highest processor online */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t decrintrs;               /* number of decrementer tics interrupts */
+  u_longlong_t mpcrintrs;               /* number of mpc's received interrupts */
+  u_longlong_t mpcsintrs;               /* number of mpc's sent interrupts */
+  u_longlong_t phantintrs;              /* number of phantom interrupts */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  short iowait;                         /* number of processes that are asleep waiting for buffered I/O */
+  short physio;                         /* number of processes waiting for raw I/O */
+  longlong_t twait;                     /* number of threads that are waiting for filesystem direct(cio) */
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds) */
+  u_longlong_t puser_spurr;             /* number of spurr cycles spent in user mode */
+  u_longlong_t psys_spurr;              /* number of spurr cycles spent in kernel mode */
+  u_longlong_t pidle_spurr;             /* number of spurr cycles spent in idle mode */
+  u_longlong_t pwait_spurr;             /* number of spurr cycles spent in wait mode */
+  int spurrflag;                        /* set if running in spurr mode */
+} perfstat_cpu_total_t_61;
+
+typedef struct { /* global cpu information AIX 7.1 */
+  int ncpus;                            /* number of active logical processors */
+  int ncpus_cfg;                        /* number of configured processors */
+  char description[IDENTIFIER_LENGTH];  /* processor description (type/official name) */
+  u_longlong_t processorHZ;             /* processor speed in Hz */
+  u_longlong_t user;                    /* raw total number of clock ticks spent in user mode */
+  u_longlong_t sys;                     /* raw total number of clock ticks spent in system mode */
+  u_longlong_t idle;                    /* raw total number of clock ticks spent idle */
+  u_longlong_t wait;                    /* raw total number of clock ticks spent waiting for I/O */
+  u_longlong_t pswitch;                 /* number of process switches (change in currently running process) */
+  u_longlong_t syscall;                 /* number of system calls executed */
+  u_longlong_t sysread;                 /* number of read system calls executed */
+  u_longlong_t syswrite;                /* number of write system calls executed */
+  u_longlong_t sysfork;                 /* number of forks system calls executed */
+  u_longlong_t sysexec;                 /* number of execs system calls executed */
+  u_longlong_t readch;                  /* number of characters tranferred with read system call */
+  u_longlong_t writech;                 /* number of characters tranferred with write system call */
+  u_longlong_t devintrs;                /* number of device interrupts */
+  u_longlong_t softintrs;               /* number of software interrupts */
+  time_t lbolt;                         /* number of ticks since last reboot */
+  u_longlong_t 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>. */
+  u_longlong_t runque;                  /* length of the run queue (processes ready) */
+  u_longlong_t swpque;                  /* ength of the swap queue (processes waiting to be paged in) */
+  u_longlong_t bread;                   /* number of blocks read */
+  u_longlong_t bwrite;                  /* number of blocks written */
+  u_longlong_t lread;                   /* number of logical read requests */
+  u_longlong_t lwrite;                  /* number of logical write requests */
+  u_longlong_t phread;                  /* number of physical reads (reads on raw devices) */
+  u_longlong_t phwrite;                 /* number of physical writes (writes on raw devices) */
+  u_longlong_t runocc;                  /* updated whenever runque is updated, i.e. the runqueue is occupied.
+                                               * This can be used to compute the simple average of ready processes  */
+  u_longlong_t swpocc;                  /* updated whenever swpque is updated. i.e. the swpqueue is occupied.
+                                               * This can be used to compute the simple average processes waiting to be paged in */
+  u_longlong_t iget;                    /* number of inode lookups */
+  u_longlong_t namei;                   /* number of vnode lookup from a path name */
+  u_longlong_t dirblk;                  /* number of 512-byte block reads by the directory search routine to locate an entry for a file */
+  u_longlong_t msg;                     /* number of IPC message operations */
+  u_longlong_t sema;                    /* number of IPC semaphore operations */
+  u_longlong_t rcvint;                  /* number of tty receive interrupts */
+  u_longlong_t xmtint;                  /* number of tyy transmit interrupts */
+  u_longlong_t mdmint;                  /* number of modem interrupts */
+  u_longlong_t tty_rawinch;             /* number of raw input characters  */
+  u_longlong_t tty_caninch;             /* number of canonical input characters (always zero) */
+  u_longlong_t tty_rawoutch;            /* number of raw output characters */
+  u_longlong_t ksched;                  /* number of kernel processes created */
+  u_longlong_t koverf;                  /* kernel process creation attempts where:
+                                               * -the user has forked to their maximum limit
+                                               * -the configuration limit of processes has been reached */
+  u_longlong_t kexit;                   /* number of kernel processes that became zombies */
+  u_longlong_t rbread;                  /* number of remote read requests */
+  u_longlong_t rcread;                  /* number of cached remote reads */
+  u_longlong_t rbwrt;                   /* number of remote writes */
+  u_longlong_t rcwrt;                   /* number of cached remote writes */
+  u_longlong_t traps;                   /* number of traps */
+  int ncpus_high;                       /* index of highest processor online */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t decrintrs;               /* number of decrementer tics interrupts */
+  u_longlong_t mpcrintrs;               /* number of mpc's received interrupts */
+  u_longlong_t mpcsintrs;               /* number of mpc's sent interrupts */
+  u_longlong_t phantintrs;              /* number of phantom interrupts */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  short iowait;                         /* number of processes that are asleep waiting for buffered I/O */
+  short physio;                         /* number of processes waiting for raw I/O */
+  longlong_t twait;                     /* number of threads that are waiting for filesystem direct(cio) */
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds) */
+  u_longlong_t puser_spurr;             /* number of spurr cycles spent in user mode */
+  u_longlong_t psys_spurr;              /* number of spurr cycles spent in kernel mode */
+  u_longlong_t pidle_spurr;             /* number of spurr cycles spent in idle mode */
+  u_longlong_t pwait_spurr;             /* number of spurr cycles spent in wait mode */
+  int spurrflag;                        /* set if running in spurr mode */
+  u_longlong_t  version;                /* version number (1, 2, etc.,) */
+/*      >>>>> END OF STRUCTURE DEFINITION <<<<<         */
+#define CURR_VERSION_CPU_TOTAL 1              /* Incremented by one for every new release *
+                                               * of perfstat_cpu_total_t data structure   */
+} perfstat_cpu_total_t_71;
+
+typedef union {
+  uint    w;
+  struct {
+          unsigned smt_capable :1;          /* OS supports SMT mode */
+          unsigned smt_enabled :1;          /* SMT mode is on */
+          unsigned lpar_capable :1;         /* OS supports logical partitioning */
+          unsigned lpar_enabled :1;         /* logical partitioning is on */
+          unsigned shared_capable :1;       /* OS supports shared processor LPAR */
+          unsigned shared_enabled :1;       /* partition runs in shared mode */
+          unsigned dlpar_capable :1;        /* OS supports dynamic LPAR */
+          unsigned capped :1;               /* partition is capped */
+          unsigned kernel_is_64 :1;         /* kernel is 64 bit */
+          unsigned pool_util_authority :1;  /* pool utilization available */
+          unsigned donate_capable :1;       /* capable of donating cycles */
+          unsigned donate_enabled :1;       /* enabled for donating cycles */
+          unsigned ams_capable:1;           /* 1 = AMS(Active Memory Sharing) capable, 0 = Not AMS capable */
+          unsigned ams_enabled:1;           /* 1 = AMS(Active Memory Sharing) enabled, 0 = Not AMS enabled */
+          unsigned power_save:1;            /* 1 = Power saving mode is enabled */
+          unsigned ame_enabled:1;           /* Active Memory Expansion is enabled */
+          unsigned shared_extended :1;
+          unsigned spare :15;               /* reserved for future usage */
+  } b;
+} perfstat_partition_type_t;
+
+typedef struct { /* partition total information AIX 5.3 < TL6 */
+  char name[IDENTIFIER_LENGTH];         /* name of the logical partition */
+  perfstat_partition_type_t type;       /* set of bits describing the partition */
+  int lpar_id;                          /* logical partition identifier */
+  int group_id;                         /* identifier of the LPAR group this partition is a member of */
+  int pool_id;                          /* identifier of the shared pool of physical processors this partition is a member of */
+  int online_cpus;                      /* number of virtual CPUs currently online on the partition */
+  int max_cpus;                         /* maximum number of virtual CPUs this parition can ever have */
+  int min_cpus;                         /* minimum number of virtual CPUs this partition must have */
+  u_longlong_t online_memory;           /* amount of memory currently online */
+  u_longlong_t max_memory;              /* maximum amount of memory this partition can ever have */
+  u_longlong_t min_memory;              /* minimum amount of memory this partition must have */
+  int entitled_proc_capacity;           /* number of processor units this partition is entitled to receive */
+  int max_proc_capacity;                /* maximum number of processor units this partition can ever have */
+  int min_proc_capacity;                /* minimum number of processor units this partition must have */
+  int proc_capacity_increment;          /* increment value to the entitled capacity */
+  int unalloc_proc_capacity;            /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
+  int var_proc_capacity_weight;         /* partition priority weight to receive extra capacity */
+  int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated  in the shared processor pool this partition belongs to */
+  int online_phys_cpus_sys;             /* number of physical CPUs currently active in the system containing this partition */
+  int max_phys_cpus_sys;                /* maximum possible number of physical CPUs in the system containing this partition */
+  int phys_cpus_pool;                   /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t pool_idle_time;          /* number of clock tics a processor in the shared pool was idle */
+  u_longlong_t phantintrs;              /* number of phantom interrupts received by the partition */
+  u_longlong_t invol_virt_cswitch;      /* number involuntary virtual CPU context switches */
+  u_longlong_t vol_virt_cswitch;        /* number voluntary virtual CPU context switches */
+  u_longlong_t timebase_last;           /* most recently cpu time base */
+  u_longlong_t reserved_pages;          /* Currenlty number of 16GB pages. Cannot participate in DR operations */
+  u_longlong_t reserved_pagesize;       /* Currently 16GB pagesize Cannot participate in DR operations */
+} perfstat_partition_total_t_53_5;
+
+typedef struct { /* partition total information AIX 5.3 < TL10 */
+  char name[IDENTIFIER_LENGTH];         /* name of the logical partition */
+  perfstat_partition_type_t type;       /* set of bits describing the partition */
+  int lpar_id;                          /* logical partition identifier */
+  int group_id;                         /* identifier of the LPAR group this partition is a member of */
+  int pool_id;                          /* identifier of the shared pool of physical processors this partition is a member of */
+  int online_cpus;                      /* number of virtual CPUs currently online on the partition */
+  int max_cpus;                         /* maximum number of virtual CPUs this parition can ever have */
+  int min_cpus;                         /* minimum number of virtual CPUs this partition must have */
+  u_longlong_t online_memory;           /* amount of memory currently online */
+  u_longlong_t max_memory;              /* maximum amount of memory this partition can ever have */
+  u_longlong_t min_memory;              /* minimum amount of memory this partition must have */
+  int entitled_proc_capacity;           /* number of processor units this partition is entitled to receive */
+  int max_proc_capacity;                /* maximum number of processor units this partition can ever have */
+  int min_proc_capacity;                /* minimum number of processor units this partition must have */
+  int proc_capacity_increment;          /* increment value to the entitled capacity */
+  int unalloc_proc_capacity;            /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
+  int var_proc_capacity_weight;         /* partition priority weight to receive extra capacity */
+  int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated  in the shared processor pool this partition belongs to */
+  int online_phys_cpus_sys;             /* number of physical CPUs currently active in the system containing this partition */
+  int max_phys_cpus_sys;                /* maximum possible number of physical CPUs in the system containing this partition */
+  int phys_cpus_pool;                   /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t pool_idle_time;          /* number of clock tics a processor in the shared pool was idle */
+  u_longlong_t phantintrs;              /* number of phantom interrupts received by the partition */
+  u_longlong_t invol_virt_cswitch;      /* number involuntary virtual CPU context switches */
+  u_longlong_t vol_virt_cswitch;        /* number voluntary virtual CPU context switches */
+  u_longlong_t timebase_last;           /* most recently cpu time base */
+  u_longlong_t reserved_pages;          /* Currenlty number of 16GB pages. Cannot participate in DR operations */
+  u_longlong_t reserved_pagesize;       /* Currently 16GB pagesize Cannot participate in DR operations */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t shcpus_in_sys;           /* Number of physical processors allocated for shared processor use */
+  u_longlong_t max_pool_capacity;       /* Maximum processor capacity of partitions pool */
+  u_longlong_t entitled_pool_capacity;  /* Entitled processor capacity of partitions pool */
+  u_longlong_t pool_max_time;           /* Summation of maximum time that could be consumed by the pool (nano seconds) */
+  u_longlong_t pool_busy_time;          /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t pool_scaled_busy_time;   /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t shcpu_tot_time;          /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
+  u_longlong_t shcpu_busy_time;         /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
+  u_longlong_t shcpu_scaled_busy_time;  /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
+  int ams_pool_id;                      /* AMS pool id of the pool the LPAR belongs to */
+  int var_mem_weight;                   /* variable memory capacity weight */
+  u_longlong_t iome;                    /* I/O memory entitlement of the partition in bytes*/
+  u_longlong_t pmem;                    /* Physical memory currently backing the partition's logical memory in bytes*/
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds)*/
+  u_longlong_t hypv_pagesize;           /* Hypervisor page size in KB*/
+} perfstat_partition_total_t_53;
+
+typedef struct { /* partition total information AIX 6.1|5.3 > TL09 */
+  char name[IDENTIFIER_LENGTH];         /* name of the logical partition */
+  perfstat_partition_type_t type;       /* set of bits describing the partition */
+  int lpar_id;                          /* logical partition identifier */
+  int group_id;                         /* identifier of the LPAR group this partition is a member of */
+  int pool_id;                          /* identifier of the shared pool of physical processors this partition is a member of */
+  int online_cpus;                      /* number of virtual CPUs currently online on the partition */
+  int max_cpus;                         /* maximum number of virtual CPUs this parition can ever have */
+  int min_cpus;                         /* minimum number of virtual CPUs this partition must have */
+  u_longlong_t online_memory;           /* amount of memory currently online */
+  u_longlong_t max_memory;              /* maximum amount of memory this partition can ever have */
+  u_longlong_t min_memory;              /* minimum amount of memory this partition must have */
+  int entitled_proc_capacity;           /* number of processor units this partition is entitled to receive */
+  int max_proc_capacity;                /* maximum number of processor units this partition can ever have */
+  int min_proc_capacity;                /* minimum number of processor units this partition must have */
+  int proc_capacity_increment;          /* increment value to the entitled capacity */
+  int unalloc_proc_capacity;            /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
+  int var_proc_capacity_weight;         /* partition priority weight to receive extra capacity */
+  int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated  in the shared processor pool this partition belongs to */
+  int online_phys_cpus_sys;             /* number of physical CPUs currently active in the system containing this partition */
+  int max_phys_cpus_sys;                /* maximum possible number of physical CPUs in the system containing this partition */
+  int phys_cpus_pool;                   /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t pool_idle_time;          /* number of clock tics a processor in the shared pool was idle */
+  u_longlong_t phantintrs;              /* number of phantom interrupts received by the partition */
+  u_longlong_t invol_virt_cswitch;      /* number involuntary virtual CPU context switches */
+  u_longlong_t vol_virt_cswitch;        /* number voluntary virtual CPU context switches */
+  u_longlong_t timebase_last;           /* most recently cpu time base */
+  u_longlong_t reserved_pages;          /* Currenlty number of 16GB pages. Cannot participate in DR operations */
+  u_longlong_t reserved_pagesize;       /* Currently 16GB pagesize Cannot participate in DR operations */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t shcpus_in_sys;           /* Number of physical processors allocated for shared processor use */
+  u_longlong_t max_pool_capacity;       /* Maximum processor capacity of partitions pool */
+  u_longlong_t entitled_pool_capacity;  /* Entitled processor capacity of partitions pool */
+  u_longlong_t pool_max_time;           /* Summation of maximum time that could be consumed by the pool (nano seconds) */
+  u_longlong_t pool_busy_time;          /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t pool_scaled_busy_time;   /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t shcpu_tot_time;          /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
+  u_longlong_t shcpu_busy_time;         /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
+  u_longlong_t shcpu_scaled_busy_time;  /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
+  int ams_pool_id;                      /* AMS pool id of the pool the LPAR belongs to */
+  int var_mem_weight;                   /* variable memory capacity weight */
+  u_longlong_t iome;                    /* I/O memory entitlement of the partition in bytes*/
+  u_longlong_t pmem;                    /* Physical memory currently backing the partition's logical memory in bytes*/
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds)*/
+  u_longlong_t hypv_pagesize;           /* Hypervisor page size in KB*/
+  uint online_lcpus;                    /* number of online logical cpus */
+  uint smt_thrds;                       /* number of hardware threads that are running */
+  u_longlong_t puser_spurr;             /* number of spurr cycles spent in user mode */
+  u_longlong_t psys_spurr;              /* number of spurr cycles spent in kernel mode */
+  u_longlong_t pidle_spurr;             /* number of spurr cycles spent in idle mode */
+  u_longlong_t pwait_spurr;             /* number of spurr cycles spent in wait mode */
+  int spurrflag;                        /* set if running in spurr mode */
+} perfstat_partition_total_t_61;
+
+typedef struct { /* partition total information AIX 7.1 */
+  char name[IDENTIFIER_LENGTH];         /* name of the logical partition */
+  perfstat_partition_type_t type;       /* set of bits describing the partition */
+  int lpar_id;                          /* logical partition identifier */
+  int group_id;                         /* identifier of the LPAR group this partition is a member of */
+  int pool_id;                          /* identifier of the shared pool of physical processors this partition is a member of */
+  int online_cpus;                      /* number of virtual CPUs currently online on the partition */
+  int max_cpus;                         /* maximum number of virtual CPUs this parition can ever have */
+  int min_cpus;                         /* minimum number of virtual CPUs this partition must have */
+  u_longlong_t online_memory;           /* amount of memory currently online */
+  u_longlong_t max_memory;              /* maximum amount of memory this partition can ever have */
+  u_longlong_t min_memory;              /* minimum amount of memory this partition must have */
+  int entitled_proc_capacity;           /* number of processor units this partition is entitled to receive */
+  int max_proc_capacity;                /* maximum number of processor units this partition can ever have */
+  int min_proc_capacity;                /* minimum number of processor units this partition must have */
+  int proc_capacity_increment;          /* increment value to the entitled capacity */
+  int unalloc_proc_capacity;            /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
+  int var_proc_capacity_weight;         /* partition priority weight to receive extra capacity */
+  int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated  in the shared processor pool this partition belongs to */
+  int online_phys_cpus_sys;             /* number of physical CPUs currently active in the system containing this partition */
+  int max_phys_cpus_sys;                /* maximum possible number of physical CPUs in the system containing this partition */
+  int phys_cpus_pool;                   /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+  u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+  u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+  u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+  u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+  u_longlong_t pool_idle_time;          /* number of clock tics a processor in the shared pool was idle */
+  u_longlong_t phantintrs;              /* number of phantom interrupts received by the partition */
+  u_longlong_t invol_virt_cswitch;      /* number involuntary virtual CPU context switches */
+  u_longlong_t vol_virt_cswitch;        /* number voluntary virtual CPU context switches */
+  u_longlong_t timebase_last;           /* most recently cpu time base */
+  u_longlong_t reserved_pages;          /* Currenlty number of 16GB pages. Cannot participate in DR operations */
+  u_longlong_t reserved_pagesize;       /* Currently 16GB pagesize Cannot participate in DR operations */
+  u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+  u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+  u_longlong_t shcpus_in_sys;           /* Number of physical processors allocated for shared processor use */
+  u_longlong_t max_pool_capacity;       /* Maximum processor capacity of partitions pool */
+  u_longlong_t entitled_pool_capacity;  /* Entitled processor capacity of partitions pool */
+  u_longlong_t pool_max_time;           /* Summation of maximum time that could be consumed by the pool (nano seconds) */
+  u_longlong_t pool_busy_time;          /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t pool_scaled_busy_time;   /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+  u_longlong_t shcpu_tot_time;          /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
+  u_longlong_t shcpu_busy_time;         /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
+  u_longlong_t shcpu_scaled_busy_time;  /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
+  int ams_pool_id;                      /* AMS pool id of the pool the LPAR belongs to */
+  int var_mem_weight;                   /* variable memory capacity weight */
+  u_longlong_t iome;                    /* I/O memory entitlement of the partition in bytes*/
+  u_longlong_t pmem;                    /* Physical memory currently backing the partition's logical memory in bytes*/
+  u_longlong_t hpi;                     /* number of hypervisor page-ins */
+  u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds)*/
+  u_longlong_t hypv_pagesize;           /* Hypervisor page size in KB*/
+  uint online_lcpus;                    /* number of online logical cpus */
+  uint smt_thrds;                       /* number of hardware threads that are running */
+  u_longlong_t puser_spurr;             /* number of spurr cycles spent in user mode */
+  u_longlong_t psys_spurr;              /* number of spurr cycles spent in kernel mode */
+  u_longlong_t pidle_spurr;             /* number of spurr cycles spent in idle mode */
+  u_longlong_t pwait_spurr;             /* number of spurr cycles spent in wait mode */
+  int spurrflag;                        /* set if running in spurr mode */
+  char hardwareid[CEC_ID_LEN];          /* CEC Identifier */
+        uint power_save_mode;                 /* Power save mode for the LPAR. Introduced through LI 53K PRF : Feature 728 292*/
+        ushort ame_version;                   /* AME Version */
+        u_longlong_t true_memory;             /* True Memory Size in 4KB pages */
+        u_longlong_t expanded_memory;         /* Expanded Memory Size in 4KB pages */
+        u_longlong_t target_memexp_factr;     /* Target Memory Expansion Factor scaled by 100 */
+        u_longlong_t current_memexp_factr;    /* Current Memory Expansion Factor scaled by 100 */
+        u_longlong_t target_cpool_size;       /* Target Compressed Pool Size in bytes */
+        u_longlong_t max_cpool_size;          /* Max Size of Compressed Pool in bytes */
+        u_longlong_t min_ucpool_size;         /* Min Size of Uncompressed Pool in bytes */
+        u_longlong_t ame_deficit_size;        /*Deficit memory size in bytes */
+        u_longlong_t version;                 /* version number (1, 2, etc.,) */
+        u_longlong_t cmcs_total_time;         /* Total CPU time spent due to active memory expansion */
+} perfstat_partition_total_t_71;
+
+typedef struct { /* partition total information AIX 7.1 >= TL1*/
+        char name[IDENTIFIER_LENGTH];         /* name of the logical partition */
+        perfstat_partition_type_t type;       /* set of bits describing the partition */
+        int lpar_id;                          /* logical partition identifier */
+        int group_id;                         /* identifier of the LPAR group this partition is a member of */
+        int pool_id;                          /* identifier of the shared pool of physical processors this partition is a member of */
+        int online_cpus;                      /* number of virtual CPUs currently online on the partition */
+        int max_cpus;                         /* maximum number of virtual CPUs this parition can ever have */
+        int min_cpus;                         /* minimum number of virtual CPUs this partition must have */
+        u_longlong_t online_memory;           /* amount of memory currently online */
+        u_longlong_t max_memory;              /* maximum amount of memory this partition can ever have */
+        u_longlong_t min_memory;              /* minimum amount of memory this partition must have */
+        int entitled_proc_capacity;           /* number of processor units this partition is entitled to receive */
+        int max_proc_capacity;                /* maximum number of processor units this partition can ever have */
+        int min_proc_capacity;                /* minimum number of processor units this partition must have */
+        int proc_capacity_increment;          /* increment value to the entitled capacity */
+        int unalloc_proc_capacity;            /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
+        int var_proc_capacity_weight;         /* partition priority weight to receive extra capacity */
+        int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated  in the shared processor pool this partition belongs to */
+        int online_phys_cpus_sys;             /* number of physical CPUs currently active in the system containing this partition */
+        int max_phys_cpus_sys;                /* maximum possible number of physical CPUs in the system containing this partition */
+        int phys_cpus_pool;                   /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+        u_longlong_t puser;                   /* raw number of physical processor tics in user mode */
+        u_longlong_t psys;                    /* raw number of physical processor tics in system mode */
+        u_longlong_t pidle;                   /* raw number of physical processor tics idle */
+        u_longlong_t pwait;                   /* raw number of physical processor tics waiting for I/O */
+        u_longlong_t pool_idle_time;          /* number of clock tics a processor in the shared pool was idle */
+        u_longlong_t phantintrs;              /* number of phantom interrupts received by the partition */
+        u_longlong_t invol_virt_cswitch;      /* number involuntary virtual CPU context switches */
+        u_longlong_t vol_virt_cswitch;        /* number voluntary virtual CPU context switches */
+        u_longlong_t timebase_last;           /* most recently cpu time base */
+        u_longlong_t reserved_pages;          /* Currenlty number of 16GB pages. Cannot participate in DR operations */
+        u_longlong_t reserved_pagesize;       /* Currently 16GB pagesize Cannot participate in DR operations */
+        u_longlong_t idle_donated_purr;       /* number of idle cycles donated by a dedicated partition enabled for donation */
+        u_longlong_t idle_donated_spurr;      /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
+        u_longlong_t busy_donated_purr;       /* number of busy cycles donated by a dedicated partition enabled for donation */
+        u_longlong_t busy_donated_spurr;      /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
+        u_longlong_t idle_stolen_purr;        /* number of idle cycles stolen by the hypervisor from a dedicated partition */
+        u_longlong_t idle_stolen_spurr;       /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
+        u_longlong_t busy_stolen_purr;        /* number of busy cycles stolen by the hypervisor from a dedicated partition */
+        u_longlong_t busy_stolen_spurr;       /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
+        u_longlong_t shcpus_in_sys;           /* Number of physical processors allocated for shared processor use */
+        u_longlong_t max_pool_capacity;       /* Maximum processor capacity of partitions pool */
+        u_longlong_t entitled_pool_capacity;  /* Entitled processor capacity of partitions pool */
+        u_longlong_t pool_max_time;           /* Summation of maximum time that could be consumed by the pool (nano seconds) */
+        u_longlong_t pool_busy_time;          /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+        u_longlong_t pool_scaled_busy_time;   /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
+        u_longlong_t shcpu_tot_time;          /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
+        u_longlong_t shcpu_busy_time;         /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
+        u_longlong_t shcpu_scaled_busy_time;  /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
+        int ams_pool_id;                      /* AMS pool id of the pool the LPAR belongs to */
+        int var_mem_weight;                   /* variable memory capacity weight */
+        u_longlong_t iome;                    /* I/O memory entitlement of the partition in bytes*/
+        u_longlong_t pmem;                    /* Physical memory currently backing the partition's logical memory in bytes*/
+        u_longlong_t hpi;                     /* number of hypervisor page-ins */
+        u_longlong_t hpit;                    /* Time spent in hypervisor page-ins (in nanoseconds)*/
+        u_longlong_t hypv_pagesize;           /* Hypervisor page size in KB*/
+        uint online_lcpus;                    /* number of online logical cpus */
+        uint smt_thrds;                       /* number of hardware threads that are running */
+        u_longlong_t puser_spurr;             /* number of spurr cycles spent in user mode */
+        u_longlong_t psys_spurr;              /* number of spurr cycles spent in kernel mode */
+        u_longlong_t pidle_spurr;             /* number of spurr cycles spent in idle mode */
+        u_longlong_t pwait_spurr;             /* number of spurr cycles spent in wait mode */
+        int spurrflag;                        /* set if running in spurr mode */
+        char hardwareid[CEC_ID_LEN];          /* CEC Identifier */
+        uint power_save_mode;                 /* Power save mode for the LPAR. Introduced through LI 53K PRF : Feature 728 292*/
+        ushort ame_version;                   /* AME Version */
+        u_longlong_t true_memory;             /* True Memory Size in 4KB pages */
+        u_longlong_t expanded_memory;         /* Expanded Memory Size in 4KB pages */
+        u_longlong_t target_memexp_factr;     /* Target Memory Expansion Factor scaled by 100 */
+        u_longlong_t current_memexp_factr;    /* Current Memory Expansion Factor scaled by 100 */
+        u_longlong_t target_cpool_size;       /* Target Compressed Pool Size in bytes */
+        u_longlong_t max_cpool_size;          /* Max Size of Compressed Pool in bytes */
+        u_longlong_t min_ucpool_size;         /* Min Size of Uncompressed Pool in bytes */
+        u_longlong_t ame_deficit_size;        /*Deficit memory size in bytes */
+        u_longlong_t version;                 /* version number (1, 2, etc.,) */
+        u_longlong_t cmcs_total_time;         /* Total CPU time spent due to active memory expansion */
+        u_longlong_t purr_coalescing;         /* If the calling partition is authorized to see pool wide statistics then PURR cycles consumed to coalesce data else set to zero.*/
+        u_longlong_t spurr_coalescing;        /* If the calling partition is authorized to see pool wide statistics then SPURR cycles consumed to coalesce data else set to zero.*/
+        u_longlong_t MemPoolSize;             /* Indicates the memory pool size of the pool that the partition belongs to (in bytes)., mpsz */
+        u_longlong_t IOMemEntInUse;           /* I/O memory entitlement of the LPAR in use in bytes. iomu */
+        u_longlong_t IOMemEntFree;            /* free I/O memory entitlement in bytes.  iomf */
+        u_longlong_t IOHighWaterMark;         /* high water mark of I/O memory entitlement usage in bytes. iohwn */
+        u_longlong_t purr_counter;            /* number of purr cycles spent in user + kernel mode */
+        u_longlong_t spurr_counter;           /* number of spurr cycles spent in user + kernel mode */
+
+        /* Marketing Requirement(MR): MR1124083744  */
+        u_longlong_t real_free;               /* free real memory (in 4KB pages) */
+        u_longlong_t real_avail;              /* number of pages available for user application (memfree + numperm - minperm - minfree) */
+        /*      >>>>> END OF STRUCTURE DEFINITION <<<<<         */
+#define CURR_VERSION_PARTITION_TOTAL 5        /* Incremented by one for every new release     *
+                                               * of perfstat_partition_total_t data structure */
+} perfstat_partition_total_t_71_1;
+
+typedef union { /* WPAR Type & Flags */
+        uint    w;
+        struct {
+                unsigned app_wpar :1;        /* Application WPAR */
+                unsigned cpu_rset :1;        /* WPAR restricted to CPU resource set */
+                unsigned cpu_xrset:1;        /* WPAR restricted to CPU Exclusive resource set */
+                unsigned cpu_limits :1;      /* CPU resource limits enforced */
+                unsigned mem_limits :1;      /* Memory resource limits enforced */
+                unsigned spare :27;          /* reserved for future usage */
+        } b;
+} perfstat_wpar_type_t;
+
+typedef struct { /* Workload partition Information AIX 5.3 & 6.1*/
+       char name[MAXCORRALNAMELEN+1]; /* name of the Workload Partition */
+       perfstat_wpar_type_t type;     /* set of bits describing the wpar */
+       cid_t wpar_id;                 /* workload partition identifier */
+       uint  online_cpus;             /* Number of Virtual CPUs in partition rset or  number of virtual CPUs currently online on the Global partition*/
+       int   cpu_limit;               /* CPU limit in 100ths of % - 1..10000 */
+       int   mem_limit;               /* Memory limit in 100ths of % - 1..10000 */
+       u_longlong_t online_memory;    /* amount of memory currently online in Global Partition */
+       int entitled_proc_capacity;    /* number of processor units this partition is entitled to receive */
+} perfstat_wpar_total_t_61;
+
+typedef struct { /* Workload partition Information AIX 7.1*/
+       char name[MAXCORRALNAMELEN+1]; /* name of the Workload Partition */
+       perfstat_wpar_type_t type;     /* set of bits describing the wpar */
+       cid_t wpar_id;                 /* workload partition identifier */
+       uint  online_cpus;             /* Number of Virtual CPUs in partition rset or  number of virtual CPUs currently online on the Global partition*/
+       int   cpu_limit;               /* CPU limit in 100ths of % - 1..10000 */
+       int   mem_limit;               /* Memory limit in 100ths of % - 1..10000 */
+       u_longlong_t online_memory;    /* amount of memory currently online in Global Partition */
+       int entitled_proc_capacity;    /* number of processor units this partition is entitled to receive */
+       u_longlong_t version;          /* version number (1, 2, etc.,)                  */
+/*      >>>>> END OF STRUCTURE DEFINITION <<<<<         */
+#define CURR_VERSION_WPAR_TOTAL 1     /* Incremented by one for every new release      *
+                                       * of perfstat_wpar_total_t data structure       */
+} perfstat_wpar_total_t_71;
+
+typedef void * rsethandle_t;  /* Type to identify a resource set handle: rsethandle_t */
+
+typedef enum { WPARNAME, WPARID, RSETHANDLE } wparid_specifier; /* Type of wparid_specifier */
+
+typedef struct { /* WPAR identifier */
+        wparid_specifier spec;  /* Specifier to choose wpar id or name */
+        union  {
+                cid_t wpar_id;                      /* WPAR ID */
+                rsethandle_t rset;                  /* Rset Handle */
+                char wparname[MAXCORRALNAMELEN+1];  /* WPAR NAME */
+        } u;
+        char name[IDENTIFIER_LENGTH]; /* name of the structure element identifier */
+} perfstat_id_wpar_t;
+
+
+
+// end: libperfstat.h (AIX 5.2, 5.3, 6.1, 7.1)
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1/* latest perfstat_partition_total_t structure */
+#define PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t_71             /* latest perfstat_cpu_total_t structure */
+#define PERFSTAT_WPAR_TOTAL_T_LATEST perfstat_wpar_total_t_71           /* latest perfstat_wpar_total_t structure */
 
 class libperfstat {
 
@@ -41,19 +766,107 @@
   // 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
+  // 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,
+  // Get all available data also on newer AIX versions (PERFSTAT_CPU_TOTAL_T_LATEST).
+  static int perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* 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 int perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff,
+                                      int sizeof_userbuff, int desired_number);
+
   static void perfstat_reset();
+
+  static int perfstat_wpar_total(perfstat_id_wpar_t *name, PERFSTAT_WPAR_TOTAL_T_LATEST* userbuff,
+                                 int sizeof_userbuff, int desired_number);
+
+  static cid_t wpar_getcid();
+
+
+  ////////////////////////////////////////////////////////////////
+  // The convenience functions get_partitioninfo(), get_cpuinfo(), get_wparinfo() return
+  // information about partition, cpu and wpars, respectivly. They can be used without
+  // regard for which OS release we are on. On older AIX release, some output structure
+  // members will be 0.
+
+  // Result struct for get_partitioninfo().
+  struct partitioninfo_t {
+    // partition type info
+    unsigned smt_capable :1;          /* OS supports SMT mode */
+    unsigned smt_enabled :1;          /* SMT mode is on */
+    unsigned lpar_capable :1;         /* OS supports logical partitioning */
+    unsigned lpar_enabled :1;         /* logical partitioning is on */
+    unsigned shared_capable :1;       /* OS supports shared processor LPAR */
+    unsigned shared_enabled :1;       /* partition runs in shared mode */
+    unsigned dlpar_capable :1;        /* OS supports dynamic LPAR */
+    unsigned capped :1;               /* partition is capped */
+    unsigned kernel_is_64 :1;         /* kernel is 64 bit */
+    unsigned pool_util_authority :1;  /* pool utilization available */
+    unsigned donate_capable :1;       /* capable of donating cycles */
+    unsigned donate_enabled :1;       /* enabled for donating cycles */
+    unsigned ams_capable:1;           /* 1 = AMS(Active Memory Sharing) capable, 0 = Not AMS capable */
+    unsigned ams_enabled:1;           /* 1 = AMS(Active Memory Sharing) enabled, 0 = Not AMS enabled */
+    unsigned power_save:1;            /* 1 = Power saving mode is enabled */
+    unsigned ame_enabled:1;           /* Active Memory Expansion is enabled */
+    // partition total info
+    int online_cpus;                  /* number of virtual CPUs currently online on the partition */
+    int entitled_proc_capacity;       /* number of processor units this partition is entitled to receive */
+    int var_proc_capacity_weight;     /* partition priority weight to receive extra capacity */
+    int phys_cpus_pool;               /* number of the physical CPUs currently in the shared processor pool this partition belong to */
+    int pool_id;                      /* identifier of the shared pool of physical processors this partition is a member of */
+    u_longlong_t entitled_pool_capacity;  /* Entitled processor capacity of partitions pool */
+    char name[IDENTIFIER_LENGTH];     /* name of the logical partition */
+
+    u_longlong_t timebase_last;       /* most recently cpu time base (an incremented long int on PowerPC) */
+    u_longlong_t pool_idle_time;      /* pool idle time = number of clock tics a processor in the shared pool was idle */
+    u_longlong_t pcpu_tics_user;      /* raw number of physical processor tics in user mode */
+    u_longlong_t pcpu_tics_sys;       /* raw number of physical processor tics in system mode */
+    u_longlong_t pcpu_tics_idle;      /* raw number of physical processor tics idle */
+    u_longlong_t pcpu_tics_wait;      /* raw number of physical processor tics waiting for I/O */
+
+    u_longlong_t true_memory;          /* True Memory Size in 4KB pages */
+    u_longlong_t expanded_memory;      /* Expanded Memory Size in 4KB pages */
+    u_longlong_t target_memexp_factr;  /* Target Memory Expansion Factor scaled by 100 */
+    u_longlong_t current_memexp_factr; /* Current Memory Expansion Factor scaled by 100 */
+    u_longlong_t cmcs_total_time;      /* Total CPU time spent due to active memory expansion */
+  };
+
+  // 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)
+    unsigned long long user_clock_ticks;  // raw total number of clock ticks spent in user mode
+    unsigned long long sys_clock_ticks;   // raw total number of clock ticks spent in system mode
+    unsigned long long idle_clock_ticks;  // raw total number of clock ticks spent idle
+    unsigned long long wait_clock_ticks;  // raw total number of clock ticks spent waiting for I/O
+  };
+
+  // Result struct for get_wparinfo().
+  struct wparinfo_t {
+    char name[MAXCORRALNAMELEN+1];  /* name of the Workload Partition */
+    unsigned short wpar_id;         /* workload partition identifier */
+    unsigned app_wpar :1;           /* Application WPAR */
+    unsigned cpu_rset :1;           /* WPAR restricted to CPU resource set */
+    unsigned cpu_xrset:1;           /* WPAR restricted to CPU Exclusive resource set */
+    unsigned cpu_limits :1;         /* CPU resource limits enforced */
+    unsigned mem_limits :1;         /* Memory resource limits enforced */
+    int cpu_limit;                  /* CPU limit in 100ths of % - 1..10000 */
+    int mem_limit;                  /* Memory limit in 100ths of % - 1..10000 */
+  };
+
+  static bool get_partitioninfo(partitioninfo_t* ppi);
+  static bool get_cpuinfo(cpuinfo_t* pci);
+  static bool get_wparinfo(wparinfo_t* pwi);
+
 };
 
 #endif // OS_AIX_VM_LIBPERFSTAT_AIX_HPP
--- a/src/os/aix/vm/loadlib_aix.cpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/loadlib_aix.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright 2012, 2015 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
@@ -35,7 +35,6 @@
 #endif
 
 #include "loadlib_aix.hpp"
-// for CritSect
 #include "misc_aix.hpp"
 #include "porting_aix.hpp"
 #include "utilities/debug.hpp"
--- a/src/os/aix/vm/misc_aix.cpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/misc_aix.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -26,6 +26,8 @@
 #include "runtime/stubRoutines.hpp"
 
 #include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
 
 void MiscUtils::init_critsect(MiscUtils::critsect_t* cs) {
   const int rc = pthread_mutex_init(cs, NULL);
--- a/src/os/aix/vm/misc_aix.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/misc_aix.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -29,6 +29,8 @@
 // misc_aix.hpp, misc_aix.cpp: convenience functions needed for the OpenJDK AIX
 // port.
 #include "utilities/globalDefinitions.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/debug.hpp"
 
 #include <pthread.h>
 
@@ -40,7 +42,6 @@
   } \
 }
 #define ERRBYE(s) { trcVerbose(s); return -1; }
-#define trc(fmt, ...)
 
 #define assert0(b) assert((b), "")
 #define guarantee0(b) guarantee((b), "")
--- a/src/os/aix/vm/osThread_aix.cpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/osThread_aix.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -35,7 +35,7 @@
 void OSThread::pd_initialize() {
   assert(this != NULL, "check");
   _thread_id        = 0;
-  _pthread_id       = 0;
+  _kernel_thread_id = 0;
   _siginfo = NULL;
   _ucontext = NULL;
   _expanding_stack = 0;
--- a/src/os/aix/vm/osThread_aix.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/osThread_aix.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -27,7 +27,7 @@
 #define OS_AIX_VM_OSTHREAD_AIX_HPP
 
  public:
-  typedef pid_t thread_id_t;
+  typedef pthread_t thread_id_t;
 
  private:
   int _thread_type;
@@ -43,9 +43,13 @@
 
  private:
 
-  // _pthread_id is the pthread id, which is used by library calls
-  // (e.g. pthread_kill).
-  pthread_t _pthread_id;
+  // On AIX, we use the pthread id as OSThread::thread_id and keep the kernel thread id
+  // separately for diagnostic purposes.
+  //
+  // Note: this kernel thread id is saved at thread start. Depending on the
+  // AIX scheduling mode, this may not be the current thread id (usually not
+  // a problem though as we run with AIXTHREAD_SCOPE=S).
+  tid_t _kernel_thread_id;
 
   sigset_t _caller_sigmask; // Caller's signal mask
 
@@ -66,11 +70,16 @@
     return false;
   }
 #endif // ASSERT
+  tid_t kernel_thread_id() const {
+    return _kernel_thread_id;
+  }
+  void set_kernel_thread_id(tid_t tid) {
+    _kernel_thread_id = tid;
+  }
+
   pthread_t pthread_id() const {
-    return _pthread_id;
-  }
-  void set_pthread_id(pthread_t tid) {
-    _pthread_id = tid;
+    // Here: same as OSThread::thread_id()
+    return _thread_id;
   }
 
   // ***************************************************************
--- a/src/os/aix/vm/os_aix.cpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/os_aix.cpp	Mon Nov 16 10:58:14 2015 +0100
@@ -36,6 +36,7 @@
 #include "compiler/compileBroker.hpp"
 #include "interpreter/interpreter.hpp"
 #include "jvm_aix.h"
+#include "libo4.hpp"
 #include "libperfstat_aix.hpp"
 #include "loadlib_aix.hpp"
 #include "memory/allocation.inline.hpp"
@@ -108,25 +109,14 @@
 #include <sys/vminfo.h>
 #include <sys/wait.h>
 
-// If RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling
-// getrusage() is prepared to handle the associated failure.
-#ifndef RUSAGE_THREAD
-#define RUSAGE_THREAD   (1)               /* only the calling thread */
-#endif
-
-// PPC port
-static const uintx Use64KPagesThreshold       = 1*M;
-static const uintx MaxExpectedDataSegmentSize = SIZE_4G*2;
-
-// Add missing declarations (should be in procinfo.h but isn't until AIX 6.1).
+// Missing prototypes for various system APIs.
+extern "C"
+int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t);
+
 #if !defined(_AIXVERSION_610)
-extern "C" {
-  int getthrds64(pid_t ProcessIdentifier,
-                 struct thrdentry64* ThreadBuffer,
-                 int ThreadSize,
-                 tid64_t* IndexPointer,
-                 int Count);
-}
+extern "C" int getthrds64(pid_t, struct thrdentry64*, int, tid64_t*, int);
+extern "C" int getprocs64(procentry64*, int, fdsinfo*, int, pid_t*, int);
+extern "C" int getargs   (procsinfo*, int, char*, int);
 #endif
 
 #define MAX_PATH (2 * K)
@@ -150,18 +140,9 @@
 typedef unsigned long stackslot_t;
 typedef stackslot_t* stackptr_t;
 
-// 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
-#ifndef PV_8
-#define PV_8 0x300000          /* Power PC 8 */
-#define PV_8_Compat 0x308000   /* Power PC 8 */
-#endif
-
 // Query dimensions of the stack of the calling thread.
 static bool query_stack_dimensions(address* p_stack_base, size_t* p_stack_size);
+static address resolve_function_descriptor_to_code_pointer(address p);
 
 // 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) {
@@ -185,7 +166,7 @@
   if (((uintptr_t)p) & 0x3) {
     return false;
   }
-  if (!LoadedLibraries::find_for_text_address(p, NULL)) {
+  if (LoadedLibraries::find_for_text_address(p, NULL) == NULL) {
     return false;
   }
   return true;
@@ -203,31 +184,44 @@
   CHECK_STACK_PTR(sp, stack_base, stack_size); \
 }
 
+static void vmembk_print_on(outputStream* os);
+
 ////////////////////////////////////////////////////////////////////////////////
 // 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;
+
+// -1 = uninitialized, 0 if AIX, 1 if OS/400 pase
 int       os::Aix::_on_pase = -1;
+
+// -1 = uninitialized, otherwise os version in the form 0xMMmm - MM:major, mm:minor
+//  E.g. 0x0601 for  AIX 6.1 or 0x0504 for OS/400 V5R4
 int       os::Aix::_os_version = -1;
+
 int       os::Aix::_stack_page_size = -1;
+
+// -1 = uninitialized, 0 - no, 1 - yes
 int       os::Aix::_xpg_sus_mode = -1;
+
+// -1 = uninitialized, 0 - no, 1 - yes
 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;
 
+// Process break recorded at startup.
+static address g_brk_at_startup = NULL;
+
 // This describes the state of multipage support of the underlying
 // OS. Note that this is of no interest to the outsize world and
 // therefore should not be defined in AIX class.
@@ -278,8 +272,9 @@
 // a specific wish address, e.g. to place the heap in a
 // compressed-oops-friendly way.
 static bool is_close_to_brk(address a) {
-  address a1 = (address) sbrk(0);
-  if (a >= a1 && a < (a1 + MaxExpectedDataSegmentSize)) {
+  assert0(g_brk_at_startup != NULL);
+  if (a >= g_brk_at_startup &&
+      a < (g_brk_at_startup + MaxExpectedDataSegmentSize)) {
     return true;
   }
   return false;
@@ -290,11 +285,15 @@
 }
 
 julong os::Aix::available_memory() {
+  // Avoid expensive API call here, as returned value will always be null.
+  if (os::Aix::on_pase()) {
+    return 0x0LL;
+  }
   os::Aix::meminfo_t mi;
   if (os::Aix::get_meminfo(&mi)) {
     return mi.real_free;
   } else {
-    return 0xFFFFFFFFFFFFFFFFLL;
+    return ULONG_MAX;
   }
 }
 
@@ -332,7 +331,7 @@
 
   for (int i = 0; i < numFullDisclaimsNeeded; i ++) {
     if (::disclaim(p, maxDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
-      trc("Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno);
+      trcVerbose("Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno);
       return false;
     }
     p += maxDisclaimSize;
@@ -340,7 +339,7 @@
 
   if (lastDisclaimSize > 0) {
     if (::disclaim(p, lastDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
-      trc("Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno);
+      trcVerbose("Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno);
       return false;
     }
   }
@@ -357,25 +356,30 @@
 #error Add appropriate cpu_arch setting
 #endif
 
+// Wrap the function "vmgetinfo" which is not available on older OS releases.
+static int checked_vmgetinfo(void *out, int command, int arg) {
+  if (os::Aix::on_pase() && os::Aix::os_version() < 0x0601) {
+    guarantee(false, "cannot call vmgetinfo on AS/400 older than V6R1");
+  }
+  return ::vmgetinfo(out, command, arg);
+}
 
 // Given an address, returns the size of the page backing that address.
 size_t os::Aix::query_pagesize(void* addr) {
 
+  if (os::Aix::on_pase() && os::Aix::os_version() < 0x0601) {
+    // AS/400 older than V6R1: no vmgetinfo here, default to 4K
+    return SIZE_4K;
+  }
+
   vm_page_info pi;
   pi.addr = (uint64_t)addr;
-  if (::vmgetinfo(&pi, VM_PAGE_INFO, sizeof(pi)) == 0) {
+  if (checked_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() {
@@ -387,7 +391,6 @@
   // 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;
@@ -400,7 +403,6 @@
     case SIZE_64K: return "64K";
     case SIZE_16M: return "16M";
     case SIZE_16G: return "16G";
-    case -1:       return "not set";
     default:
       assert(false, "surprise");
       return "??";
@@ -431,6 +433,8 @@
   }
 
   // Query default shm page size (LDR_CNTRL SHMPSIZE).
+  // Note that this is pure curiosity. We do not rely on default page size but set
+  // our own page size after allocated.
   {
     const int shmid = ::shmget(IPC_PRIVATE, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
     guarantee(shmid != -1, "shmget failed");
@@ -447,26 +451,26 @@
   // number of reasons so we may just as well guarantee it here.
   guarantee0(!os::Aix::is_primordial_thread());
 
-  // Query pthread stack page size.
+  // Query pthread stack page size. Should be the same as data page size because
+  // pthread stacks are allocated from C-Heap.
   {
     int dummy = 0;
     g_multipage_support.pthr_stack_pagesize = os::Aix::query_pagesize(&dummy);
   }
 
   // Query default text page size (LDR_CNTRL TEXTPSIZE).
-  /* PPC port: so far unused.
   {
     address any_function =
-      (address) resolve_function_descriptor_to_code_pointer((address)describe_pagesize);
+      resolve_function_descriptor_to_code_pointer((address)describe_pagesize);
     g_multipage_support.textpsize = os::Aix::query_pagesize(any_function);
   }
-  */
 
   // Now probe for support of 64K pages and 16M pages.
 
   // Before OS/400 V6R1, there is no support for pages other than 4K.
   if (os::Aix::on_pase_V5R4_or_older()) {
-    Unimplemented();
+    trcVerbose("OS/400 < V6R1 - no large page support.");
+    g_multipage_support.error = ERROR_MP_OS_TOO_OLD;
     goto query_multipage_support_end;
   }
 
@@ -474,10 +478,10 @@
   {
     const int MAX_PAGE_SIZES = 4;
     psize_t sizes[MAX_PAGE_SIZES];
-    const int num_psizes = ::vmgetinfo(sizes, VMINFO_GETPSIZES, MAX_PAGE_SIZES);
+    const int num_psizes = checked_vmgetinfo(sizes, VMINFO_GETPSIZES, MAX_PAGE_SIZES);
     if (num_psizes == -1) {
-      trc("vmgetinfo(VMINFO_GETPSIZES) failed (errno: %d)\n", errno);
-      trc("disabling multipage support.\n");
+      trcVerbose("vmgetinfo(VMINFO_GETPSIZES) failed (errno: %d)", errno);
+      trcVerbose("disabling multipage support.");
       g_multipage_support.error = ERROR_MP_VMGETINFO_FAILED;
       goto query_multipage_support_end;
     }
@@ -505,8 +509,8 @@
       if (::shmctl(shmid, SHM_PAGESIZE, &shm_buf) != 0) {
         const int en = errno;
         ::shmctl(shmid, IPC_RMID, NULL); // As early as possible!
-        // PPC port trcVerbose("shmctl(SHM_PAGESIZE) failed with %s",
-        // PPC port  MiscUtils::describe_errno(en));
+        trcVerbose("shmctl(SHM_PAGESIZE) failed with errno=%n",
+          errno);
       } else {
         // Attach and double check pageisze.
         void* p = ::shmat(shmid, NULL, 0);
@@ -532,35 +536,35 @@
 
 query_multipage_support_end:
 
-  trcVerbose("base page size (sysconf _SC_PAGESIZE): %s\n",
+  trcVerbose("base page size (sysconf _SC_PAGESIZE): %s",
       describe_pagesize(g_multipage_support.pagesize));
-  trcVerbose("Data page size (C-Heap, bss, etc): %s\n",
+  trcVerbose("Data page size (C-Heap, bss, etc): %s",
       describe_pagesize(g_multipage_support.datapsize));
-  trcVerbose("Text page size: %s\n",
+  trcVerbose("Text page size: %s",
       describe_pagesize(g_multipage_support.textpsize));
-  trcVerbose("Thread stack page size (pthread): %s\n",
+  trcVerbose("Thread stack page size (pthread): %s",
       describe_pagesize(g_multipage_support.pthr_stack_pagesize));
-  trcVerbose("Default shared memory page size: %s\n",
+  trcVerbose("Default shared memory page size: %s",
       describe_pagesize(g_multipage_support.shmpsize));
-  trcVerbose("Can use 64K pages dynamically with shared meory: %s\n",
+  trcVerbose("Can use 64K pages dynamically with shared meory: %s",
       (g_multipage_support.can_use_64K_pages ? "yes" :"no"));
-  trcVerbose("Can use 16M pages dynamically with shared memory: %s\n",
+  trcVerbose("Can use 16M pages dynamically with shared memory: %s",
       (g_multipage_support.can_use_16M_pages ? "yes" :"no"));
-  trcVerbose("Multipage error details: %d\n",
+  trcVerbose("Multipage error details: %d",
       g_multipage_support.error);
 
   // sanity checks
   assert0(g_multipage_support.pagesize == SIZE_4K);
   assert0(g_multipage_support.datapsize == SIZE_4K || g_multipage_support.datapsize == SIZE_64K);
-  // PPC port: so far unused.assert0(g_multipage_support.textpsize == SIZE_4K || g_multipage_support.textpsize == SIZE_64K);
+  assert0(g_multipage_support.textpsize == SIZE_4K || g_multipage_support.textpsize == SIZE_64K);
   assert0(g_multipage_support.pthr_stack_pagesize == g_multipage_support.datapsize);
   assert0(g_multipage_support.shmpsize == SIZE_4K || g_multipage_support.shmpsize == SIZE_64K);
 
-} // end os::Aix::query_multipage_support()
+}
 
 void os::init_system_properties_values() {
 
-#define DEFAULT_LIBPATH "/usr/lib:/lib"
+#define DEFAULT_LIBPATH "/lib:/usr/lib"
 #define EXTENSIONS_DIR  "/lib/ext"
 
   // Buffer that fits several sprintfs.
@@ -578,7 +582,10 @@
 
     // 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 /libjvm.so.
+    }
     pslash = strrchr(buf, '/');
     if (pslash != NULL) {
       *pslash = '\0';            // Get rid of /{client|server|hotspot}.
@@ -753,8 +760,21 @@
   memset(pmi, 0, sizeof(meminfo_t));
 
   if (os::Aix::on_pase()) {
-
-    Unimplemented();
+    // On PASE, use the libo4 porting library.
+
+    unsigned long long virt_total = 0;
+    unsigned long long real_total = 0;
+    unsigned long long real_free = 0;
+    unsigned long long pgsp_total = 0;
+    unsigned long long pgsp_free = 0;
+    if (libo4::get_memory_info(&virt_total, &real_total, &real_free, &pgsp_total, &pgsp_free)) {
+      pmi->virt_total = virt_total;
+      pmi->real_total = real_total;
+      pmi->real_free = real_free;
+      pmi->pgsp_total = pgsp_total;
+      pmi->pgsp_free = pgsp_free;
+      return true;
+    }
     return false;
 
   } else {
@@ -770,7 +790,7 @@
     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);
+      trcVerbose("perfstat_memory_total() failed (errno=%d)", errno);
       assert(0, "perfstat_memory_total() failed");
       return false;
     }
@@ -798,81 +818,6 @@
   }
 } // 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_8:
-    strcpy(pci->version, "Power PC 8");
-    break;
-  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;
-  case PV_8_Compat:
-    strcpy(pci->version, "PV_8_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
 
@@ -889,6 +834,26 @@
     thread->set_stack_size(size);
   }
 
+  const pthread_t pthread_id = ::pthread_self();
+  const tid_t kernel_thread_id = ::thread_self();
+
+  trcVerbose("newborn Thread : pthread-id %u, ktid " UINT64_FORMAT
+    ", stack %p ... %p, stacksize 0x%IX (%IB)",
+    pthread_id, kernel_thread_id,
+    thread->stack_base() - thread->stack_size(),
+    thread->stack_base(),
+    thread->stack_size(),
+    thread->stack_size());
+
+  // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc()
+  // by the pthread library). In rare cases, this may not be the case, e.g. when third-party
+  // tools hook pthread_create(). In this case, we may run into problems establishing
+  // guard pages on those stacks, because the stacks may reside in memory which is not
+  // protectable (shmated).
+  if (thread->stack_base() > ::sbrk(0)) {
+    trcVerbose("Thread " UINT64_FORMAT ": stack not in data segment.", (uint64_t) pthread_id);
+  }
+
   // Do some sanity checks.
   CHECK_CURRENT_STACK_PTR(thread->stack_base(), thread->stack_size());
 
@@ -906,28 +871,31 @@
 
   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
+  // Thread_id is pthread id.
+  osthread->set_thread_id(pthread_id);
+
+  // .. but keep kernel thread id too for diagnostics
+  osthread->set_kernel_thread_id(kernel_thread_id);
+
+  // Initialize signal mask for this thread.
   os::Aix::hotspot_sigmask(thread);
 
-  // initialize floating point control register
+  // 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
+  // Call one more level start routine.
   thread->run();
 
+  trcVerbose("Thread finished : pthread-id %u, ktid " UINT64_FORMAT ".",
+    pthread_id, kernel_thread_id);
+
   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
@@ -992,8 +960,14 @@
   pthread_attr_destroy(&attr);
 
   if (ret == 0) {
-    // PPC port traceOsMisc(("Created New Thread : pthread-id %u", tid));
+    trcVerbose("Created New Thread : pthread-id %u", tid);
   } else {
+    if (os::Aix::on_pase()) {
+      // QIBM_MULTI_THREADED=Y is needed when the launcher is started on iSeries
+      // using QSH. Otherwise pthread_create fails with errno=11.
+      trcVerbose("(Please make sure you set the environment variable "
+              "QIBM_MULTI_THREADED=Y before running this program.)");
+    }
     if (PrintMiscellaneous && (Verbose || WizardMode)) {
       perror("pthread_create()");
     }
@@ -1003,8 +977,8 @@
     return false;
   }
 
-  // Store pthread info into the OSThread
-  osthread->set_pthread_id(tid);
+  // OSThread::thread_id is the pthread id.
+  osthread->set_thread_id(tid);
 
   return true;
 }
@@ -1030,9 +1004,21 @@
     return false;
   }
 
-  // Store pthread info into the OSThread
-  osthread->set_thread_id(os::Aix::gettid());
-  osthread->set_pthread_id(::pthread_self());
+  const pthread_t pthread_id = ::pthread_self();
+  const tid_t kernel_thread_id = ::thread_self();
+
+  trcVerbose("attaching Thread : pthread-id %u, ktid " UINT64_FORMAT ", stack %p ... %p, stacksize 0x%IX (%IB)",
+    pthread_id, kernel_thread_id,
+    thread->stack_base() - thread->stack_size(),
+    thread->stack_base(),
+    thread->stack_size(),
+    thread->stack_size());
+
+  // OSThread::thread_id is the pthread id.
+  osthread->set_thread_id(pthread_id);
+
+  // .. but keep kernel thread id too for diagnostics
+  osthread->set_kernel_thread_id(kernel_thread_id);
 
   // initialize floating point control register
   os::Aix::init_thread_fpu_state();
@@ -1126,17 +1112,15 @@
   nanos = 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;
+
+    timeval time;
+    int status = gettimeofday(&time, NULL);
+    assert(status != -1, "PASE error at gettimeofday()");
+    jlong usecs = jlong((unsigned long long) time.tv_sec * (1000 * 1000) + time.tv_usec);
+    return 1000 * usecs;
+
   } else {
     // On AIX use the precision of processors real time clock
     // or time base registers.
@@ -1265,22 +1249,12 @@
   return n;
 }
 
-intx os::current_thread_id() { return (intx)pthread_self(); }
+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());
+  return getpid();
 }
 
 // DLL functions
@@ -1317,6 +1291,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     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) {
@@ -1554,62 +1531,98 @@
   os::loadavg(loadavg, 3);
   st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);
   st->cr();
+
+  // print wpar info
+  libperfstat::wparinfo_t wi;
+  if (libperfstat::get_wparinfo(&wi)) {
+    st->print_cr("wpar info");
+    st->print_cr("name: %s", wi.name);
+    st->print_cr("id:   %d", wi.wpar_id);
+    st->print_cr("type: %s", (wi.app_wpar ? "application" : "system"));
+  }
+
+  // print partition info
+  libperfstat::partitioninfo_t pi;
+  if (libperfstat::get_partitioninfo(&pi)) {
+    st->print_cr("partition info");
+    st->print_cr(" name: %s", pi.name);
+  }
+
 }
 
 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("  Base page size (sysconf _SC_PAGESIZE):  %s",
+    describe_pagesize(g_multipage_support.pagesize));
+  st->print_cr("  Data page size (C-Heap, bss, etc):      %s",
+    describe_pagesize(g_multipage_support.datapsize));
+  st->print_cr("  Text page size:                         %s",
+    describe_pagesize(g_multipage_support.textpsize));
+  st->print_cr("  Thread stack page size (pthread):       %s",
+    describe_pagesize(g_multipage_support.pthr_stack_pagesize));
   st->print_cr("  Default shared memory page size:        %s",
     describe_pagesize(g_multipage_support.shmpsize));
   st->print_cr("  Can use 64K pages dynamically with shared meory:  %s",
     (g_multipage_support.can_use_64K_pages ? "yes" :"no"));
   st->print_cr("  Can use 16M pages dynamically with shared memory: %s",
     (g_multipage_support.can_use_16M_pages ? "yes" :"no"));
-  if (g_multipage_error != 0) {
-    st->print_cr("  multipage error: %d", g_multipage_error);
-  }
+  st->print_cr("  Multipage error: %d",
+    g_multipage_support.error);
+  st->cr();
+  st->print_cr("  os::vm_page_size:       %s", describe_pagesize(os::vm_page_size()));
+  // not used in OpenJDK st->print_cr("  os::stack_page_size:    %s", describe_pagesize(os::stack_page_size()));
 
   // 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>");
 
+  // Print out EXTSHM because it is an unsupported setting.
   const char* const extshm = ::getenv("EXTSHM");
   st->print_cr("  EXTSHM=%s.", extshm ? extshm : "<unset>");
   if ( (strcmp(extshm, "on") == 0) || (strcmp(extshm, "ON") == 0) ) {
     st->print_cr("  *** Unsupported! Please remove EXTSHM from your environment! ***");
   }
 
-  // Call os::Aix::get_meminfo() to retrieve memory statistics.
+  // Print out AIXTHREAD_GUARDPAGES because it affects the size of pthread stacks.
+  const char* const aixthread_guardpages = ::getenv("AIXTHREAD_GUARDPAGES");
+  st->print_cr("  AIXTHREAD_GUARDPAGES=%s.",
+      aixthread_guardpages ? aixthread_guardpages : "<unset>");
+
   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);
+      st->print_cr("physical total : " SIZE_FORMAT, mi.real_total);
+      st->print_cr("physical free  : " SIZE_FORMAT, mi.real_free);
+      st->print_cr("swap total     : " SIZE_FORMAT, mi.pgsp_total);
+      st->print_cr("swap free      : " SIZE_FORMAT, mi.pgsp_free);
     } else {
-      Unimplemented();
+      // PASE - Numbers are result of QWCRSSTS; they mean:
+      // real_total: Sum of all system pools
+      // real_free: always 0
+      // pgsp_total: we take the size of the system ASP
+      // pgsp_free: size of system ASP times percentage of system ASP unused
+      st->print_cr("physical total     : " SIZE_FORMAT, mi.real_total);
+      st->print_cr("system asp total   : " SIZE_FORMAT, mi.pgsp_total);
+      st->print_cr("%% system asp used : " SIZE_FORMAT,
+        mi.pgsp_total ? (100.0f * (mi.pgsp_total - mi.pgsp_free) / mi.pgsp_total) : -1.0f);
     }
     st->print_raw(buffer);
-  } else {
-    st->print_cr("  (no more information available)");
-  }
+  }
+  st->cr();
+
+  // Print segments allocated with os::reserve_memory.
+  st->print_cr("internal virtual memory regions used by vm:");
+  vmembk_print_on(st);
 }
 
 // Get a string for the cpuinfo that is a summary of the cpu type
 void os::get_summary_cpu_info(char* buf, size_t buflen) {
   // This looks good
-  os::Aix::cpuinfo_t ci;
-  if (os::Aix::get_cpuinfo(&ci)) {
+  libperfstat::cpuinfo_t ci;
+  if (libperfstat::get_cpuinfo(&ci)) {
     strncpy(buf, ci.version, buflen);
   } else {
     strncpy(buf, "AIX", buflen);
@@ -1617,10 +1630,15 @@
 }
 
 void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
+  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();
 }
@@ -1759,21 +1777,75 @@
 // a counter for each possible signal value
 static volatile jint pending_signals[NSIG+1] = { 0 };
 
-// Linux(POSIX) specific hand shaking semaphore.
+// Wrapper functions for: sem_init(), sem_post(), sem_wait()
+// On AIX, we use sem_init(), sem_post(), sem_wait()
+// On Pase, we need to use msem_lock() and msem_unlock(), because Posix Semaphores
+// do not seem to work at all on PASE (unimplemented, will cause SIGILL).
+// Note that just using msem_.. APIs for both PASE and AIX is not an option either, as
+// on AIX, msem_..() calls are suspected of causing problems.
 static sem_t sig_sem;
+static msemaphore* p_sig_msem = 0;
+
+static void local_sem_init() {
+  if (os::Aix::on_aix()) {
+    int rc = ::sem_init(&sig_sem, 0, 0);
+    guarantee(rc != -1, "sem_init failed");
+  } else {
+    // Memory semaphores must live in shared mem.
+    guarantee0(p_sig_msem == NULL);
+    p_sig_msem = (msemaphore*)os::reserve_memory(sizeof(msemaphore), NULL);
+    guarantee(p_sig_msem, "Cannot allocate memory for memory semaphore");
+    guarantee(::msem_init(p_sig_msem, 0) == p_sig_msem, "msem_init failed");
+  }
+}
+
+static void local_sem_post() {
+  static bool warn_only_once = false;
+  if (os::Aix::on_aix()) {
+    int rc = ::sem_post(&sig_sem);
+    if (rc == -1 && !warn_only_once) {
+      trcVerbose("sem_post failed (errno = %d, %s)", errno, strerror(errno));
+      warn_only_once = true;
+    }
+  } else {
+    guarantee0(p_sig_msem != NULL);
+    int rc = ::msem_unlock(p_sig_msem, 0);
+    if (rc == -1 && !warn_only_once) {
+      trcVerbose("msem_unlock failed (errno = %d, %s)", errno, strerror(errno));
+      warn_only_once = true;
+    }
+  }
+}
+
+static void local_sem_wait() {
+  static bool warn_only_once = false;
+  if (os::Aix::on_aix()) {
+    int rc = ::sem_wait(&sig_sem);
+    if (rc == -1 && !warn_only_once) {
+      trcVerbose("sem_wait failed (errno = %d, %s)", errno, strerror(errno));
+      warn_only_once = true;
+    }
+  } else {
+    guarantee0(p_sig_msem != NULL); // must init before use
+    int rc = ::msem_lock(p_sig_msem, 0);
+    if (rc == -1 && !warn_only_once) {
+      trcVerbose("msem_lock failed (errno = %d, %s)", errno, strerror(errno));
+      warn_only_once = true;
+    }
+  }
+}
 
 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");
+  local_sem_init();
 }
 
 void os::signal_notify(int sig) {
   Atomic::inc(&pending_signals[sig]);
-  ::sem_post(&sig_sem);
+  local_sem_post();
 }
 
 static int check_pending_signals(bool wait) {
@@ -1796,7 +1868,7 @@
       thread->set_suspend_equivalent();
       // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
 
-      ::sem_wait(&sig_sem);
+      local_sem_wait();
 
       // were we externally suspended while we were waiting?
       threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@@ -1807,7 +1879,8 @@
         // while suspended because that would surprise the thread that
         // suspended us.
         //
-        ::sem_post(&sig_sem);
+
+        local_sem_post();
 
         thread->java_suspend_self();
       }
@@ -1858,14 +1931,14 @@
   // also check that range is fully page aligned to the page size if the block.
   void assert_is_valid_subrange(char* p, size_t s) const {
     if (!contains_range(p, s)) {
-      fprintf(stderr, "[" PTR_FORMAT " - " PTR_FORMAT "] is not a sub "
-              "range of [" PTR_FORMAT " - " PTR_FORMAT "].\n",
-              p, p + s - 1, addr, addr + size - 1);
+      trcVerbose("[" PTR_FORMAT " - " PTR_FORMAT "] is not a sub "
+              "range of [" PTR_FORMAT " - " PTR_FORMAT "].",
+              p, p + s, addr, addr + size);
       guarantee0(false);
     }
     if (!is_aligned_to(p, pagesize) || !is_aligned_to(p + s, pagesize)) {
-      fprintf(stderr, "range [" PTR_FORMAT " - " PTR_FORMAT "] is not"
-              " aligned to pagesize (%s)\n", p, p + s);
+      trcVerbose("range [" PTR_FORMAT " - " PTR_FORMAT "] is not"
+              " aligned to pagesize (%lu)", p, p + s, (unsigned long) pagesize);
       guarantee0(false);
     }
   }
@@ -1962,7 +2035,7 @@
   // Reserve the shared segment.
   int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRUSR | S_IWUSR);
   if (shmid == -1) {
-    trc("shmget(.., " UINTX_FORMAT ", ..) failed (errno: %d).", size, errno);
+    trcVerbose("shmget(.., " UINTX_FORMAT ", ..) failed (errno: %d).", size, errno);
     return NULL;
   }
 
@@ -1991,7 +2064,7 @@
 
   // (A) Right after shmat and before handing shmat errors delete the shm segment.
   if (::shmctl(shmid, IPC_RMID, NULL) == -1) {
-    trc("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno);
+    trcVerbose("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno);
     assert(false, "failed to remove shared memory segment!");
   }
 
@@ -2056,6 +2129,8 @@
   return true;
 }
 
+////////////////////////////////  mmap-based routines /////////////////////////////////
+
 // Reserve memory via mmap.
 // If <requested_addr> is given, an attempt is made to attach at the given address.
 // Failing that, memory is allocated at any address.
@@ -2201,9 +2276,6 @@
   return rc;
 }
 
-// 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");
@@ -2245,11 +2317,18 @@
     size, os::vm_page_size());
 
   vmembk_t* const vmi = vmembk_find(addr);
-  assert0(vmi);
+  guarantee0(vmi);
   vmi->assert_is_valid_subrange(addr, size);
 
   trcVerbose("commit_memory [" PTR_FORMAT " - " PTR_FORMAT "].", addr, addr + size - 1);
 
+  if (UseExplicitCommit) {
+    // AIX commits memory on touch. So, touch all pages to be committed.
+    for (char* p = addr; p < (addr + size); p += SIZE_4K) {
+      *p = '\0';
+    }
+  }
+
   return true;
 }
 
@@ -2274,7 +2353,7 @@
 
   // Dynamically do different things for mmap/shmat.
   const vmembk_t* const vmi = vmembk_find(addr);
-  assert0(vmi);
+  guarantee0(vmi);
   vmi->assert_is_valid_subrange(addr, size);
 
   if (vmi->type == VMEM_SHMATED) {
@@ -2372,7 +2451,7 @@
 
   // Dynamically do different things for mmap/shmat.
   vmembk_t* const vmi = vmembk_find(addr);
-  assert0(vmi);
+  guarantee0(vmi);
 
   // Always round to os::vm_page_size(), which may be larger than 4K.
   size = align_size_up(size, os::vm_page_size());
@@ -2448,11 +2527,31 @@
       } else {
         rc = read_protected;
       }
+
+      if (!rc) {
+        if (os::Aix::on_pase()) {
+          // There is an issue on older PASE systems where mprotect() will return success but the
+          // memory will not be protected.
+          // This has nothing to do with the problem of using mproect() on SPEC1170 incompatible
+          // machines; we only see it rarely, when using mprotect() to protect the guard page of
+          // a stack. It is an OS error.
+          //
+          // A valid strategy is just to try again. This usually works. :-/
+
+          ::usleep(1000);
+          if (::mprotect(addr, size, prot) == 0) {
+            const bool read_protected_2 =
+              (SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
+              SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
+            rc = true;
+          }
+        }
+      }
     }
   }
-  if (!rc) {
-    assert(false, "mprotect failed.");
-  }
+
+  assert(rc == true, "mprotect failed.");
+
   return rc;
 }
 
@@ -2489,10 +2588,11 @@
 }
 
 char* os::reserve_memory_special(size_t bytes, size_t alignment, 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;
+  // reserve_memory_special() is used to allocate large paged memory. On AIX, we implement
+  // 64k paged memory reservation using the normal memory allocation paths (os::reserve_memory()),
+  // so this is not needed.
+  assert(false, "should not be called on AIX");
+  return NULL;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
@@ -2944,7 +3044,9 @@
   // getting raised while being blocked.
   unblock_program_error_signals();
 
+  int orig_errno = errno;  // Preserve errno value over signal handler.
   JVM_handle_aix_signal(sig, info, uc, true);
+  errno = orig_errno;
 }
 
 // This boolean allows users to forward their own non-matching signals
@@ -3066,7 +3168,6 @@
   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)) {
@@ -3090,7 +3191,6 @@
     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;
   }
@@ -3282,7 +3382,7 @@
   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");
+    os_sigaction = CAST_TO_FN_PTR(os_sigaction_t, dlsym(RTLD_DEFAULT, "sigaction"));
     if (os_sigaction == NULL) return;
   }
 
@@ -3299,7 +3399,6 @@
   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;
 
@@ -3357,6 +3456,10 @@
   // (Shared memory boundary is supposed to be a 256M aligned.)
   assert(SHMLBA == ((uint64_t)0x10000000ULL)/*256M*/, "unexpected");
 
+  // Record process break at startup.
+  g_brk_at_startup = (address) ::sbrk(0);
+  assert(g_brk_at_startup != (address) -1, "sbrk failed");
+
   // 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();
@@ -3364,7 +3467,7 @@
   // Scan environment (SPEC1170 behaviour, etc).
   os::Aix::scan_environment();
 
-  // Check which pages are supported by AIX.
+  // Probe multipage support.
   query_multipage_support();
 
   // Act like we only have one page size by eliminating corner cases which
@@ -3417,9 +3520,9 @@
     }
   } else {
     // datapsize = 64k. Data segment, thread stacks are 64k paged.
-    //   This normally means that we can allocate 64k pages dynamically.
-    //   (There is one special case where this may be false: EXTSHM=on.
-    //    but we decided to not support that mode).
+    // This normally means that we can allocate 64k pages dynamically.
+    // (There is one special case where this may be false: EXTSHM=on.
+    // but we decided to not support that mode).
     assert0(g_multipage_support.can_use_64K_pages);
     Aix::_page_size = SIZE_64K;
     trcVerbose("64K page mode");
@@ -3435,7 +3538,7 @@
   _page_sizes[0] = 0;
 
   // debug trace
-  trcVerbose("os::vm_page_size %s\n", describe_pagesize(os::vm_page_size()));
+  trcVerbose("os::vm_page_size %s", describe_pagesize(os::vm_page_size()));
 
   // Next, we need to initialize libo4 and libperfstat libraries.
   if (os::Aix::on_pase()) {
@@ -3453,8 +3556,6 @@
   // need libperfstat etc.
   os::Aix::initialize_system_info();
 
-  _initial_pid = getpid();
-
   clock_tics_per_sec = sysconf(_SC_CLK_TCK);
 
   init_random(1234567);
@@ -3479,11 +3580,21 @@
 // This is called _after_ the global arguments have been parsed.
 jint os::init_2(void) {
 
+  if (os::Aix::on_pase()) {
+    trcVerbose("Running on PASE.");
+  } else {
+    trcVerbose("Running on AIX (not PASE).");
+  }
+
   trcVerbose("processor count: %d", os::_processor_count);
   trcVerbose("physical memory: %lu", Aix::_physical_memory);
 
   // Initially build up the loaded dll map.
   LoadedLibraries::reload();
+  if (Verbose) {
+    trcVerbose("Loaded Libraries: ");
+    LoadedLibraries::print(tty);
+  }
 
   const int page_size = Aix::page_size();
   const int map_size = page_size;
@@ -3521,10 +3632,8 @@
                                      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);
-      }
+      trcVerbose("SafePoint Polling  Page address: %p (wish) => %p",
+                   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.
@@ -3551,11 +3660,9 @@
     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
+    trcVerbose("Memory Serialize  Page address: %p - %p, size %IX (%IB)",
+        mem_serialize_page, mem_serialize_page + Aix::page_size(),
+        Aix::page_size(), Aix::page_size());
   }
 
   // initialize suspend/resume support - must do this before signal_sets_init()
@@ -3592,7 +3699,10 @@
   // 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 (UseNUMA) {
+    UseNUMA = false;
+    warning("NUMA optimizations are not available on this OS.");
+  }
 
   if (MaxFDLimit) {
     // Set the number of file descriptors to max. print out error
@@ -3614,7 +3724,7 @@
 
   if (PerfAllowAtExitRegistration) {
     // Only register atexit functions if PerfAllowAtExitRegistration is set.
-    // Atexit functions can be delayed until process exit time, which
+    // At exit 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.
 
@@ -3714,16 +3824,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // 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) {
 
   st->print(PTR_FORMAT ": ", addr);
@@ -4087,24 +4187,28 @@
 // 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;
+
+    // AS/400 PASE: use libo4 porting library
+    double v[3] = { 0.0, 0.0, 0.0 };
+
+    if (libo4::get_load_avg(v, v + 1, v + 2)) {
+      for (int i = 0; i < nelem; i ++) {
+        values[i] = v[i];
+      }
+      return nelem;
+    } else {
+      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)) {
+    libperfstat::cpuinfo_t ci;
+    if (libperfstat::get_cpuinfo(&ci)) {
       for (int i = 0; i < nelem; i++) {
         values[i] = ci.loadavg[i];
       }
@@ -4131,8 +4235,7 @@
       (void)::poll(NULL, 0, 100);
     }
   } else {
-    jio_fprintf(stderr,
-      "Could not open pause file '%s', continuing immediately.\n", filename);
+    trcVerbose("Could not open pause file '%s', continuing immediately.", filename);
   }
 }
 
@@ -4154,7 +4257,7 @@
   memset(&uts, 0, sizeof(uts));
   strcpy(uts.sysname, "?");
   if (::uname(&uts) == -1) {
-    trc("uname failed (%d)", errno);
+    trcVerbose("uname failed (%d)", errno);
     guarantee(0, "Could not determine whether we run on AIX or PASE");
   } else {
     trcVerbose("uname says: sysname \"%s\" version \"%s\" release \"%s\" "
@@ -4166,15 +4269,22 @@
     assert(minor > 0, "invalid OS release");
     _os_version = (major << 8) | minor;
     if (strcmp(uts.sysname, "OS400") == 0) {
-      Unimplemented();
+      // We run on AS/400 PASE. We do not support versions older than V5R4M0.
+      _on_pase = 1;
+      if (_os_version < 0x0504) {
+        trcVerbose("OS/400 releases older than V5R4M0 not supported.");
+        assert(false, "OS/400 release too old.");
+      } else {
+        trcVerbose("We run on OS/400 (pase) V%dR%d", major, minor);
+      }
     } 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) {
-        trc("AIX release older than AIX 5.3 not supported.");
+        trcVerbose("AIX release older than AIX 5.3 not supported.");
         assert(false, "AIX release too old.");
       } else {
-        trcVerbose("We run on AIX %d.%d\n", major, minor);
+        trcVerbose("We run on AIX %d.%d", major, minor);
       }
     } else {
       assert(false, "unknown OS");
@@ -4200,12 +4310,17 @@
   // 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>");
-  }
+  trcVerbose("EXTSHM=%s.", p ? p : "<unset>");
   if (p && strcasecmp(p, "ON") == 0) {
-    fprintf(stderr, "Unsupported setting: EXTSHM=ON. Large Page support will be disabled.\n");
     _extshm = 1;
+    trcVerbose("*** Unsupported mode! Please remove EXTSHM from your environment! ***");
+    if (!AllowExtshm) {
+      // We allow under certain conditions the user to continue. However, we want this
+      // to be a fatal error by default. On certain AIX systems, leaving EXTSHM=ON means
+      // that the VM is not able to allocate 64k pages for the heap.
+      // We do not want to run with reduced performance.
+      vm_exit_during_initialization("EXTSHM is ON. Please remove EXTSHM from your environment.");
+    }
   } else {
     _extshm = 0;
   }
@@ -4222,7 +4337,7 @@
   trcVerbose("XPG_SUS_ENV=%s.", p ? p : "<unset>");
   if (p && strcmp(p, "ON") == 0) {
     _xpg_sus_mode = 1;
-    trc("Unsupported setting: XPG_SUS_ENV=ON");
+    trcVerbose("Unsupported setting: XPG_SUS_ENV=ON");
     // 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.
@@ -4231,35 +4346,46 @@
     _xpg_sus_mode = 0;
   }
 
-  // Switch off AIX internal (pthread) guard pages. This has
-  // immediate effect for any pthread_create calls which follow.
+  if (os::Aix::on_pase()) {
+    p = ::getenv("QIBM_MULTI_THREADED");
+    trcVerbose("QIBM_MULTI_THREADED=%s.", p ? p : "<unset>");
+  }
+
+  p = ::getenv("LDR_CNTRL");
+  trcVerbose("LDR_CNTRL=%s.", p ? p : "<unset>");
+  if (os::Aix::on_pase() && os::Aix::os_version() == 0x0701) {
+    if (p && ::strstr(p, "TEXTPSIZE")) {
+      trcVerbose("*** WARNING - LDR_CNTRL contains TEXTPSIZE. "
+        "you may experience hangs or crashes on OS/400 V7R1.");
+    }
+  }
+
   p = ::getenv("AIXTHREAD_GUARDPAGES");
   trcVerbose("AIXTHREAD_GUARDPAGES=%s.", p ? p : "<unset>");
-  rc = ::putenv("AIXTHREAD_GUARDPAGES=0");
-  guarantee(rc == 0, "");
 
 } // end: os::Aix::scan_environment()
 
-// PASE: initialize the libo4 library (AS400 PASE porting library).
+// PASE: initialize the libo4 library (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.
+  guarantee(os::Aix::on_pase(), "OS/400 only.");
+  if (!libo4::init()) {
+    trcVerbose("libo4 initialization failed.");
+    assert(false, "libo4 initialization failed");
+  } else {
+    trcVerbose("libo4 initialized.");
+  }
+}
+
+// AIX: initialize the libperfstat library.
 void os::Aix::initialize_libperfstat() {
-
   assert(os::Aix::on_aix(), "AIX only");
-
   if (!libperfstat::init()) {
-    trc("libperfstat initialization failed.");
+    trcVerbose("libperfstat initialization failed.");
     assert(false, "libperfstat initialization failed");
   } else {
-    if (Verbose) {
-      fprintf(stderr, "libperfstat initialized.\n");
-    }
-  }
-} // end: os::Aix::initialize_libperfstat
+    trcVerbose("libperfstat initialized.");
+  }
+}
 
 /////////////////////////////////////////////////////////////////////////////
 // thread stack
@@ -4296,10 +4422,11 @@
   }
   guarantee0(pinfo.__pi_stackend);
 
-  // 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.
+  // The following may 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 then.
+
   guarantee0(pinfo.__pi_stacksize);
 
   // Note: we get three values from pthread_getthrds_np:
@@ -4326,7 +4453,8 @@
   //
 
   address stack_base = (address)(pinfo.__pi_stackend);
-  address stack_low_addr = (address)align_ptr_up(pinfo.__pi_stackaddr,  os::vm_page_size());
+  address stack_low_addr = (address)align_ptr_up(pinfo.__pi_stackaddr,
+    os::vm_page_size());
   size_t stack_size = stack_base - stack_low_addr;
 
   if (p_stack_base) {
--- a/src/os/aix/vm/os_aix.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/os_aix.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -34,9 +34,6 @@
 class Aix {
   friend class os;
 
-  // Length of strings included in the libperfstat structures.
-#define IDENTIFIER_LENGTH 64
-
   static bool libjsig_is_loaded;        // libjsig that interposes sigaction(),
                                         // __sigaction(), signal() is loaded
   static struct sigaction *(*get_signal_action)(int);
@@ -45,13 +42,15 @@
 
   static void check_signal_handler(int sig);
 
- protected:
+ private:
 
   static julong _physical_memory;
   static pthread_t _main_thread;
   static Mutex* _createThread_lock;
   static int _page_size;
-  static int _logical_cpus;
+
+  // Page size of newly created pthreads.
+  static int _stack_page_size;
 
   // -1 = uninitialized, 0 = AIX, 1 = OS/400 (PASE)
   static int _on_pase;
@@ -63,6 +62,9 @@
   //  for OS/400 e.g. 0x0504 for OS/400 V5R4
   static int _os_version;
 
+  // 4 Byte kernel version: Version, Release, Tech Level, Service Pack.
+  static unsigned int _os_kernel_version;
+
   // -1 = uninitialized,
   //  0 - SPEC1170 not requested (XPG_SUS_ENV is OFF or not set)
   //  1 - SPEC1170 requested (XPG_SUS_ENV is ON)
@@ -73,35 +75,6 @@
   //  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;
-
   static julong available_memory();
   static julong physical_memory() { return _physical_memory; }
   static void initialize_system_info();
@@ -125,9 +98,6 @@
  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);
@@ -215,6 +185,14 @@
     return _os_version;
   }
 
+  // Get 4 byte AIX kernel version number:
+  // highest 2 bytes: Version, Release
+  // if available: lowest 2 bytes: Tech Level, Service Pack.
+  static unsigned int os_kernel_version() {
+    if (_os_kernel_version) return _os_kernel_version;
+    return os_version() << 16;
+  }
+
   // Convenience method: returns true if running on PASE V5R4 or older.
   static bool on_pase_V5R4_or_older() {
     return on_pase() && os_version() <= 0x0504;
@@ -257,27 +235,12 @@
 
   };
 
-  // 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> {
--- a/src/os/aix/vm/os_aix.inline.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os/aix/vm/os_aix.inline.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -60,6 +60,8 @@
 // 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) {
+  // TODO: Determine whether Sys V memory is split. If yes, we need to treat
+  // this the same way Windows treats its VirtualAlloc allocations.
 }
 
 // Bang the shadow pages if they need to be touched to be mapped.
--- a/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp	Sat Dec 05 07:16:52 2015 +0100
+++ b/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp	Mon Nov 16 10:58:14 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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.
  *
@@ -35,8 +35,7 @@
   /******************************/                                                                                                   \
   /* Threads (NOTE: incomplete) */                                                                                                   \
   /******************************/                                                                                                   \
-  nonstatic_field(OSThread,                      _thread_id,                                      pid_t)                             \
-  nonstatic_field(OSThread,                      _pthread_id,                                     pthread_t)
+  nonstatic_field(OSThread,                      _thread_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) \
@@ -45,7 +44,6 @@
   /* 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)