# HG changeset patch # User stuefe # Date 1447667894 -3600 # Mon Nov 16 10:58:14 2015 +0100 # Node ID 19bc0fd9c4d2a396a452f2b9f7bd9f9a2c7fb77b # Parent 756e5b1c59fad2c62f8523e15753d0239e2d5304 imported patch aix-cleanup-2 diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/globals_aix.hpp --- a/src/os/aix/vm/globals_aix.hpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/globals_aix.hpp Mon Nov 16 10:58:14 2015 +0100 @@ -29,40 +29,58 @@ // // Defines Aix specific flags. They are not available on other platforms. // -#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \ +// (Please keep the switches sorted alphabetically.) +#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, retired) \ \ - /* Use 64K pages for virtual memory (shmat). */ \ + /* 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 variabkle is found; for certain */ \ + /* customer scenarios, we may want to tbe able to run despite that variable. */ \ + product(bool, AllowExtshm, false, \ + "Allow VM to run with EXTSHM=ON.") \ + \ + /* 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 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); define_pd_global(bool, UseThreadPriorities, true) ; #endif // OS_AIX_VM_GLOBALS_AIX_HPP + diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/libperfstat_aix.cpp --- a/src/os/aix/vm/libperfstat_aix.cpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/libperfstat_aix.cpp Mon Nov 16 10:58:14 2015 +0100 @@ -22,49 +22,50 @@ * */ -#include "runtime/arguments.hpp" #include "libperfstat_aix.hpp" +#include "misc_aix.hpp" -// For dlopen and friends -#include +#include +#include -// 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,267 @@ 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.2 and XLC 8 +// SAPJVM MBS 2012-08-14 : on AIX 5.3/ xlC10 some of the definitions are available but +// e.g. PV_/ stuff is still missing so keep the definitions +// +// XLC 8 build is using the systemcfg.h from /usr/vacpp/include/sys instead of /usr/include/sys +// Missing values for the version field +#define PV_5_2 0x0F0001 /* Power PC 5 */ +#define PV_5_3 0x0F0002 /* Power PC 5 */ +#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)) { + if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(perfstat_cpu_total_t_52), 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; + +} + + + + diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/libperfstat_aix.hpp --- a/src/os/aix/vm/libperfstat_aix.hpp Sat Nov 14 18:26:35 2015 +0000 +++ 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,791 @@ #ifndef OS_AIX_VM_LIBPERFSTAT_AIX_HPP #define OS_AIX_VM_LIBPERFSTAT_AIX_HPP -#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////////////// +// 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 +// +// 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.2 */ + 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<. */ + 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 */ +} perfstat_cpu_total_t_52; + +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<. */ + 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<. */ + 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<. */ + 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 p +ool 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 +825,149 @@ // Load the libperfstat library (must be in LIBPATH). // Returns true if succeeded, false if error. static bool init(); - - // cleanup of the libo4 porting library. static void cleanup(); // direct wrappers for the libperfstat functionality. All they do is // to call the functions with the same name via function pointers. - static int perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff, + // SAP JVM ASt 2011-05-12: 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); + // implement if needed + //int perfstat_cpu(perfstat_id_t *name, perfstat_cpu_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_disk_total(perfstat_id_t *name, perfstat_disk_total_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_disk(perfstat_id_t *name, perfstat_disk_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_diskadapter(perfstat_id_t *name, perfstat_diskadapter_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_diskpath(perfstat_id_t *name, perfstat_diskpath_t* userbuff, int sizeof_userbuff, + // int desired_number); + static int perfstat_memory_total(perfstat_id_t *name, perfstat_memory_total_t* userbuff, int sizeof_userbuff, int desired_number); + // implement if needed + //int perfstat_netinterface_total(perfstat_id_t *name, perfstat_netinterface_total_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_netinterface(perfstat_id_t *name, perfstat_netinterface_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_pagingspace(perfstat_id_t *name, perfstat_pagingspace_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_netbuffer(perfstat_id_t *name, perfstat_netbuffer_t* userbuff, + // int sizeof_userbuff, int desired_number); + + // implement if needed + //int perfstat_protocol(perfstat_id_t *name, perfstat_protocol_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); + + // Reset the information provided by ODM. 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<. + 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 + diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/loadlib_aix.cpp --- a/src/os/aix/vm/loadlib_aix.cpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/loadlib_aix.cpp Mon Nov 16 10:58:14 2015 +0100 @@ -22,7 +22,6 @@ * */ - // Implementation of LoadedLibraries and friends // Ultimately this just uses loadquery() @@ -35,7 +34,6 @@ #endif #include "loadlib_aix.hpp" -// for CritSect #include "misc_aix.hpp" #include "porting_aix.hpp" #include "utilities/debug.hpp" @@ -47,14 +45,14 @@ // Use raw malloc instead of os::malloc - this code gets used for error reporting. // A class to "intern" eternal strings. -// TODO: similar coding exists in AIX version of dladdr and potentially elsewhere: consolidate! +// TODO: similar coding exists in AIX vcersion of dladdr and potentially elsewhere: consolidate! class StringList { char** _list; int _cap; int _num; - // Enlarge list. If oom, leave old list intact and return false. + // enlarge list. If oom, leave old list intact and return false. bool enlarge() { int cap2 = _cap + 64; char** l2 = (char**) ::realloc(_list, sizeof(char*) * cap2); @@ -66,8 +64,8 @@ return true; } - // Append string to end of list. - // Returns NULL if oom. + // append string to end of list + // returns NULL if oom char* append(const char* s) { if (_cap == _num) { if (!enlarge()) { @@ -93,14 +91,14 @@ , _num(0) {} - // String is copied into the list; pointer to copy is returned. - // Returns NULL if oom. + // string is copied into the list; pointer to copy is returned. + // returns NULL if oom. char* add (const char* s) { - for (int i = 0; i < _num; i++) { + for (int i = 0; i < _num; i ++) { if (strcmp(_list[i], s) == 0) { return _list[i]; } - } + } return append(s); } @@ -110,7 +108,7 @@ ////////////////////// -// Entries are kept in a linked list ordered by text address. Entries are not +// Entries are kept in a linked list ordered by text address. Entries are not // eternal - this list is rebuilt on every reload. // Note that we do not hand out those entries, but copies of them. @@ -121,7 +119,7 @@ static void print_entry(const entry_t* e, outputStream* os) { const loaded_module_t* const lm = &(e->info); - os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT + os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " " "%s", (lm->is_in_vm ? '*' : ' '), @@ -131,14 +129,15 @@ if (lm->member) { os->print("(%s)", lm->member); } -} + +} static entry_t* g_first = NULL; static entry_t* find_entry_for_text_address(const void* p) { for (entry_t* e = g_first; e; e = e->next) { - if ((uintptr_t)p >= (uintptr_t)e->info.text && - (uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len)) { + if ( (uintptr_t)p >= (uintptr_t)e->info.text && + (uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len) ) { return e; } } @@ -147,15 +146,15 @@ static entry_t* find_entry_for_data_address(const void* p) { for (entry_t* e = g_first; e; e = e->next) { - if ((uintptr_t)p >= (uintptr_t)e->info.data && - (uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len)) { + if ( (uintptr_t)p >= (uintptr_t)e->info.data && + (uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len) ) { return e; } } return NULL; } -// Adds a new entry to the list (ordered by text address ascending). +// adds a new entry to the list (ordered by text address ascending) static void add_entry_to_list(entry_t* e, entry_t** start) { entry_t* last = NULL; entry_t* e2 = *start; @@ -182,21 +181,26 @@ } -// Rebuild the internal module table. If an error occurs, old table remains +// rebuild the internal module table. If an error occurs, old table remains // unchanged. static bool reload_table() { - bool rc = false; + bool rc = false; trcVerbose("reload module table..."); entry_t* new_list = NULL; const struct ld_info* ldi = NULL; - // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery + // call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery // requires a large enough buffer. uint8_t* buffer = NULL; - size_t buflen = 1024; + size_t buflen = +#ifdef ASSERT + 64; +#else + 1024; +#endif for (;;) { buffer = (uint8_t*) ::realloc(buffer, buflen); if (loadquery(L_GETINFO, buffer, buflen) == -1) { @@ -213,11 +217,11 @@ trcVerbose("loadquery buffer size is %llu.", buflen); - // Iterate over the loadquery result. For details see sys/ldr.h on AIX. + // iterate over the loadquery result. For details see sys/ldr.h on AIX. ldi = (struct ld_info*) buffer; for (;;) { - + entry_t* e = (entry_t*) ::malloc(sizeof(entry_t)); if (!e) { trcVerbose("OOM."); @@ -226,7 +230,7 @@ memset(e, 0, sizeof(entry_t)); - e->info.text = ldi->ldinfo_textorg; + e->info.text = ldi->ldinfo_textorg; e->info.text_len = ldi->ldinfo_textsize; e->info.data = ldi->ldinfo_dataorg; e->info.data_len = ldi->ldinfo_datasize; @@ -237,7 +241,7 @@ goto cleanup; } - // Extract short name + // extract short name { const char* p = strrchr(e->info.path, '/'); if (p) { @@ -248,8 +252,8 @@ } } - // Do we have a member name as well (see ldr.h)? - const char* p_mbr_name = + // do we have a member name as well (see ldr.h)? + const char* p_mbr_name = ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1; if (*p_mbr_name) { e->info.member = g_stringlist.add(p_mbr_name); @@ -261,9 +265,9 @@ e->info.member = NULL; } - if (strcmp(e->info.shortname, "libjvm.so") == 0) { - // Note that this, theoretically, is fuzzy. We may accidentally contain - // more than one libjvm.so. But that is improbable, so lets go with this + if (strcmp(e->info.shortname, "libjvm.so") == 0) { + // note that this, theoretically, is fuzzy. We may accidentally contain + // more than one libjvm.so. But that is improbable, so lets go with this // solution. e->info.is_in_vm = true; } @@ -271,15 +275,15 @@ trcVerbose("entry: %p %llu, %p %llu, %s %s %s, %d", e->info.text, e->info.text_len, e->info.data, e->info.data_len, - e->info.path, e->info.shortname, + e->info.path, e->info.shortname, (e->info.member ? e->info.member : "NULL"), e->info.is_in_vm ); - // Add to list. + // add to list add_entry_to_list(e, &new_list); - // Next entry... + // next entry... if (ldi->ldinfo_next) { ldi = (struct ld_info*)(((char*)ldi) + ldi->ldinfo_next); } else { @@ -287,13 +291,13 @@ } } - // We are done. All is well. Free old list and swap to new one. + // we are done. All is well. Free old list and swap to new one. if (g_first) { free_entry_list(&g_first); } g_first = new_list; new_list = NULL; - + rc = true; cleanup: @@ -309,12 +313,12 @@ } // end LoadedLibraries::reload() -/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// // Externals static MiscUtils::CritSect g_cs; -// Rebuild the internal module table. If an error occurs, old table remains +// rebuild the internal module table. If an error occurs, old table remains // unchanged. bool LoadedLibraries::reload() { MiscUtils::AutoCritSect lck(&g_cs); @@ -332,8 +336,10 @@ } } -bool LoadedLibraries::find_for_text_address(const void* p, - loaded_module_t* info) { + +bool LoadedLibraries::find_for_text_address ( + const void* p, loaded_module_t* info +) { MiscUtils::AutoCritSect lck(&g_cs); if (!g_first) { reload_table(); @@ -367,3 +373,4 @@ return false; } + diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/misc_aix.cpp --- a/src/os/aix/vm/misc_aix.cpp Sat Nov 14 18:26:35 2015 +0000 +++ 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 +#include +#include void MiscUtils::init_critsect(MiscUtils::critsect_t* cs) { const int rc = pthread_mutex_init(cs, NULL); @@ -58,4 +60,236 @@ (SafeFetch32(aligned, deadbeef) != deadbeef); } +const char* MiscUtils::describe_errno(int err_no) { + switch (err_no) { + case E2BIG: return "E2BIG"; + case EACCES: return "EACCES"; +#ifdef EADDRINUSE + case EADDRINUSE: return "EADDRINUSE"; +#endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: return "EADDRNOTAVAIL"; +#endif +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: return "EAFNOSUPPORT"; +#endif + case EAGAIN: return "EAGAIN"; +#ifdef EALREADY + case EALREADY: return "EALREADY"; +#endif + case EBADF: return "EBADF"; +#ifdef EBADMSG + case EBADMSG: return "EBADMSG"; +#endif + case EBUSY: return "EBUSY"; +#ifdef ECANCELED + case ECANCELED: return "ECANCELED"; +#endif +#ifdef ECHILD + case ECHILD: return "ECHILD"; +#endif +#ifdef ECONNABORTED + case ECONNABORTED: return "ECONNABORTED"; +#endif +#ifdef ECONNREFUSED + case ECONNREFUSED: return "ECONNREFUSED"; +#endif +#ifdef ECONNRESET + case ECONNRESET: return "ECONNRESET"; +#endif +#ifdef EDEADLK + case EDEADLK: return "EDEADLK"; +#endif +#ifdef EDESTADDRREQ + case EDESTADDRREQ: return "EDESTADDRREQ"; +#endif +#ifdef EDOM + case EDOM: return "EDOM"; +#endif +#ifdef EDQUOT + case EDQUOT: return "EDQUOT"; +#endif +#ifdef EEXIST + case EEXIST: return "EEXIST"; +#endif + case EFAULT: return "EFAULT"; +#ifdef EFBIG + case EFBIG: return "EFBIG"; +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: return "EHOSTUNREACH"; +#endif +#ifdef EIDRM + case EIDRM: return "EIDRM"; +#endif +#ifdef EILSEQ + case EILSEQ: return "EILSEQ"; +#endif +#ifdef EINPROGRESS + case EINPROGRESS: return "EINPROGRESS"; +#endif + case EINTR: return "EINTR"; + case EINVAL: return "EINVAL"; +#ifdef EIO + case EIO: return "EIO"; +#endif +#ifdef EISCONN + case EISCONN: return "EISCONN"; +#endif + case EISDIR: return "EISDIR"; +#ifdef ELOOP + case ELOOP: return "ELOOP"; +#endif +#ifdef EMFILE + case EMFILE: return "EMFILE"; +#endif +#ifdef EMLINK + case EMLINK: return "EMLINK"; +#endif +#ifdef EMSGSIZE + case EMSGSIZE: return "EMSGSIZE"; +#endif +#ifdef EMULTIHOP + case EMULTIHOP: return "EMULTIHOP"; +#endif + case ENAMETOOLONG: return "ENAMETOOLONG"; +#ifdef ENETDOWN + case ENETDOWN: return "ENETDOWN"; +#endif +#ifdef ENETRESET + case ENETRESET: return "ENETRESET"; +#endif +#ifdef ENETUNREACH + case ENETUNREACH: return "ENETUNREACH"; +#endif +#ifdef ENFILE + case ENFILE: return "ENFILE"; +#endif +#ifdef ENOBUFS + case ENOBUFS: return "ENOBUFS"; +#endif +#ifdef ENODATA + case ENODATA: return "ENODATA"; +#endif +#ifdef ENODEV + case ENODEV: return "ENODEV"; +#endif + case ENOENT: return "ENOENT"; +#ifdef ENOEXEC + case ENOEXEC: return "ENOEXEC"; +#endif +#ifdef ENOLCK + case ENOLCK: return "ENOLCK"; +#endif +#ifdef ENOLINK + case ENOLINK: return "ENOLINK"; +#endif + case ENOMEM: return "ENOMEM"; +#ifdef ENOMSG + case ENOMSG: return "ENOMSG"; +#endif +#ifdef ENOPROTOOPT + case ENOPROTOOPT: return "ENOPROTOOPT"; +#endif +#ifdef ENOSPC + case ENOSPC: return "ENOSPC"; +#endif +#ifdef ENOSR + case ENOSR: return "ENOSR"; +#endif +#ifdef ENOSTR + case ENOSTR: return "ENOSTR"; +#endif +#ifdef ENOSYS + case ENOSYS: return "ENOSYS"; +#endif +#ifdef ENOTCONN + case ENOTCONN: return "ENOTCONN"; +#endif +#ifdef ENOTDIR + case ENOTDIR: return "ENOTDIR"; +#endif +// AIX: ENOTEMPTY == EEXIST +#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) + case ENOTEMPTY: return "ENOTEMPTY"; +#endif +#ifdef ENOTSOCK + case ENOTSOCK: return "ENOTSOCK"; +#endif +#ifdef ENOTSUP + case ENOTSUP: return "ENOTSUP"; +#endif +#ifdef ENOTTY + case ENOTTY: return "ENOTTY"; +#endif +#ifdef ENXIO + case ENXIO: return "ENXIO"; +#endif +// on some unices EOPNOTSUPP==ENOTSUPP +#if defined(ENOTSUP) && defined(EOPNOTSUPP) && (EOPNOTSUPP != ENOTSUP) + case EOPNOTSUPP: return "EOPNOTSUPP"; +#endif +#ifdef EOVERFLOW + case EOVERFLOW: return "EOVERFLOW"; +#endif +#ifdef EPERM + case EPERM: return "EPERM"; +#endif +#ifdef EPIPE + case EPIPE: return "EPIPE"; +#endif +#ifdef EPROTO + case EPROTO: return "EPROTO"; +#endif +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: return "EPROTONOSUPPORT"; +#endif +#ifdef EPROTOTYPE + case EPROTOTYPE: return "EPROTOTYPE"; +#endif + case ERANGE: return "ERANGE"; +#ifdef EROFS + case EROFS: return "EROFS"; +#endif +#ifdef ESPIPE + case ESPIPE: return "ESPIPE"; +#endif +#ifdef ESRCH + case ESRCH: return "ESRCH"; +#endif +#ifdef ESTALE + case ESTALE: return "ESTALE"; +#endif +#ifdef ETIME + case ETIME: return "ETIME"; +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: return "ETIMEDOUT"; +#endif +#ifdef ETXTBSY + case ETXTBSY: return "ETXTBSY"; +#endif +// on some unices EWOULDBLOCK==EAGAIN +#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: return "EWOULDBLOCK"; +#endif +#ifdef EXDEV + case EXDEV: return "EXDEV"; +#endif + default: return "unknown"; + } +} +void MiscUtils::sleep_ms(int milliseconds) { + // from usleep() manpage: + // "The useconds argument must be less than 1,000,000 " + // fallback to sleep for that. + if (milliseconds >= 1000) { + const int seconds = (milliseconds / 1000) + 1; + ::sleep(seconds); + } + + ::usleep(milliseconds * 1000); +} + + diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/misc_aix.hpp --- a/src/os/aix/vm/misc_aix.hpp Sat Nov 14 18:26:35 2015 +0000 +++ 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 @@ -95,6 +97,11 @@ // always return true. Use CanUseSafeFetch32 to handle this case. bool is_readable_pointer(const void* p); + const char* describe_errno(int err_no); + + void sleep_ms(int milliseconds); + + } #endif // OS_AIX_VM_MISC_AIX_HPP diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/os_aix.cpp --- a/src/os/aix/vm/os_aix.cpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/os_aix.cpp Mon Nov 16 10:58:14 2015 +0100 @@ -121,14 +121,14 @@ // Add missing declarations (should be in procinfo.h but isn't until AIX 6.1). #if !defined(_AIXVERSION_610) extern "C" { - int getthrds64(pid_t ProcessIdentifier, - struct thrdentry64* ThreadBuffer, - int ThreadSize, - tid64_t* IndexPointer, - int Count); + int getprocs64(procentry64 * , int , fdsinfo * , int , pid_t * , int); } #endif +// missing from prototypes in sys/time.h +extern "C" +int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t); + #define MAX_PATH (2 * K) // for timer info max values which include all bits @@ -185,7 +185,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; @@ -207,13 +207,25 @@ // 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; //////////////////////////////////////////////////////////////////////////////// @@ -228,6 +240,9 @@ 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 +293,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 +306,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; } } @@ -357,25 +377,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() { @@ -453,14 +478,12 @@ g_multipage_support.pthr_stack_pagesize = os::Aix::query_pagesize(&dummy); } - // Query default text page size (LDR_CNTRL TEXTPSIZE). - /* PPC port: so far unused. + // Query pthread stack page size. This should be the same as data page size + // because pthread library allocated from c heap { - address any_function = - (address) resolve_function_descriptor_to_code_pointer((address)describe_pagesize); - g_multipage_support.textpsize = os::Aix::query_pagesize(any_function); - } - */ + int dummy = 0; + g_multipage_support.pthr_stack_pagesize = os::Aix::query_pagesize(&dummy); + } // Now probe for support of 64K pages and 16M pages. @@ -474,7 +497,7 @@ { 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"); @@ -505,8 +528,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 %s", + MiscUtils::describe_errno(en)); } else { // Attach and double check pageisze. void* p = ::shmat(shmid, NULL, 0); @@ -552,7 +575,7 @@ // 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); @@ -560,7 +583,7 @@ 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 +601,10 @@ // Found the full path to libjvm.so. // Now cut the path to /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}. @@ -754,7 +780,23 @@ 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 { @@ -802,6 +844,12 @@ // Returns false if something went wrong; // the content of pci is undefined in this case. bool os::Aix::get_cpuinfo(cpuinfo_t* pci) { + + // There is no perfstat lib on Pase. + if (os::Aix::on_pase()) { + return false; + } + assert(pci, "get_cpuinfo: invalid parameter"); memset(pci, 0, sizeof(cpuinfo_t)); @@ -823,6 +871,11 @@ 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: @@ -867,13 +920,6 @@ } //end os::Aix::get_cpuinfo ////////////////////////////////////////////////////////////////////////////// -// detecting pthread library - -void os::Aix::libpthread_init() { - return; -} - -////////////////////////////////////////////////////////////////////////////// // create new thread // Thread start routine for all newly created threads @@ -889,6 +935,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)) { + fprintf(stderr, "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()); @@ -907,7 +973,7 @@ OSThread* osthread = thread->osthread(); // thread_id is kernel thread id (similar to Solaris LWP id) - osthread->set_thread_id(os::Aix::gettid()); + osthread->set_thread_id(pthread_id); // initialize signal mask for this thread os::Aix::hotspot_sigmask(thread); @@ -920,14 +986,14 @@ // 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,7 +1058,7 @@ 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 (PrintMiscellaneous && (Verbose || WizardMode)) { perror("pthread_create()"); @@ -1030,9 +1096,18 @@ 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); // initialize floating point control register os::Aix::init_thread_fpu_state(); @@ -1152,17 +1227,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. @@ -1291,22 +1364,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 @@ -1343,6 +1406,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) { @@ -1586,49 +1652,68 @@ 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())); + 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 : ""); + // print out EXTSHM because it is an unsupported setting const char* const extshm = ::getenv("EXTSHM"); st->print_cr(" EXTSHM=%s.", extshm ? extshm : ""); 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 : ""); + 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 @@ -1642,11 +1727,16 @@ } } -void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) { +void os::pd_print_cpu_info(outputStream* st) { + 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(); } @@ -1785,21 +1875,76 @@ // 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 (UsePosixSemaphores) { + int rc = ::sem_init(&sig_sem, 0, 0); + guarantee(rc != -1, "sem_init failed"); + } else { + // memory semaphores must live in shared memory + 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 (UsePosixSemaphores) { + int rc = ::sem_post(&sig_sem); + if (rc == -1 && !warn_only_once) { + traceOsMiscWarning(("sem_post failed (errno = %d, %s)", errno, strerror(errno))); + warn_only_once = true; + } + } else { + guarantee0(p_sig_msem != NULL); // must init before use + int rc = ::msem_unlock(p_sig_msem, 0); + if (rc == -1 && !warn_only_once) { + traceOsMiscWarning(("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 (UsePosixSemaphores) { + int rc = ::sem_wait(&sig_sem); + if (rc == -1 && !warn_only_once) { + traceOsMiscWarning(("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) { + traceOsMiscWarning(("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); + int rc = local_sem_init(&sig_sem, 0, 0); guarantee(rc != -1, "sem_init failed"); } void os::signal_notify(int sig) { Atomic::inc(&pending_signals[sig]); - ::sem_post(&sig_sem); + local_sem_post(&sig_sem); } static int check_pending_signals(bool wait) { @@ -1822,7 +1967,7 @@ thread->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() - ::sem_wait(&sig_sem); + local_sem_wait(&sig_sem); // were we externally suspended while we were waiting? threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); @@ -1833,7 +1978,7 @@ // while suspended because that would surprise the thread that // suspended us. // - ::sem_post(&sig_sem); + local_sem_post(&sig_sem); thread->java_suspend_self(); } @@ -1886,12 +2031,12 @@ 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); + 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); + " aligned to pagesize (%lu)\n", p, p + s, (unsigned long) pagesize); guarantee0(false); } } @@ -1947,6 +2092,8 @@ } } +//////////////////////////////// SAPJVM stuefe 2014-05-06: System V shm routines /////////// + // Reserve and attach a section of System V memory. // If is not NULL, function will attempt to attach the memory at the given // address. Failing that, it will attach the memory anywhere. @@ -2082,6 +2229,8 @@ return true; } +//////////////////////////////// mmap-based routines ///////////////////////////////// + // Reserve memory via mmap. // If is given, an attempt is made to attach at the given address. // Failing that, memory is allocated at any address. @@ -2267,10 +2416,15 @@ assert0(is_aligned_to(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; } @@ -2292,7 +2446,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) { @@ -2390,7 +2544,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()); @@ -2466,9 +2620,32 @@ } 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. :-/ + + MiscUtils::sleep_ms(1); + 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) { + + if (rc) { + Events::log("mprotect(" PTR_FORMAT "-" PTR_FORMAT ", 0x%X) - ok.", addr, addr + size, prot); + } else { assert(false, "mprotect failed."); } return rc; @@ -2507,10 +2684,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) { @@ -3078,7 +3256,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)) { @@ -3102,7 +3279,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; } @@ -3310,7 +3486,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; @@ -3378,10 +3553,15 @@ // This is called _before_ the most of global arguments have been parsed. void os::init(void) { + // This is basic, we want to know if that ever changes. // (Shared memory boundary is supposed to be a 256M aligned.) assert(SHMLBA == ((uint64_t)0x10000000ULL)/*256M*/, "unexpected"); + // 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(); @@ -3389,6 +3569,16 @@ // Scan environment (SPEC1170 behaviour, etc). os::Aix::scan_environment(); + // SAPJVM stuefe 2010-09-27: + // At runtime, switch implementation of semaphores depending on the OS. + if (FLAG_IS_DEFAULT(UsePosixSemaphores)) { + if (os::Aix::on_aix()) { + FLAG_SET_ERGO(bool, UsePosixSemaphores, true); + } else { + FLAG_SET_ERGO(bool, UsePosixSemaphores, false); + } + } + // Check which pages are supported by AIX. query_multipage_support(); @@ -3458,6 +3648,7 @@ // For now UseLargePages is just ignored. FLAG_SET_ERGO(bool, UseLargePages, false); _page_sizes[0] = 0; + _large_page_size = -1; // debug trace trcVerbose("os::vm_page_size %s\n", describe_pagesize(os::vm_page_size())); @@ -3504,11 +3695,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; @@ -3617,8 +3818,6 @@ // Note that this can be 0, if no default stacksize was set. JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size())); - Aix::libpthread_init(); - if (MaxFDLimit) { // Set the number of file descriptors to max. print out error // if getrlimit/setrlimit fails but continue regardless. @@ -4191,7 +4390,14 @@ 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; @@ -4225,12 +4431,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 : ""); - } + trcVerbose("EXTSHM=%s.", p ? p : ""); 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, because leaving EXTSHM=ON leads to, on + // ceratin AIX systems, the VM not being 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; } @@ -4265,26 +4476,27 @@ } // 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 diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/os_aix.hpp --- a/src/os/aix/vm/os_aix.hpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/os_aix.hpp Mon Nov 16 10:58:14 2015 +0100 @@ -39,6 +39,8 @@ #define MAXSIGNUM 63 // Length of strings included in the libperfstat structures. #define IDENTIFIER_LENGTH 64 + // Length of the wpar name included in the libperfstat structures. +#define MAXCORRALNAMELEN 25 static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions static unsigned int sigs; // mask of signals that have @@ -54,7 +56,7 @@ // For signal flags diagnostics static int sigflags[MAXSIGNUM]; - protected: + private: static julong _physical_memory; static pthread_t _main_thread; @@ -62,6 +64,9 @@ 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; @@ -72,6 +77,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) @@ -82,35 +90,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(); @@ -134,9 +113,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); @@ -224,6 +200,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; @@ -246,6 +230,13 @@ return _extshm; } + // Process break recorded at VM startup. + static address get_brk_at_startup(); + + // Address closest to process break allocated with os::reserve_memory + // and friends (to see whether we are encrouching upon the process break). + static address get_lowest_allocation_above_brk(); + // result struct for get_meminfo() struct meminfo_t { @@ -266,6 +257,50 @@ }; + // 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 */ + + // SAPJVM MBS 2012-11-29 : additional values used in cpu util. calculation + 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 */ + + // SAPJVM ASt 2015-01-19: additional AME information + 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) @@ -276,17 +311,63 @@ char version[20]; // processor version from _system_configuration (sys/systemcfg.h) }; + // 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 */ + }; + // 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 partition information on AIX + // (on AIX, using libperfstat) + // Returns true if ok, false if error. + static bool get_partitioninfo(partitioninfo_t* ppi); + // 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 + // Function to retrieve wpar information on AIX + // (on AIX, using libperfstat) + // Returns true if ok, false if error. + static bool get_wparinfo(wparinfo_t* pwi); + + // -1 = uninitialized, otherwise return number of logical cpus on AIX + static int logical_cpus () { + assert(_logical_cpus != -1, "not initialized"); + return _logical_cpus; + } + + // PASE: Function to parse a QSYS.LIB path and to extract library name, object name, object type + // e.g. : /QSYS.LIB/TOMLIB.LIB/A.PGM -> TOMLIB, A, *PGM + // Also handles IASP specs (by quietly swallowing them) + // Notes: + // returned names are always uppercase. Case of input path does not matter. + #define MAX_AS400_OBJNAME_LEN 10 + #define MAX_AS400_IASP_NAME_LEN MAX_AS400_OBJNAME_LEN + #define MAX_AS400_LIB_NAME_LEN MAX_AS400_OBJNAME_LEN + #define MAX_AS400_OBJTYPE_LEN 10 + static bool parse_qsyslib_path( + const char* path, + char lib [MAX_AS400_LIB_NAME_LEN + 1], + char obj [MAX_AS400_OBJNAME_LEN + 1], + char type [MAX_AS400_OBJTYPE_LEN + 1], + int* hint = NULL + ); + +}; class PlatformEvent : public CHeapObj { diff -r 756e5b1c59fa -r 19bc0fd9c4d2 src/os/aix/vm/os_aix.inline.hpp --- a/src/os/aix/vm/os_aix.inline.hpp Sat Nov 14 18:26:35 2015 +0000 +++ b/src/os/aix/vm/os_aix.inline.hpp Mon Nov 16 10:58:14 2015 +0100 @@ -64,6 +64,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. @@ -156,14 +158,14 @@ return ::close(fd); } +inline int os::socket(int domain, int type, int protocol) { + return ::socket(domain, type, protocol); +} + inline int os::socket_close(int fd) { return ::close(fd); } -inline int os::socket(int domain, int type, int protocol) { - return ::socket(domain, type, protocol); -} - inline int os::recv(int fd, char* buf, size_t nBytes, uint flags) { RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, flags)); }