8025985: com.sun.management.OSMBeanFactory should not be public
Reviewed-by: alanb, erikj, ihse, jbachorik
--- a/jdk/makefiles/lib/ServiceabilityLibraries.gmk Fri Nov 08 18:54:29 2013 +0000
+++ b/jdk/makefiles/lib/ServiceabilityLibraries.gmk Fri Nov 08 12:13:02 2013 -0800
@@ -275,19 +275,12 @@
##########################################################################################
BUILD_LIBMANAGEMENT_SRC := $(JDK_TOPDIR)/src/share/native/sun/management \
- $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/management \
- $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/com/sun/management
+ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/management
BUILD_LIBMANAGEMENT_EXCLUDES :=
BUILD_LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/sun/management
-ifneq ($(OPENJDK_TARGET_OS), windows)
- BUILD_LIBMANAGEMENT_EXCLUDES += OperatingSystem_md.c
-else
- BUILD_LIBMANAGEMENT_EXCLUDES += UnixOperatingSystem_md.c
-endif
-
ifneq ($(OPENJDK_TARGET_OS), solaris)
BUILD_LIBMANAGEMENT_EXCLUDES += SolarisOperatingSystem.c
endif
--- a/jdk/makefiles/mapfiles/libmanagement/mapfile-vers Fri Nov 08 18:54:29 2013 +0000
+++ b/jdk/makefiles/mapfiles/libmanagement/mapfile-vers Fri Nov 08 12:13:02 2013 -0800
@@ -27,17 +27,17 @@
SUNWprivate_1.1 {
global:
- Java_com_sun_management_UnixOperatingSystem_getCommittedVirtualMemorySize;
- Java_com_sun_management_UnixOperatingSystem_getFreePhysicalMemorySize;
- Java_com_sun_management_UnixOperatingSystem_getFreeSwapSpaceSize;
- Java_com_sun_management_UnixOperatingSystem_getMaxFileDescriptorCount;
- Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount;
- Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad;
- Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime;
- Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad;
- Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize;
- Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
- Java_com_sun_management_UnixOperatingSystem_initialize;
+ Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize;
+ Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize;
+ Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize;
+ Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount;
+ Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount;
+ Java_sun_management_OperatingSystemImpl_getProcessCpuLoad;
+ Java_sun_management_OperatingSystemImpl_getProcessCpuTime;
+ Java_sun_management_OperatingSystemImpl_getSystemCpuLoad;
+ Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize;
+ Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize;
+ Java_sun_management_OperatingSystemImpl_initialize;
Java_sun_management_ClassLoadingImpl_setVerboseClass;
Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand;
Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/BaseOperatingSystemImpl.java Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management;
+
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.ManagementFactory;
+import javax.management.ObjectName;
+import sun.misc.Unsafe;
+
+/**
+ * Implementation class for the operating system.
+ * Standard and committed hotspot-specific metrics if any.
+ *
+ * ManagementFactory.getOperatingSystemMXBean() returns an instance
+ * of this class.
+ */
+public class BaseOperatingSystemImpl implements OperatingSystemMXBean {
+
+ private final VMManagement jvm;
+
+ /**
+ * Constructor of BaseOperatingSystemImpl class.
+ */
+ protected BaseOperatingSystemImpl(VMManagement vm) {
+ this.jvm = vm;
+ }
+
+ public String getName() {
+ return jvm.getOsName();
+ }
+
+ public String getArch() {
+ return jvm.getOsArch();
+ }
+
+ public String getVersion() {
+ return jvm.getOsVersion();
+ }
+
+ public int getAvailableProcessors() {
+ return jvm.getAvailableProcessors();
+ }
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private double[] loadavg = new double[1];
+ public double getSystemLoadAverage() {
+ if (unsafe.getLoadAverage(loadavg, 1) == 1) {
+ return loadavg[0];
+ } else {
+ return -1.0;
+ }
+ }
+ public ObjectName getObjectName() {
+ return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
+ }
+
+}
--- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Fri Nov 08 18:54:29 2013 +0000
+++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Fri Nov 08 12:13:02 2013 -0800
@@ -46,7 +46,6 @@
import java.util.HashMap;
import java.util.List;
import com.sun.management.DiagnosticCommandMBean;
-import com.sun.management.OSMBeanFactory;
import com.sun.management.HotSpotDiagnosticMXBean;
import static java.lang.management.ManagementFactory.*;
@@ -104,8 +103,7 @@
public static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {
if (osMBean == null) {
- osMBean = (OperatingSystemImpl)
- OSMBeanFactory.getOperatingSystemMXBean(jvm);
+ osMBean = new OperatingSystemImpl(jvm);
}
return osMBean;
}
--- a/jdk/src/share/classes/sun/management/OperatingSystemImpl.java Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.lang.management.OperatingSystemMXBean;
-import java.lang.management.ManagementFactory;
-import javax.management.ObjectName;
-import sun.misc.Unsafe;
-
-/**
- * Implementation class for the operating system.
- * Standard and committed hotspot-specific metrics if any.
- *
- * ManagementFactory.getOperatingSystemMXBean() returns an instance
- * of this class.
- */
-public class OperatingSystemImpl implements OperatingSystemMXBean {
-
- private final VMManagement jvm;
-
- /**
- * Constructor of OperatingSystemImpl class.
- */
- protected OperatingSystemImpl(VMManagement vm) {
- this.jvm = vm;
- }
-
- public String getName() {
- return jvm.getOsName();
- }
-
- public String getArch() {
- return jvm.getOsArch();
- }
-
- public String getVersion() {
- return jvm.getOsVersion();
- }
-
- public int getAvailableProcessors() {
- return jvm.getAvailableProcessors();
- }
-
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private double[] loadavg = new double[1];
- public double getSystemLoadAverage() {
- if (unsafe.getLoadAverage(loadavg, 1) == 1) {
- return loadavg[0];
- } else {
- return -1.0;
- }
- }
- public ObjectName getObjectName() {
- return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
- }
-
-}
--- a/jdk/src/solaris/classes/com/sun/management/OSMBeanFactory.java Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.management;
-
-import java.lang.management.OperatingSystemMXBean;
-import sun.management.VMManagement;
-
-/**
- * Operating system dependent MBean factory.
- * <p>
- * <b>WARNING:</b> While this class is public, it should not be treated as
- * public API and its API may change in incompatable ways between dot dot
- * releases and even patch releases. You should not rely on this class.
- */
-@jdk.Exported(false)
-public class OSMBeanFactory {
- /* static factory class */
- private OSMBeanFactory() {};
-
- private static UnixOperatingSystem osMBean = null;
-
- public static synchronized OperatingSystemMXBean
- getOperatingSystemMXBean(VMManagement jvm) {
-
- if (osMBean == null) {
- osMBean = new UnixOperatingSystem(jvm);
- }
- return (OperatingSystemMXBean) osMBean;
- }
-}
--- a/jdk/src/solaris/classes/com/sun/management/UnixOperatingSystem.java Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.management;
-
-import sun.management.VMManagement;
-
-/**
- * Implementation class for the operating system.
- * Standard and committed hotspot-specific metrics if any.
- *
- * ManagementFactory.getOperatingSystemMXBean() returns an instance
- * of this class.
- */
-class UnixOperatingSystem
- extends sun.management.OperatingSystemImpl
- implements UnixOperatingSystemMXBean {
-
- UnixOperatingSystem(VMManagement vm) {
- super(vm);
- }
-
- public native long getCommittedVirtualMemorySize();
- public native long getTotalSwapSpaceSize();
- public native long getFreeSwapSpaceSize();
- public native long getProcessCpuTime();
- public native long getFreePhysicalMemorySize();
- public native long getTotalPhysicalMemorySize();
- public native long getOpenFileDescriptorCount();
- public native long getMaxFileDescriptorCount();
- public native double getSystemCpuLoad();
- public native double getProcessCpuLoad();
-
- static {
- initialize();
- }
- private static native void initialize();
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/management/OperatingSystemImpl.java Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management;
+
+/**
+ * Implementation class for the operating system.
+ * Standard and committed hotspot-specific metrics if any.
+ *
+ * ManagementFactory.getOperatingSystemMXBean() returns an instance
+ * of this class.
+ */
+class OperatingSystemImpl extends BaseOperatingSystemImpl
+ implements com.sun.management.UnixOperatingSystemMXBean {
+
+ OperatingSystemImpl(VMManagement vm) {
+ super(vm);
+ }
+
+ public native long getCommittedVirtualMemorySize();
+ public native long getTotalSwapSpaceSize();
+ public native long getFreeSwapSpaceSize();
+ public native long getProcessCpuTime();
+ public native long getFreePhysicalMemorySize();
+ public native long getTotalPhysicalMemorySize();
+ public native long getOpenFileDescriptorCount();
+ public native long getMaxFileDescriptorCount();
+ public native double getSystemCpuLoad();
+ public native double getProcessCpuLoad();
+
+ static {
+ initialize();
+ }
+ private static native void initialize();
+}
--- a/jdk/src/solaris/native/com/sun/management/LinuxOperatingSystem.c Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <pthread.h>
-#include "com_sun_management_UnixOperatingSystem.h"
-
-struct ticks {
- uint64_t used;
- uint64_t usedKernel;
- uint64_t total;
-};
-
-typedef struct ticks ticks;
-
-typedef enum {
- CPU_LOAD_VM_ONLY,
- CPU_LOAD_GLOBAL,
-} CpuLoadTarget;
-
-static struct perfbuf {
- int nProcs;
- ticks jvmTicks;
- ticks cpuTicks;
- ticks *cpus;
-} counters;
-
-#define DEC_64 "%lld"
-
-static void next_line(FILE *f) {
- while (fgetc(f) != '\n');
-}
-
-/**
- * Return the total number of ticks since the system was booted.
- * If the usedTicks parameter is not NULL, it will be filled with
- * the number of ticks spent on actual processes (user, system or
- * nice processes) since system boot. Note that this is the total number
- * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
- * n times the number of ticks that has passed in clock time.
- *
- * Returns a negative value if the reading of the ticks failed.
- */
-static int get_totalticks(int which, ticks *pticks) {
- FILE *fh;
- uint64_t userTicks, niceTicks, systemTicks, idleTicks;
- int n;
-
- if((fh = fopen("/proc/stat", "r")) == NULL) {
- return -1;
- }
-
- n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64,
- &userTicks, &niceTicks, &systemTicks, &idleTicks);
-
- // Move to next line
- next_line(fh);
-
- //find the line for requested cpu faster to just iterate linefeeds?
- if (which != -1) {
- int i;
- for (i = 0; i < which; i++) {
- if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) {
- fclose(fh);
- return -2;
- }
- next_line(fh);
- }
- n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n",
- &userTicks, &niceTicks, &systemTicks, &idleTicks);
- }
-
- fclose(fh);
- if (n != 4) {
- return -2;
- }
-
- pticks->used = userTicks + niceTicks;
- pticks->usedKernel = systemTicks;
- pticks->total = userTicks + niceTicks + systemTicks + idleTicks;
-
- return 0;
-}
-
-static int vread_statdata(const char *procfile, const char *fmt, va_list args) {
- FILE *f;
- int n;
- char buf[2048];
-
- if ((f = fopen(procfile, "r")) == NULL) {
- return -1;
- }
-
- if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
- char *tmp;
-
- buf[n-1] = '\0';
- /** skip through pid and exec name. the exec name _could be wacky_ (renamed) and
- * make scanf go mupp.
- */
- if ((tmp = strrchr(buf, ')')) != NULL) {
- // skip the ')' and the following space but check that the buffer is long enough
- tmp += 2;
- if (tmp < buf + n) {
- n = vsscanf(tmp, fmt, args);
- }
- }
- }
-
- fclose(f);
-
- return n;
-}
-
-static int read_statdata(const char *procfile, const char *fmt, ...) {
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = vread_statdata(procfile, fmt, args);
- va_end(args);
- return n;
-}
-
-/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
-static int read_ticks(const char *procfile, uint64_t *userTicks, uint64_t *systemTicks) {
- return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "DEC_64" "DEC_64,
- userTicks, systemTicks
- );
-}
-
-/**
- * Return the number of ticks spent in any of the processes belonging
- * to the JVM on any CPU.
- */
-static int get_jvmticks(ticks *pticks) {
- uint64_t userTicks;
- uint64_t systemTicks;
-
- if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) {
- return -1;
- }
-
- // get the total
- if (get_totalticks(-1, pticks) < 0) {
- return -1;
- }
-
- pticks->used = userTicks;
- pticks->usedKernel = systemTicks;
-
- return 0;
-}
-
-/**
- * This method must be called first, before any data can be gathererd.
- */
-int perfInit() {
- static int initialized=1;
-
- if (!initialized) {
- int i;
-
- int n = sysconf(_SC_NPROCESSORS_ONLN);
- if (n <= 0) {
- n = 1;
- }
-
- counters.cpus = calloc(n,sizeof(ticks));
- if (counters.cpus != NULL) {
- // For the CPU load
- get_totalticks(-1, &counters.cpuTicks);
-
- for (i = 0; i < n; i++) {
- get_totalticks(i, &counters.cpus[i]);
- }
- // For JVM load
- get_jvmticks(&counters.jvmTicks);
- initialized = 1;
- }
- }
-
- return initialized ? 0 : -1;
-}
-
-#define MAX(a,b) (a>b?a:b)
-#define MIN(a,b) (a<b?a:b)
-
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-/**
- * Return the load of the CPU as a double. 1.0 means the CPU process uses all
- * available time for user or system processes, 0.0 means the CPU uses all time
- * being idle.
- *
- * Returns a negative value if there is a problem in determining the CPU load.
- */
-
-static double get_cpuload_internal(int which, double *pkernelLoad, CpuLoadTarget target) {
- uint64_t udiff, kdiff, tdiff;
- ticks *pticks, tmp;
- double user_load = -1.0;
- int failed = 0;
-
- *pkernelLoad = 0.0;
-
- pthread_mutex_lock(&lock);
-
- if(perfInit() == 0) {
-
- if (target == CPU_LOAD_VM_ONLY) {
- pticks = &counters.jvmTicks;
- } else if (which == -1) {
- pticks = &counters.cpuTicks;
- } else {
- pticks = &counters.cpus[which];
- }
-
- tmp = *pticks;
-
- if (target == CPU_LOAD_VM_ONLY) {
- if (get_jvmticks(pticks) != 0) {
- failed = 1;
- }
- } else if (get_totalticks(which, pticks) < 0) {
- failed = 1;
- }
-
- if(!failed) {
- // seems like we sometimes end up with less kernel ticks when
- // reading /proc/self/stat a second time, timing issue between cpus?
- if (pticks->usedKernel < tmp.usedKernel) {
- kdiff = 0;
- } else {
- kdiff = pticks->usedKernel - tmp.usedKernel;
- }
- tdiff = pticks->total - tmp.total;
- udiff = pticks->used - tmp.used;
-
- if (tdiff == 0) {
- user_load = 0;
- } else {
- if (tdiff < (udiff + kdiff)) {
- tdiff = udiff + kdiff;
- }
- *pkernelLoad = (kdiff / (double)tdiff);
- // BUG9044876, normalize return values to sane values
- *pkernelLoad = MAX(*pkernelLoad, 0.0);
- *pkernelLoad = MIN(*pkernelLoad, 1.0);
-
- user_load = (udiff / (double)tdiff);
- user_load = MAX(user_load, 0.0);
- user_load = MIN(user_load, 1.0);
- }
- }
- }
- pthread_mutex_unlock(&lock);
- return user_load;
-}
-
-double get_cpu_load(int which) {
- double u, s;
- u = get_cpuload_internal(which, &s, CPU_LOAD_GLOBAL);
- if (u < 0) {
- return -1.0;
- }
- // Cap total systemload to 1.0
- return MIN((u + s), 1.0);
-}
-
-double get_process_load() {
- double u, s;
- u = get_cpuload_internal(-1, &s, CPU_LOAD_VM_ONLY);
- if (u < 0) {
- return -1.0;
- }
- return u + s;
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- if(perfInit() == 0) {
- return get_cpu_load(-1);
- } else {
- return -1.0;
- }
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- if(perfInit() == 0) {
- return get_process_load();
- } else {
- return -1.0;
- }
-}
--- a/jdk/src/solaris/native/com/sun/management/MacosxOperatingSystem.c Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "com_sun_management_UnixOperatingSystem.h"
-
-#include <sys/time.h>
-#include <mach/mach.h>
-#include <mach/task_info.h>
-
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- // This code is influenced by the darwin top source
-
- kern_return_t kr;
- mach_msg_type_number_t count;
- host_cpu_load_info_data_t load;
-
- static jlong last_used = 0;
- static jlong last_total = 0;
-
- count = HOST_CPU_LOAD_INFO_COUNT;
- kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&load, &count);
- if (kr != KERN_SUCCESS) {
- return -1;
- }
-
- jlong used = load.cpu_ticks[CPU_STATE_USER] + load.cpu_ticks[CPU_STATE_NICE] + load.cpu_ticks[CPU_STATE_SYSTEM];
- jlong total = used + load.cpu_ticks[CPU_STATE_IDLE];
-
- if (last_used == 0 || last_total == 0) {
- // First call, just set the last values
- last_used = used;
- last_total = total;
- // return 0 since we have no data, not -1 which indicates error
- return 0;
- }
-
- jlong used_delta = used - last_used;
- jlong total_delta = total - last_total;
-
- jdouble cpu = (jdouble) used_delta / total_delta;
-
- last_used = used;
- last_total = total;
-
- return cpu;
-}
-
-
-#define TIME_VALUE_TO_TIMEVAL(a, r) do { \
- (r)->tv_sec = (a)->seconds; \
- (r)->tv_usec = (a)->microseconds; \
-} while (0)
-
-
-#define TIME_VALUE_TO_MICROSECONDS(TV) \
- ((TV).tv_sec * 1000 * 1000 + (TV).tv_usec)
-
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- // This code is influenced by the darwin top source
-
- struct task_basic_info_64 task_info_data;
- struct task_thread_times_info thread_info_data;
- struct timeval user_timeval, system_timeval, task_timeval;
- struct timeval now;
- mach_port_t task = mach_task_self();
- kern_return_t kr;
-
- static jlong last_task_time = 0;
- static jlong last_time = 0;
-
- mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
- kr = task_info(task,
- TASK_THREAD_TIMES_INFO,
- (task_info_t)&thread_info_data,
- &thread_info_count);
- if (kr != KERN_SUCCESS) {
- // Most likely cause: |task| is a zombie.
- return -1;
- }
-
- mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
- kr = task_info(task,
- TASK_BASIC_INFO_64,
- (task_info_t)&task_info_data,
- &count);
- if (kr != KERN_SUCCESS) {
- // Most likely cause: |task| is a zombie.
- return -1;
- }
-
- /* Set total_time. */
- // thread info contains live time...
- TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval);
- TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval);
- timeradd(&user_timeval, &system_timeval, &task_timeval);
-
- // ... task info contains terminated time.
- TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval);
- TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval);
- timeradd(&user_timeval, &task_timeval, &task_timeval);
- timeradd(&system_timeval, &task_timeval, &task_timeval);
-
- if (gettimeofday(&now, NULL) < 0) {
- return -1;
- }
- jint ncpus = JVM_ActiveProcessorCount();
- jlong time = TIME_VALUE_TO_MICROSECONDS(now) * ncpus;
- jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval);
-
- if ((last_task_time == 0) || (last_time == 0)) {
- // First call, just set the last values.
- last_task_time = task_time;
- last_time = time;
- // return 0 since we have no data, not -1 which indicates error
- return 0;
- }
-
- jlong task_time_delta = task_time - last_task_time;
- jlong time_delta = time - last_time;
- if (time_delta == 0) {
- return -1;
- }
-
- jdouble cpu = (jdouble) task_time_delta / time_delta;
-
- last_task_time = task_time;
- last_time = time;
-
- return cpu;
- }
--- a/jdk/src/solaris/native/com/sun/management/SolarisOperatingSystem.c Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <fcntl.h>
-#include <kstat.h>
-#include <procfs.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/sysinfo.h>
-#include <sys/lwp.h>
-#include <pthread.h>
-#include <utmpx.h>
-#include <dlfcn.h>
-#include <sys/loadavg.h>
-#include <jni.h>
-#include "jvm.h"
-#include "com_sun_management_UnixOperatingSystem.h"
-
-typedef struct {
- kstat_t *kstat;
- uint64_t last_idle;
- uint64_t last_total;
- double last_ratio;
-} cpuload_t;
-
-static cpuload_t *cpu_loads = NULL;
-static unsigned int num_cpus;
-static kstat_ctl_t *kstat_ctrl = NULL;
-
-static void map_cpu_kstat_counters() {
- kstat_t *kstat;
- int i;
-
- // Get number of CPU(s)
- if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
- num_cpus = 1;
- }
-
- // Data structure for saving CPU load
- if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
- return;
- }
-
- // Get kstat cpu_stat counters for every CPU
- // (loop over kstat to find our cpu_stat(s)
- i = 0;
- for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
- if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
-
- if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
- // Failed to initialize kstat for this CPU so ignore it
- continue;
- }
-
- if (i == num_cpus) {
- // Found more cpu_stats than reported CPUs
- break;
- }
-
- cpu_loads[i++].kstat = kstat;
- }
- }
-}
-
-static int init_cpu_kstat_counters() {
- static int initialized = 0;
-
- // Concurrence in this method is prevented by the lock in
- // the calling method get_cpu_load();
- if(!initialized) {
- if ((kstat_ctrl = kstat_open()) != NULL) {
- map_cpu_kstat_counters();
- initialized = 1;
- }
- }
- return initialized ? 0 : -1;
-}
-
-static void update_cpu_kstat_counters() {
- if(kstat_chain_update(kstat_ctrl) != 0) {
- free(cpu_loads);
- map_cpu_kstat_counters();
- }
-}
-
-int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
- if (load->kstat == NULL) {
- // no handle.
- return -1;
- }
- if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
- // disabling for now, a kstat chain update is likely to happen next time
- load->kstat = NULL;
- return -1;
- }
- return 0;
-}
-
-double get_single_cpu_load(unsigned int n) {
- cpuload_t *load;
- cpu_stat_t cpu_stat;
- uint_t *usage;
- uint64_t c_idle;
- uint64_t c_total;
- uint64_t d_idle;
- uint64_t d_total;
- int i;
-
- if (n >= num_cpus) {
- return -1.0;
- }
-
- load = &cpu_loads[n];
- if (read_cpustat(load, &cpu_stat) < 0) {
- return -1.0;
- }
-
- usage = cpu_stat.cpu_sysinfo.cpu;
- c_idle = usage[CPU_IDLE];
-
- for (c_total = 0, i = 0; i < CPU_STATES; i++) {
- c_total += usage[i];
- }
-
- // Calculate diff against previous snapshot
- d_idle = c_idle - load->last_idle;
- d_total = c_total - load->last_total;
-
- /** update if weve moved */
- if (d_total > 0) {
- // Save current values for next time around
- load->last_idle = c_idle;
- load->last_total = c_total;
- load->last_ratio = (double) (d_total - d_idle) / d_total;
- }
-
- return load->last_ratio;
-}
-
-int get_info(const char *path, void *info, size_t s, off_t o) {
- int fd;
- int ret = 0;
- if ((fd = open(path, O_RDONLY)) < 0) {
- return -1;
- }
- if (pread(fd, info, s, o) != s) {
- ret = -1;
- }
- close(fd);
- return ret;
-}
-
-#define MIN(a, b) ((a < b) ? a : b)
-
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-/**
- * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
- */
-double get_cpu_load(int which) {
- double load =.0;
-
- pthread_mutex_lock(&lock);
- if(init_cpu_kstat_counters()==0) {
-
- update_cpu_kstat_counters();
-
- if (which == -1) {
- unsigned int i;
- double t;
-
- for (t = .0, i = 0; i < num_cpus; i++) {
- t += get_single_cpu_load(i);
- }
-
- // Cap total systemload to 1.0
- load = MIN((t / num_cpus), 1.0);
- } else {
- load = MIN(get_single_cpu_load(which), 1.0);
- }
- } else {
- load = -1.0;
- }
- pthread_mutex_unlock(&lock);
-
- return load;
-}
-
-/**
- * Return the cpu load (0-1) for the current process (i.e the JVM)
- * or -1.0 if the get_info() call failed
- */
-double get_process_load(void) {
- psinfo_t info;
-
- // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
- // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
- if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
- return (double) info.pr_pctcpu / 0x8000;
- }
- return -1.0;
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- return get_cpu_load(-1);
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- return get_process_load();
-}
-
--- a/jdk/src/solaris/native/com/sun/management/UnixOperatingSystem_md.c Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,451 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jlong.h"
-#include "jvm.h"
-#include "management.h"
-#include "com_sun_management_UnixOperatingSystem.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(_ALLBSD_SOURCE)
-#include <sys/sysctl.h>
-#ifdef __APPLE__
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <mach/mach.h>
-#include <sys/proc_info.h>
-#include <libproc.h>
-#endif
-#else
-#include <sys/swap.h>
-#endif
-#include <sys/resource.h>
-#include <sys/times.h>
-#ifndef _ALLBSD_SOURCE
-#include <sys/sysinfo.h>
-#endif
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-static jlong page_size = 0;
-
-#if defined(_ALLBSD_SOURCE)
-#define MB (1024UL * 1024UL)
-#else
-
-/* This gets us the new structured proc interfaces of 5.6 & later */
-/* - see comment in <sys/procfs.h> */
-#define _STRUCTURED_PROC 1
-#include <sys/procfs.h>
-
-#endif /* _ALLBSD_SOURCE */
-
-static struct dirent* read_dir(DIR* dirp, struct dirent* entry) {
-#ifdef __solaris__
- struct dirent* dbuf = readdir(dirp);
- return dbuf;
-#else /* __linux__ || _ALLBSD_SOURCE */
- struct dirent* p;
- if (readdir_r(dirp, entry, &p) == 0) {
- return p;
- } else {
- return NULL;
- }
-#endif
-}
-
-// true = get available swap in bytes
-// false = get total swap in bytes
-static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
-#ifdef __solaris__
- long total, avail;
- int nswap, i, count;
- swaptbl_t *stbl;
- char *strtab;
-
- // First get the number of swap resource entries
- if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
- throw_internal_error(env, "swapctl failed to get nswap");
- return -1;
- }
- if (nswap == 0) {
- return 0;
- }
-
- // Allocate storage for resource entries
- stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
- sizeof(struct swaptable));
- if (stbl == NULL) {
- JNU_ThrowOutOfMemoryError(env, 0);
- return -1;
- }
-
- // Allocate storage for the table
- strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
- if (strtab == NULL) {
- free(stbl);
- JNU_ThrowOutOfMemoryError(env, 0);
- return -1;
- }
-
- for (i = 0; i < (nswap + 1); i++) {
- stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
- }
- stbl->swt_n = nswap + 1;
-
- // Get the entries
- if ((count = swapctl(SC_LIST, stbl)) < 0) {
- free(stbl);
- free(strtab);
- throw_internal_error(env, "swapctl failed to get swap list");
- return -1;
- }
-
- // Sum the entries to get total and free swap
- total = 0;
- avail = 0;
- for (i = 0; i < count; i++) {
- total += stbl->swt_ent[i].ste_pages;
- avail += stbl->swt_ent[i].ste_free;
- }
-
- free(stbl);
- free(strtab);
- return available ? ((jlong)avail * page_size) :
- ((jlong)total * page_size);
-#elif defined(__linux__)
- int ret;
- FILE *fp;
- jlong total = 0, avail = 0;
-
- struct sysinfo si;
- ret = sysinfo(&si);
- if (ret != 0) {
- throw_internal_error(env, "sysinfo failed to get swap size");
- }
- total = (jlong)si.totalswap * si.mem_unit;
- avail = (jlong)si.freeswap * si.mem_unit;
-
- return available ? avail : total;
-#elif defined(__APPLE__)
- struct xsw_usage vmusage;
- size_t size = sizeof(vmusage);
- if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) {
- throw_internal_error(env, "sysctlbyname failed");
- }
- return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total;
-#else /* _ALLBSD_SOURCE */
- /*
- * XXXBSD: there's no way available to get swap info in
- * FreeBSD. Usage of libkvm is not an option here
- */
- // throw_internal_error(env, "Unimplemented in FreeBSD");
- return (0);
-#endif
-}
-
-JNIEXPORT void JNICALL
-Java_com_sun_management_UnixOperatingSystem_initialize
- (JNIEnv *env, jclass cls)
-{
- page_size = sysconf(_SC_PAGESIZE);
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getCommittedVirtualMemorySize
- (JNIEnv *env, jobject mbean)
-{
-#ifdef __solaris__
- psinfo_t psinfo;
- ssize_t result;
- size_t remaining;
- char* addr;
- int fd;
-
- fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
- if (fd < 0) {
- throw_internal_error(env, "Unable to open /proc/self/psinfo");
- return -1;
- }
-
- addr = (char *)&psinfo;
- for (remaining = sizeof(psinfo_t); remaining > 0;) {
- result = JVM_Read(fd, addr, remaining);
- if (result < 0) {
- JVM_Close(fd);
- throw_internal_error(env, "Unable to read /proc/self/psinfo");
- return -1;
- }
- remaining -= result;
- addr += result;
- }
-
- JVM_Close(fd);
- return (jlong) psinfo.pr_size * 1024;
-#elif defined(__linux__)
- FILE *fp;
- unsigned long vsize = 0;
-
- if ((fp = fopen("/proc/self/stat", "r")) == NULL) {
- throw_internal_error(env, "Unable to open /proc/self/stat");
- return -1;
- }
-
- // Ignore everything except the vsize entry
- if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) {
- throw_internal_error(env, "Unable to get virtual memory usage");
- fclose(fp);
- return -1;
- }
-
- fclose(fp);
- return (jlong)vsize;
-#elif defined(__APPLE__)
- struct task_basic_info t_info;
- mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
-
- kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
- if (res != KERN_SUCCESS) {
- throw_internal_error(env, "task_info failed");
- }
- return t_info.virtual_size;
-#else /* _ALLBSD_SOURCE */
- /*
- * XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
- */
- // throw_internal_error(env, "Unimplemented in FreeBSD");
- return (64 * MB);
-#endif
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize
- (JNIEnv *env, jobject mbean)
-{
- return get_total_or_available_swap_space_size(env, JNI_FALSE);
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getFreeSwapSpaceSize
- (JNIEnv *env, jobject mbean)
-{
- return get_total_or_available_swap_space_size(env, JNI_TRUE);
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime
- (JNIEnv *env, jobject mbean)
-{
-#ifdef __APPLE__
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) != 0) {
- throw_internal_error(env, "getrusage failed");
- return -1;
- }
- jlong microsecs =
- usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
- usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
- return microsecs * 1000;
-#else
- jlong clk_tck, ns_per_clock_tick;
- jlong cpu_time_ns;
- struct tms time;
-
- /*
- * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
- * add a magic to handle it
- */
-#if defined(__solaris__) || defined(_SC_CLK_TCK)
- clk_tck = (jlong) sysconf(_SC_CLK_TCK);
-#elif defined(__linux__) || defined(_ALLBSD_SOURCE)
- clk_tck = 100;
-#endif
- if (clk_tck == -1) {
- throw_internal_error(env,
- "sysconf failed - not able to get clock tick");
- return -1;
- }
-
- times(&time);
- ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck;
- cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) *
- ns_per_clock_tick;
- return cpu_time_ns;
-#endif
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getFreePhysicalMemorySize
- (JNIEnv *env, jobject mbean)
-{
-#ifdef __APPLE__
- mach_msg_type_number_t count;
- vm_statistics_data_t vm_stats;
- kern_return_t res;
-
- count = HOST_VM_INFO_COUNT;
- res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count);
- if (res != KERN_SUCCESS) {
- throw_internal_error(env, "host_statistics failed");
- return -1;
- }
- return (jlong)vm_stats.free_count * page_size;
-#elif defined(_ALLBSD_SOURCE)
- /*
- * XXBSDL no way to do it in FreeBSD
- */
- // throw_internal_error(env, "unimplemented in FreeBSD")
- return (128 * MB);
-#else // solaris / linux
- jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
- return (num_avail_physical_pages * page_size);
-#endif
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize
- (JNIEnv *env, jobject mbean)
-{
-#ifdef _ALLBSD_SOURCE
- jlong result = 0;
- int mib[2];
- size_t rlen;
-
- mib[0] = CTL_HW;
- mib[1] = HW_MEMSIZE;
- rlen = sizeof(result);
- if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) {
- throw_internal_error(env, "sysctl failed");
- return -1;
- }
- return result;
-#else // solaris / linux
- jlong num_physical_pages = sysconf(_SC_PHYS_PAGES);
- return (num_physical_pages * page_size);
-#endif
-}
-
-
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount
- (JNIEnv *env, jobject mbean)
-{
-#ifdef __APPLE__
- // This code is influenced by the darwin lsof source
- pid_t my_pid;
- struct proc_bsdinfo bsdinfo;
- struct proc_fdinfo *fds;
- int nfiles;
- kern_return_t kres;
- int res;
- size_t fds_size;
-
- kres = pid_for_task(mach_task_self(), &my_pid);
- if (kres != KERN_SUCCESS) {
- throw_internal_error(env, "pid_for_task failed");
- return -1;
- }
-
- // get the maximum number of file descriptors
- res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE);
- if (res <= 0) {
- throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed");
- return -1;
- }
-
- // allocate memory to hold the fd information (we don't acutally use this information
- // but need it to get the number of open files)
- fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo);
- fds = malloc(fds_size);
- if (fds == NULL) {
- JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors");
- return -1;
- }
-
- // get the list of open files - the return value is the number of bytes
- // proc_pidinfo filled in
- res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size);
- if (res <= 0) {
- free(fds);
- throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS");
- return -1;
- }
- nfiles = res / sizeof(struct proc_fdinfo);
- free(fds);
-
- return nfiles;
-#elif defined(_ALLBSD_SOURCE)
- /*
- * XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
- */
- // throw_internal_error(env, "Unimplemented in FreeBSD");
- return (100);
-#else /* solaris/linux */
- DIR *dirp;
- struct dirent dbuf;
- struct dirent* dentp;
- jlong fds = 0;
-
- dirp = opendir("/proc/self/fd");
- if (dirp == NULL) {
- throw_internal_error(env, "Unable to open directory /proc/self/fd");
- return -1;
- }
-
- // iterate through directory entries, skipping '.' and '..'
- // each entry represents an open file descriptor.
- while ((dentp = read_dir(dirp, &dbuf)) != NULL) {
- if (isdigit(dentp->d_name[0])) {
- fds++;
- }
- }
-
- closedir(dirp);
- // subtract by 1 which was the fd open for this implementation
- return (fds - 1);
-#endif
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_UnixOperatingSystem_getMaxFileDescriptorCount
- (JNIEnv *env, jobject mbean)
-{
- struct rlimit rlp;
-
- if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {
- throw_internal_error(env, "getrlimit failed");
- return -1;
- }
- return (jlong) rlp.rlim_cur;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/management/LinuxOperatingSystem.c Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include "sun_management_OperatingSystemImpl.h"
+
+struct ticks {
+ uint64_t used;
+ uint64_t usedKernel;
+ uint64_t total;
+};
+
+typedef struct ticks ticks;
+
+typedef enum {
+ CPU_LOAD_VM_ONLY,
+ CPU_LOAD_GLOBAL,
+} CpuLoadTarget;
+
+static struct perfbuf {
+ int nProcs;
+ ticks jvmTicks;
+ ticks cpuTicks;
+ ticks *cpus;
+} counters;
+
+#define DEC_64 "%lld"
+
+static void next_line(FILE *f) {
+ while (fgetc(f) != '\n');
+}
+
+/**
+ * Return the total number of ticks since the system was booted.
+ * If the usedTicks parameter is not NULL, it will be filled with
+ * the number of ticks spent on actual processes (user, system or
+ * nice processes) since system boot. Note that this is the total number
+ * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
+ * n times the number of ticks that has passed in clock time.
+ *
+ * Returns a negative value if the reading of the ticks failed.
+ */
+static int get_totalticks(int which, ticks *pticks) {
+ FILE *fh;
+ uint64_t userTicks, niceTicks, systemTicks, idleTicks;
+ int n;
+
+ if((fh = fopen("/proc/stat", "r")) == NULL) {
+ return -1;
+ }
+
+ n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64,
+ &userTicks, &niceTicks, &systemTicks, &idleTicks);
+
+ // Move to next line
+ next_line(fh);
+
+ //find the line for requested cpu faster to just iterate linefeeds?
+ if (which != -1) {
+ int i;
+ for (i = 0; i < which; i++) {
+ if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) {
+ fclose(fh);
+ return -2;
+ }
+ next_line(fh);
+ }
+ n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n",
+ &userTicks, &niceTicks, &systemTicks, &idleTicks);
+ }
+
+ fclose(fh);
+ if (n != 4) {
+ return -2;
+ }
+
+ pticks->used = userTicks + niceTicks;
+ pticks->usedKernel = systemTicks;
+ pticks->total = userTicks + niceTicks + systemTicks + idleTicks;
+
+ return 0;
+}
+
+static int vread_statdata(const char *procfile, const char *fmt, va_list args) {
+ FILE *f;
+ int n;
+ char buf[2048];
+
+ if ((f = fopen(procfile, "r")) == NULL) {
+ return -1;
+ }
+
+ if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
+ char *tmp;
+
+ buf[n-1] = '\0';
+ /** skip through pid and exec name. the exec name _could be wacky_ (renamed) and
+ * make scanf go mupp.
+ */
+ if ((tmp = strrchr(buf, ')')) != NULL) {
+ // skip the ')' and the following space but check that the buffer is long enough
+ tmp += 2;
+ if (tmp < buf + n) {
+ n = vsscanf(tmp, fmt, args);
+ }
+ }
+ }
+
+ fclose(f);
+
+ return n;
+}
+
+static int read_statdata(const char *procfile, const char *fmt, ...) {
+ int n;
+ va_list args;
+
+ va_start(args, fmt);
+ n = vread_statdata(procfile, fmt, args);
+ va_end(args);
+ return n;
+}
+
+/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
+static int read_ticks(const char *procfile, uint64_t *userTicks, uint64_t *systemTicks) {
+ return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "DEC_64" "DEC_64,
+ userTicks, systemTicks
+ );
+}
+
+/**
+ * Return the number of ticks spent in any of the processes belonging
+ * to the JVM on any CPU.
+ */
+static int get_jvmticks(ticks *pticks) {
+ uint64_t userTicks;
+ uint64_t systemTicks;
+
+ if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) {
+ return -1;
+ }
+
+ // get the total
+ if (get_totalticks(-1, pticks) < 0) {
+ return -1;
+ }
+
+ pticks->used = userTicks;
+ pticks->usedKernel = systemTicks;
+
+ return 0;
+}
+
+/**
+ * This method must be called first, before any data can be gathererd.
+ */
+int perfInit() {
+ static int initialized=1;
+
+ if (!initialized) {
+ int i;
+
+ int n = sysconf(_SC_NPROCESSORS_ONLN);
+ if (n <= 0) {
+ n = 1;
+ }
+
+ counters.cpus = calloc(n,sizeof(ticks));
+ if (counters.cpus != NULL) {
+ // For the CPU load
+ get_totalticks(-1, &counters.cpuTicks);
+
+ for (i = 0; i < n; i++) {
+ get_totalticks(i, &counters.cpus[i]);
+ }
+ // For JVM load
+ get_jvmticks(&counters.jvmTicks);
+ initialized = 1;
+ }
+ }
+
+ return initialized ? 0 : -1;
+}
+
+#define MAX(a,b) (a>b?a:b)
+#define MIN(a,b) (a<b?a:b)
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Return the load of the CPU as a double. 1.0 means the CPU process uses all
+ * available time for user or system processes, 0.0 means the CPU uses all time
+ * being idle.
+ *
+ * Returns a negative value if there is a problem in determining the CPU load.
+ */
+
+static double get_cpuload_internal(int which, double *pkernelLoad, CpuLoadTarget target) {
+ uint64_t udiff, kdiff, tdiff;
+ ticks *pticks, tmp;
+ double user_load = -1.0;
+ int failed = 0;
+
+ *pkernelLoad = 0.0;
+
+ pthread_mutex_lock(&lock);
+
+ if(perfInit() == 0) {
+
+ if (target == CPU_LOAD_VM_ONLY) {
+ pticks = &counters.jvmTicks;
+ } else if (which == -1) {
+ pticks = &counters.cpuTicks;
+ } else {
+ pticks = &counters.cpus[which];
+ }
+
+ tmp = *pticks;
+
+ if (target == CPU_LOAD_VM_ONLY) {
+ if (get_jvmticks(pticks) != 0) {
+ failed = 1;
+ }
+ } else if (get_totalticks(which, pticks) < 0) {
+ failed = 1;
+ }
+
+ if(!failed) {
+ // seems like we sometimes end up with less kernel ticks when
+ // reading /proc/self/stat a second time, timing issue between cpus?
+ if (pticks->usedKernel < tmp.usedKernel) {
+ kdiff = 0;
+ } else {
+ kdiff = pticks->usedKernel - tmp.usedKernel;
+ }
+ tdiff = pticks->total - tmp.total;
+ udiff = pticks->used - tmp.used;
+
+ if (tdiff == 0) {
+ user_load = 0;
+ } else {
+ if (tdiff < (udiff + kdiff)) {
+ tdiff = udiff + kdiff;
+ }
+ *pkernelLoad = (kdiff / (double)tdiff);
+ // BUG9044876, normalize return values to sane values
+ *pkernelLoad = MAX(*pkernelLoad, 0.0);
+ *pkernelLoad = MIN(*pkernelLoad, 1.0);
+
+ user_load = (udiff / (double)tdiff);
+ user_load = MAX(user_load, 0.0);
+ user_load = MIN(user_load, 1.0);
+ }
+ }
+ }
+ pthread_mutex_unlock(&lock);
+ return user_load;
+}
+
+double get_cpu_load(int which) {
+ double u, s;
+ u = get_cpuload_internal(which, &s, CPU_LOAD_GLOBAL);
+ if (u < 0) {
+ return -1.0;
+ }
+ // Cap total systemload to 1.0
+ return MIN((u + s), 1.0);
+}
+
+double get_process_load() {
+ double u, s;
+ u = get_cpuload_internal(-1, &s, CPU_LOAD_VM_ONLY);
+ if (u < 0) {
+ return -1.0;
+ }
+ return u + s;
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getSystemCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ if(perfInit() == 0) {
+ return get_cpu_load(-1);
+ } else {
+ return -1.0;
+ }
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ if(perfInit() == 0) {
+ return get_process_load();
+ } else {
+ return -1.0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/management/MacosxOperatingSystem.c Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "sun_management_OperatingSystemImpl.h"
+
+#include <sys/time.h>
+#include <mach/mach.h>
+#include <mach/task_info.h>
+
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getSystemCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ // This code is influenced by the darwin top source
+
+ kern_return_t kr;
+ mach_msg_type_number_t count;
+ host_cpu_load_info_data_t load;
+
+ static jlong last_used = 0;
+ static jlong last_total = 0;
+
+ count = HOST_CPU_LOAD_INFO_COUNT;
+ kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&load, &count);
+ if (kr != KERN_SUCCESS) {
+ return -1;
+ }
+
+ jlong used = load.cpu_ticks[CPU_STATE_USER] + load.cpu_ticks[CPU_STATE_NICE] + load.cpu_ticks[CPU_STATE_SYSTEM];
+ jlong total = used + load.cpu_ticks[CPU_STATE_IDLE];
+
+ if (last_used == 0 || last_total == 0) {
+ // First call, just set the last values
+ last_used = used;
+ last_total = total;
+ // return 0 since we have no data, not -1 which indicates error
+ return 0;
+ }
+
+ jlong used_delta = used - last_used;
+ jlong total_delta = total - last_total;
+
+ jdouble cpu = (jdouble) used_delta / total_delta;
+
+ last_used = used;
+ last_total = total;
+
+ return cpu;
+}
+
+
+#define TIME_VALUE_TO_TIMEVAL(a, r) do { \
+ (r)->tv_sec = (a)->seconds; \
+ (r)->tv_usec = (a)->microseconds; \
+} while (0)
+
+
+#define TIME_VALUE_TO_MICROSECONDS(TV) \
+ ((TV).tv_sec * 1000 * 1000 + (TV).tv_usec)
+
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ // This code is influenced by the darwin top source
+
+ struct task_basic_info_64 task_info_data;
+ struct task_thread_times_info thread_info_data;
+ struct timeval user_timeval, system_timeval, task_timeval;
+ struct timeval now;
+ mach_port_t task = mach_task_self();
+ kern_return_t kr;
+
+ static jlong last_task_time = 0;
+ static jlong last_time = 0;
+
+ mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
+ kr = task_info(task,
+ TASK_THREAD_TIMES_INFO,
+ (task_info_t)&thread_info_data,
+ &thread_info_count);
+ if (kr != KERN_SUCCESS) {
+ // Most likely cause: |task| is a zombie.
+ return -1;
+ }
+
+ mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
+ kr = task_info(task,
+ TASK_BASIC_INFO_64,
+ (task_info_t)&task_info_data,
+ &count);
+ if (kr != KERN_SUCCESS) {
+ // Most likely cause: |task| is a zombie.
+ return -1;
+ }
+
+ /* Set total_time. */
+ // thread info contains live time...
+ TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval);
+ TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval);
+ timeradd(&user_timeval, &system_timeval, &task_timeval);
+
+ // ... task info contains terminated time.
+ TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval);
+ TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval);
+ timeradd(&user_timeval, &task_timeval, &task_timeval);
+ timeradd(&system_timeval, &task_timeval, &task_timeval);
+
+ if (gettimeofday(&now, NULL) < 0) {
+ return -1;
+ }
+ jint ncpus = JVM_ActiveProcessorCount();
+ jlong time = TIME_VALUE_TO_MICROSECONDS(now) * ncpus;
+ jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval);
+
+ if ((last_task_time == 0) || (last_time == 0)) {
+ // First call, just set the last values.
+ last_task_time = task_time;
+ last_time = time;
+ // return 0 since we have no data, not -1 which indicates error
+ return 0;
+ }
+
+ jlong task_time_delta = task_time - last_task_time;
+ jlong time_delta = time - last_time;
+ if (time_delta == 0) {
+ return -1;
+ }
+
+ jdouble cpu = (jdouble) task_time_delta / time_delta;
+
+ last_task_time = task_time;
+ last_time = time;
+
+ return cpu;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+#include "management.h"
+#include "sun_management_OperatingSystemImpl.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(_ALLBSD_SOURCE)
+#include <sys/sysctl.h>
+#ifdef __APPLE__
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <mach/mach.h>
+#include <sys/proc_info.h>
+#include <libproc.h>
+#endif
+#else
+#include <sys/swap.h>
+#endif
+#include <sys/resource.h>
+#include <sys/times.h>
+#ifndef _ALLBSD_SOURCE
+#include <sys/sysinfo.h>
+#endif
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static jlong page_size = 0;
+
+#if defined(_ALLBSD_SOURCE)
+#define MB (1024UL * 1024UL)
+#else
+
+/* This gets us the new structured proc interfaces of 5.6 & later */
+/* - see comment in <sys/procfs.h> */
+#define _STRUCTURED_PROC 1
+#include <sys/procfs.h>
+
+#endif /* _ALLBSD_SOURCE */
+
+static struct dirent* read_dir(DIR* dirp, struct dirent* entry) {
+#ifdef __solaris__
+ struct dirent* dbuf = readdir(dirp);
+ return dbuf;
+#else /* __linux__ || _ALLBSD_SOURCE */
+ struct dirent* p;
+ if (readdir_r(dirp, entry, &p) == 0) {
+ return p;
+ } else {
+ return NULL;
+ }
+#endif
+}
+
+// true = get available swap in bytes
+// false = get total swap in bytes
+static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
+#ifdef __solaris__
+ long total, avail;
+ int nswap, i, count;
+ swaptbl_t *stbl;
+ char *strtab;
+
+ // First get the number of swap resource entries
+ if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
+ throw_internal_error(env, "swapctl failed to get nswap");
+ return -1;
+ }
+ if (nswap == 0) {
+ return 0;
+ }
+
+ // Allocate storage for resource entries
+ stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
+ sizeof(struct swaptable));
+ if (stbl == NULL) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return -1;
+ }
+
+ // Allocate storage for the table
+ strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
+ if (strtab == NULL) {
+ free(stbl);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return -1;
+ }
+
+ for (i = 0; i < (nswap + 1); i++) {
+ stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
+ }
+ stbl->swt_n = nswap + 1;
+
+ // Get the entries
+ if ((count = swapctl(SC_LIST, stbl)) < 0) {
+ free(stbl);
+ free(strtab);
+ throw_internal_error(env, "swapctl failed to get swap list");
+ return -1;
+ }
+
+ // Sum the entries to get total and free swap
+ total = 0;
+ avail = 0;
+ for (i = 0; i < count; i++) {
+ total += stbl->swt_ent[i].ste_pages;
+ avail += stbl->swt_ent[i].ste_free;
+ }
+
+ free(stbl);
+ free(strtab);
+ return available ? ((jlong)avail * page_size) :
+ ((jlong)total * page_size);
+#elif defined(__linux__)
+ int ret;
+ FILE *fp;
+ jlong total = 0, avail = 0;
+
+ struct sysinfo si;
+ ret = sysinfo(&si);
+ if (ret != 0) {
+ throw_internal_error(env, "sysinfo failed to get swap size");
+ }
+ total = (jlong)si.totalswap * si.mem_unit;
+ avail = (jlong)si.freeswap * si.mem_unit;
+
+ return available ? avail : total;
+#elif defined(__APPLE__)
+ struct xsw_usage vmusage;
+ size_t size = sizeof(vmusage);
+ if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) {
+ throw_internal_error(env, "sysctlbyname failed");
+ }
+ return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total;
+#else /* _ALLBSD_SOURCE */
+ /*
+ * XXXBSD: there's no way available to get swap info in
+ * FreeBSD. Usage of libkvm is not an option here
+ */
+ // throw_internal_error(env, "Unimplemented in FreeBSD");
+ return (0);
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_sun_management_OperatingSystemImpl_initialize
+ (JNIEnv *env, jclass cls)
+{
+ page_size = sysconf(_SC_PAGESIZE);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize
+ (JNIEnv *env, jobject mbean)
+{
+#ifdef __solaris__
+ psinfo_t psinfo;
+ ssize_t result;
+ size_t remaining;
+ char* addr;
+ int fd;
+
+ fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
+ if (fd < 0) {
+ throw_internal_error(env, "Unable to open /proc/self/psinfo");
+ return -1;
+ }
+
+ addr = (char *)&psinfo;
+ for (remaining = sizeof(psinfo_t); remaining > 0;) {
+ result = JVM_Read(fd, addr, remaining);
+ if (result < 0) {
+ JVM_Close(fd);
+ throw_internal_error(env, "Unable to read /proc/self/psinfo");
+ return -1;
+ }
+ remaining -= result;
+ addr += result;
+ }
+
+ JVM_Close(fd);
+ return (jlong) psinfo.pr_size * 1024;
+#elif defined(__linux__)
+ FILE *fp;
+ unsigned long vsize = 0;
+
+ if ((fp = fopen("/proc/self/stat", "r")) == NULL) {
+ throw_internal_error(env, "Unable to open /proc/self/stat");
+ return -1;
+ }
+
+ // Ignore everything except the vsize entry
+ if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) {
+ throw_internal_error(env, "Unable to get virtual memory usage");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+ return (jlong)vsize;
+#elif defined(__APPLE__)
+ struct task_basic_info t_info;
+ mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
+
+ kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
+ if (res != KERN_SUCCESS) {
+ throw_internal_error(env, "task_info failed");
+ }
+ return t_info.virtual_size;
+#else /* _ALLBSD_SOURCE */
+ /*
+ * XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
+ */
+ // throw_internal_error(env, "Unimplemented in FreeBSD");
+ return (64 * MB);
+#endif
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize
+ (JNIEnv *env, jobject mbean)
+{
+ return get_total_or_available_swap_space_size(env, JNI_FALSE);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize
+ (JNIEnv *env, jobject mbean)
+{
+ return get_total_or_available_swap_space_size(env, JNI_TRUE);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuTime
+ (JNIEnv *env, jobject mbean)
+{
+#ifdef __APPLE__
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage) != 0) {
+ throw_internal_error(env, "getrusage failed");
+ return -1;
+ }
+ jlong microsecs =
+ usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
+ usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
+ return microsecs * 1000;
+#else
+ jlong clk_tck, ns_per_clock_tick;
+ jlong cpu_time_ns;
+ struct tms time;
+
+ /*
+ * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
+ * add a magic to handle it
+ */
+#if defined(__solaris__) || defined(_SC_CLK_TCK)
+ clk_tck = (jlong) sysconf(_SC_CLK_TCK);
+#elif defined(__linux__) || defined(_ALLBSD_SOURCE)
+ clk_tck = 100;
+#endif
+ if (clk_tck == -1) {
+ throw_internal_error(env,
+ "sysconf failed - not able to get clock tick");
+ return -1;
+ }
+
+ times(&time);
+ ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck;
+ cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) *
+ ns_per_clock_tick;
+ return cpu_time_ns;
+#endif
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize
+ (JNIEnv *env, jobject mbean)
+{
+#ifdef __APPLE__
+ mach_msg_type_number_t count;
+ vm_statistics_data_t vm_stats;
+ kern_return_t res;
+
+ count = HOST_VM_INFO_COUNT;
+ res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count);
+ if (res != KERN_SUCCESS) {
+ throw_internal_error(env, "host_statistics failed");
+ return -1;
+ }
+ return (jlong)vm_stats.free_count * page_size;
+#elif defined(_ALLBSD_SOURCE)
+ /*
+ * XXBSDL no way to do it in FreeBSD
+ */
+ // throw_internal_error(env, "unimplemented in FreeBSD")
+ return (128 * MB);
+#else // solaris / linux
+ jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
+ return (num_avail_physical_pages * page_size);
+#endif
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize
+ (JNIEnv *env, jobject mbean)
+{
+#ifdef _ALLBSD_SOURCE
+ jlong result = 0;
+ int mib[2];
+ size_t rlen;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ rlen = sizeof(result);
+ if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) {
+ throw_internal_error(env, "sysctl failed");
+ return -1;
+ }
+ return result;
+#else // solaris / linux
+ jlong num_physical_pages = sysconf(_SC_PHYS_PAGES);
+ return (num_physical_pages * page_size);
+#endif
+}
+
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount
+ (JNIEnv *env, jobject mbean)
+{
+#ifdef __APPLE__
+ // This code is influenced by the darwin lsof source
+ pid_t my_pid;
+ struct proc_bsdinfo bsdinfo;
+ struct proc_fdinfo *fds;
+ int nfiles;
+ kern_return_t kres;
+ int res;
+ size_t fds_size;
+
+ kres = pid_for_task(mach_task_self(), &my_pid);
+ if (kres != KERN_SUCCESS) {
+ throw_internal_error(env, "pid_for_task failed");
+ return -1;
+ }
+
+ // get the maximum number of file descriptors
+ res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE);
+ if (res <= 0) {
+ throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed");
+ return -1;
+ }
+
+ // allocate memory to hold the fd information (we don't acutally use this information
+ // but need it to get the number of open files)
+ fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo);
+ fds = malloc(fds_size);
+ if (fds == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors");
+ return -1;
+ }
+
+ // get the list of open files - the return value is the number of bytes
+ // proc_pidinfo filled in
+ res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size);
+ if (res <= 0) {
+ free(fds);
+ throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS");
+ return -1;
+ }
+ nfiles = res / sizeof(struct proc_fdinfo);
+ free(fds);
+
+ return nfiles;
+#elif defined(_ALLBSD_SOURCE)
+ /*
+ * XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
+ */
+ // throw_internal_error(env, "Unimplemented in FreeBSD");
+ return (100);
+#else /* solaris/linux */
+ DIR *dirp;
+ struct dirent dbuf;
+ struct dirent* dentp;
+ jlong fds = 0;
+
+ dirp = opendir("/proc/self/fd");
+ if (dirp == NULL) {
+ throw_internal_error(env, "Unable to open directory /proc/self/fd");
+ return -1;
+ }
+
+ // iterate through directory entries, skipping '.' and '..'
+ // each entry represents an open file descriptor.
+ while ((dentp = read_dir(dirp, &dbuf)) != NULL) {
+ if (isdigit(dentp->d_name[0])) {
+ fds++;
+ }
+ }
+
+ closedir(dirp);
+ // subtract by 1 which was the fd open for this implementation
+ return (fds - 1);
+#endif
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount
+ (JNIEnv *env, jobject mbean)
+{
+ struct rlimit rlp;
+
+ if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {
+ throw_internal_error(env, "getrlimit failed");
+ return -1;
+ }
+ return (jlong) rlp.rlim_cur;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/management/SolarisOperatingSystem.c Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <fcntl.h>
+#include <kstat.h>
+#include <procfs.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/sysinfo.h>
+#include <sys/lwp.h>
+#include <pthread.h>
+#include <utmpx.h>
+#include <dlfcn.h>
+#include <sys/loadavg.h>
+#include <jni.h>
+#include "jvm.h"
+#include "sun_management_OperatingSystemImpl.h"
+
+typedef struct {
+ kstat_t *kstat;
+ uint64_t last_idle;
+ uint64_t last_total;
+ double last_ratio;
+} cpuload_t;
+
+static cpuload_t *cpu_loads = NULL;
+static unsigned int num_cpus;
+static kstat_ctl_t *kstat_ctrl = NULL;
+
+static void map_cpu_kstat_counters() {
+ kstat_t *kstat;
+ int i;
+
+ // Get number of CPU(s)
+ if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
+ num_cpus = 1;
+ }
+
+ // Data structure for saving CPU load
+ if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
+ return;
+ }
+
+ // Get kstat cpu_stat counters for every CPU
+ // (loop over kstat to find our cpu_stat(s)
+ i = 0;
+ for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
+ if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
+
+ if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
+ // Failed to initialize kstat for this CPU so ignore it
+ continue;
+ }
+
+ if (i == num_cpus) {
+ // Found more cpu_stats than reported CPUs
+ break;
+ }
+
+ cpu_loads[i++].kstat = kstat;
+ }
+ }
+}
+
+static int init_cpu_kstat_counters() {
+ static int initialized = 0;
+
+ // Concurrence in this method is prevented by the lock in
+ // the calling method get_cpu_load();
+ if(!initialized) {
+ if ((kstat_ctrl = kstat_open()) != NULL) {
+ map_cpu_kstat_counters();
+ initialized = 1;
+ }
+ }
+ return initialized ? 0 : -1;
+}
+
+static void update_cpu_kstat_counters() {
+ if(kstat_chain_update(kstat_ctrl) != 0) {
+ free(cpu_loads);
+ map_cpu_kstat_counters();
+ }
+}
+
+int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
+ if (load->kstat == NULL) {
+ // no handle.
+ return -1;
+ }
+ if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
+ // disabling for now, a kstat chain update is likely to happen next time
+ load->kstat = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+double get_single_cpu_load(unsigned int n) {
+ cpuload_t *load;
+ cpu_stat_t cpu_stat;
+ uint_t *usage;
+ uint64_t c_idle;
+ uint64_t c_total;
+ uint64_t d_idle;
+ uint64_t d_total;
+ int i;
+
+ if (n >= num_cpus) {
+ return -1.0;
+ }
+
+ load = &cpu_loads[n];
+ if (read_cpustat(load, &cpu_stat) < 0) {
+ return -1.0;
+ }
+
+ usage = cpu_stat.cpu_sysinfo.cpu;
+ c_idle = usage[CPU_IDLE];
+
+ for (c_total = 0, i = 0; i < CPU_STATES; i++) {
+ c_total += usage[i];
+ }
+
+ // Calculate diff against previous snapshot
+ d_idle = c_idle - load->last_idle;
+ d_total = c_total - load->last_total;
+
+ /** update if weve moved */
+ if (d_total > 0) {
+ // Save current values for next time around
+ load->last_idle = c_idle;
+ load->last_total = c_total;
+ load->last_ratio = (double) (d_total - d_idle) / d_total;
+ }
+
+ return load->last_ratio;
+}
+
+int get_info(const char *path, void *info, size_t s, off_t o) {
+ int fd;
+ int ret = 0;
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ return -1;
+ }
+ if (pread(fd, info, s, o) != s) {
+ ret = -1;
+ }
+ close(fd);
+ return ret;
+}
+
+#define MIN(a, b) ((a < b) ? a : b)
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
+ */
+double get_cpu_load(int which) {
+ double load =.0;
+
+ pthread_mutex_lock(&lock);
+ if(init_cpu_kstat_counters()==0) {
+
+ update_cpu_kstat_counters();
+
+ if (which == -1) {
+ unsigned int i;
+ double t;
+
+ for (t = .0, i = 0; i < num_cpus; i++) {
+ t += get_single_cpu_load(i);
+ }
+
+ // Cap total systemload to 1.0
+ load = MIN((t / num_cpus), 1.0);
+ } else {
+ load = MIN(get_single_cpu_load(which), 1.0);
+ }
+ } else {
+ load = -1.0;
+ }
+ pthread_mutex_unlock(&lock);
+
+ return load;
+}
+
+/**
+ * Return the cpu load (0-1) for the current process (i.e the JVM)
+ * or -1.0 if the get_info() call failed
+ */
+double get_process_load(void) {
+ psinfo_t info;
+
+ // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
+ // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
+ if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
+ return (double) info.pr_pctcpu / 0x8000;
+ }
+ return -1.0;
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getSystemCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ return get_cpu_load(-1);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ return get_process_load();
+}
+
--- a/jdk/src/windows/classes/com/sun/management/OSMBeanFactory.java Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.management;
-
-import java.lang.management.OperatingSystemMXBean;
-import sun.management.VMManagement;
-
-/**
- * Operating system dependent MBean factory.
- * <p>
- * <b>WARNING:</b> While this class is public, it should not be treated as
- * public API and its API may change in incompatable ways between dot dot
- * releases and even patch releases. You should not rely on this class.
- */
-public class OSMBeanFactory {
- /* static factory class */
- private OSMBeanFactory() {};
-
- private static OperatingSystem osMBean = null;
-
- public static synchronized OperatingSystemMXBean
- getOperatingSystemMXBean(VMManagement jvm) {
-
- if (osMBean == null) {
- osMBean = new OperatingSystem(jvm);
- }
- return (OperatingSystemMXBean) osMBean;
- }
-}
--- a/jdk/src/windows/classes/com/sun/management/OperatingSystem.java Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.management;
-
-import sun.management.VMManagement;
-
-/**
- * Implementation class for the operating system.
- * Standard and committed hotspot-specific metrics if any.
- *
- * ManagementFactory.getOperatingSystemMXBean() returns an instance
- * of this class.
- */
-class OperatingSystem
- extends sun.management.OperatingSystemImpl
- implements OperatingSystemMXBean {
-
- // psapiLock is a lock to make sure only one thread loading
- // PSAPI DLL.
- private static Object psapiLock = new Object();
-
- OperatingSystem(VMManagement vm) {
- super(vm);
- }
-
- public long getCommittedVirtualMemorySize() {
- synchronized (psapiLock) {
- return getCommittedVirtualMemorySize0();
- }
- }
- private native long getCommittedVirtualMemorySize0();
-
- public native long getTotalSwapSpaceSize();
- public native long getFreeSwapSpaceSize();
- public native long getProcessCpuTime();
- public native long getFreePhysicalMemorySize();
- public native long getTotalPhysicalMemorySize();
- public native double getSystemCpuLoad();
- public native double getProcessCpuLoad();
-
- static {
- initialize();
- }
- private static native void initialize();
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/management/OperatingSystemImpl.java Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management;
+
+import java.lang.management.OperatingSystemMXBean;
+
+/**
+ * Implementation class for the operating system.
+ * Standard and committed hotspot-specific metrics if any.
+ *
+ * ManagementFactory.getOperatingSystemMXBean() returns an instance
+ * of this class.
+ */
+class OperatingSystemImpl extends BaseOperatingSystemImpl
+ implements OperatingSystemMXBean {
+
+ // psapiLock is a lock to make sure only one thread loading
+ // PSAPI DLL.
+ private static Object psapiLock = new Object();
+
+ OperatingSystemImpl(VMManagement vm) {
+ super(vm);
+ }
+
+ public long getCommittedVirtualMemorySize() {
+ synchronized (psapiLock) {
+ return getCommittedVirtualMemorySize0();
+ }
+ }
+ private native long getCommittedVirtualMemorySize0();
+
+ public native long getTotalSwapSpaceSize();
+ public native long getFreeSwapSpaceSize();
+ public native long getProcessCpuTime();
+ public native long getFreePhysicalMemorySize();
+ public native long getTotalPhysicalMemorySize();
+ public native double getSystemCpuLoad();
+ public native double getProcessCpuLoad();
+
+ static {
+ initialize();
+ }
+ private static native void initialize();
+}
--- a/jdk/src/windows/native/com/sun/management/OperatingSystem_md.c Fri Nov 08 18:54:29 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,941 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jlong.h"
-#include "jvm.h"
-#include "management.h"
-#include "com_sun_management_OperatingSystem.h"
-
-#include <psapi.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include <malloc.h>
-#pragma warning (push,0)
-#include <windows.h>
-#pragma warning (pop)
-#include <stdio.h>
-#include <time.h>
-#include <stdint.h>
-#include <assert.h>
-
-/* Disable warnings due to broken header files from Microsoft... */
-#pragma warning(push, 3)
-#include <pdh.h>
-#include <pdhmsg.h>
-#include <process.h>
-#pragma warning(pop)
-
-typedef unsigned __int32 juint;
-typedef unsigned __int64 julong;
-
-typedef enum boolean_values { false=0, true=1};
-
-static void set_low(jlong* value, jint low) {
- *value &= (jlong)0xffffffff << 32;
- *value |= (jlong)(julong)(juint)low;
-}
-
-static void set_high(jlong* value, jint high) {
- *value &= (jlong)(julong)(juint)0xffffffff;
- *value |= (jlong)high << 32;
-}
-
-static jlong jlong_from(jint h, jint l) {
- jlong result = 0; // initialization to avoid warning
- set_high(&result, h);
- set_low(&result, l);
- return result;
-}
-
-static HANDLE main_process;
-
-int perfiInit(void);
-
-JNIEXPORT void JNICALL
-Java_com_sun_management_OperatingSystem_initialize
- (JNIEnv *env, jclass cls)
-{
- main_process = GetCurrentProcess();
- perfiInit();
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getCommittedVirtualMemorySize0
- (JNIEnv *env, jobject mbean)
-{
- PROCESS_MEMORY_COUNTERS pmc;
- if (GetProcessMemoryInfo(main_process, &pmc, sizeof(PROCESS_MEMORY_COUNTERS)) == 0) {
- return (jlong)-1L;
- } else {
- return (jlong) pmc.PagefileUsage;
- }
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getTotalSwapSpaceSize
- (JNIEnv *env, jobject mbean)
-{
- MEMORYSTATUSEX ms;
- ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullTotalPageFile;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getFreeSwapSpaceSize
- (JNIEnv *env, jobject mbean)
-{
- MEMORYSTATUSEX ms;
- ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullAvailPageFile;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getProcessCpuTime
- (JNIEnv *env, jobject mbean)
-{
-
- FILETIME process_creation_time, process_exit_time,
- process_user_time, process_kernel_time;
-
- // Using static variables declared above
- // Units are 100-ns intervals. Convert to ns.
- GetProcessTimes(main_process, &process_creation_time,
- &process_exit_time,
- &process_kernel_time, &process_user_time);
- return (jlong_from(process_user_time.dwHighDateTime,
- process_user_time.dwLowDateTime) +
- jlong_from(process_kernel_time.dwHighDateTime,
- process_kernel_time.dwLowDateTime)) * 100;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getFreePhysicalMemorySize
- (JNIEnv *env, jobject mbean)
-{
- MEMORYSTATUSEX ms;
- ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullAvailPhys;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_sun_management_OperatingSystem_getTotalPhysicalMemorySize
- (JNIEnv *env, jobject mbean)
-{
- MEMORYSTATUSEX ms;
- ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullTotalPhys;
-}
-
-// Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer.
-// Let's just ignore it, since we make sure we have enough buffer anyway.
-static int
-pdh_fail(PDH_STATUS pdhStat) {
- return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA;
-}
-
-// INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
-// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
-// The index value for the base system counters and objects like processor,
-// process, thread, memory, and so forth are always the same irrespective
-// of the localized version of the operating system or service pack installed.
-#define PDH_PROCESSOR_IDX ((DWORD) 238)
-#define PDH_PROCESSOR_TIME_IDX ((DWORD) 6)
-#define PDH_PRIV_PROCESSOR_TIME_IDX ((DWORD) 144)
-#define PDH_PROCESS_IDX ((DWORD) 230)
-#define PDH_ID_PROCESS_IDX ((DWORD) 784)
-#define PDH_CONTEXT_SWITCH_RATE_IDX ((DWORD) 146)
-#define PDH_SYSTEM_IDX ((DWORD) 2)
-#define PDH_VIRTUAL_BYTES_IDX ((DWORD) 174)
-
-typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)(
- HQUERY hQuery,
- LPCSTR szFullCounterPath,
- DWORD dwUserData,
- HCOUNTER *phCounter
- );
-typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)(
- LPCWSTR szDataSource,
- DWORD dwUserData,
- HQUERY *phQuery
- );
-typedef DWORD (WINAPI *PdhCloseQueryFunc)(
- HQUERY hQuery
- );
-typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)(
- HQUERY hQuery
- );
-typedef DWORD (WINAPI *PdhGetFormattedCounterValueFunc)(
- HCOUNTER hCounter,
- DWORD dwFormat,
- LPDWORD lpdwType,
- PPDH_FMT_COUNTERVALUE pValue
- );
-typedef PDH_STATUS (WINAPI *PdhEnumObjectItemsFunc)(
- LPCTSTR szDataSource,
- LPCTSTR szMachineName,
- LPCTSTR szObjectName,
- LPTSTR mszCounterList,
- LPDWORD pcchCounterListLength,
- LPTSTR mszInstanceList,
- LPDWORD pcchInstanceListLength,
- DWORD dwDetailLevel,
- DWORD dwFlags
- );
-typedef PDH_STATUS (WINAPI *PdhRemoveCounterFunc)(
- HCOUNTER hCounter
- );
-typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndexFunc)(
- LPCSTR szMachineName,
- DWORD dwNameIndex,
- LPSTR szNameBuffer,
- LPDWORD pcchNameBufferSize
- );
-typedef PDH_STATUS (WINAPI *PdhMakeCounterPathFunc)(
- PDH_COUNTER_PATH_ELEMENTS *pCounterPathElements,
- LPTSTR szFullPathBuffer,
- LPDWORD pcchBufferSize,
- DWORD dwFlags
- );
-
-static PdhAddCounterFunc PdhAddCounter_i;
-static PdhOpenQueryFunc PdhOpenQuery_i;
-static PdhCloseQueryFunc PdhCloseQuery_i;
-static PdhCollectQueryDataFunc PdhCollectQueryData_i;
-static PdhGetFormattedCounterValueFunc PdhGetFormattedCounterValue_i;
-static PdhEnumObjectItemsFunc PdhEnumObjectItems_i;
-static PdhRemoveCounterFunc PdhRemoveCounter_i;
-static PdhLookupPerfNameByIndexFunc PdhLookupPerfNameByIndex_i;
-static PdhMakeCounterPathFunc PdhMakeCounterPath_i;
-
-static HANDLE thisProcess;
-static double cpuFactor;
-static DWORD num_cpus;
-
-#define FT2JLONG(X) ((((jlong)X.dwHighDateTime) << 32) | ((jlong)X.dwLowDateTime))
-#define COUNTER_BUF_SIZE 256
-// Min time between query updates.
-#define MIN_UPDATE_INTERVAL 500
-#define CONFIG_SUCCESSFUL 0
-
-/**
- * Struct for PDH queries.
- */
-typedef struct {
- HQUERY query;
- uint64_t lastUpdate; // Last time query was updated (current millis).
-} UpdateQueryS, *UpdateQueryP;
-
-/**
- * Struct for the processor load counters.
- */
-typedef struct {
- UpdateQueryS query;
- HCOUNTER* counters;
- int noOfCounters;
-} MultipleCounterQueryS, *MultipleCounterQueryP;
-
-/**
- * Struct for the jvm process load counter.
- */
-typedef struct {
- UpdateQueryS query;
- HCOUNTER counter;
-} SingleCounterQueryS, *SingleCounterQueryP;
-
-static char* getProcessPDHHeader(void);
-
-/**
- * Currently available counters.
- */
-static SingleCounterQueryS cntCtxtSwitchRate;
-static SingleCounterQueryS cntVirtualSize;
-static SingleCounterQueryS cntProcLoad;
-static SingleCounterQueryS cntProcSystemLoad;
-static MultipleCounterQueryS multiCounterCPULoad;
-
-static CRITICAL_SECTION processHeaderLock;
-static CRITICAL_SECTION initializationLock;
-
-/**
- * Initialize the perf module at startup.
- */
-int
-perfiInit(void)
-{
- InitializeCriticalSection(&processHeaderLock);
- InitializeCriticalSection(&initializationLock);
- return 0;
-}
-
-/**
- * Dynamically sets up function pointers to the PDH library.
- *
- * @return CONFIG_SUCCESSFUL on success, negative on failure.
- */
-static int
-get_functions(HMODULE h, char *ebuf, size_t elen) {
- // The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
- PdhAddCounter_i = (PdhAddCounterFunc)GetProcAddress(h, "PdhAddCounterA");
- PdhOpenQuery_i = (PdhOpenQueryFunc)GetProcAddress(h, "PdhOpenQueryA");
- PdhCloseQuery_i = (PdhCloseQueryFunc)GetProcAddress(h, "PdhCloseQuery");
- PdhCollectQueryData_i = (PdhCollectQueryDataFunc)GetProcAddress(h, "PdhCollectQueryData");
- PdhGetFormattedCounterValue_i = (PdhGetFormattedCounterValueFunc)GetProcAddress(h, "PdhGetFormattedCounterValue");
- PdhEnumObjectItems_i = (PdhEnumObjectItemsFunc)GetProcAddress(h, "PdhEnumObjectItemsA");
- PdhRemoveCounter_i = (PdhRemoveCounterFunc)GetProcAddress(h, "PdhRemoveCounter");
- PdhLookupPerfNameByIndex_i = (PdhLookupPerfNameByIndexFunc)GetProcAddress(h, "PdhLookupPerfNameByIndexA");
- PdhMakeCounterPath_i = (PdhMakeCounterPathFunc)GetProcAddress(h, "PdhMakeCounterPathA");
-
- if (PdhAddCounter_i == NULL || PdhOpenQuery_i == NULL ||
- PdhCloseQuery_i == NULL || PdhCollectQueryData_i == NULL ||
- PdhGetFormattedCounterValue_i == NULL || PdhEnumObjectItems_i == NULL ||
- PdhRemoveCounter_i == NULL || PdhLookupPerfNameByIndex_i == NULL || PdhMakeCounterPath_i == NULL)
- {
- _snprintf(ebuf, elen, "Required method could not be found.");
- return -1;
- }
- return CONFIG_SUCCESSFUL;
-}
-
-/**
- * Returns the counter value as a double for the specified query.
- * Will collect the query data and update the counter values as necessary.
- *
- * @param query the query to update (if needed).
- * @param c the counter to read.
- * @param value where to store the formatted value.
- * @param format the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc)
- * @return CONFIG_SUCCESSFUL if no error
- * -1 if PdhCollectQueryData fails
- * -2 if PdhGetFormattedCounterValue fails
- */
-static int
-getPerformanceData(UpdateQueryP query, HCOUNTER c, PDH_FMT_COUNTERVALUE* value, DWORD format) {
- clock_t now;
- now = clock();
-
- // Need to limit how often we update the query
- // to mimise the heisenberg effect.
- // (PDH behaves erratically if the counters are
- // queried too often, especially counters that
- // store and use values from two consecutive updates,
- // like cpu load.)
- if (now - query->lastUpdate > MIN_UPDATE_INTERVAL) {
- if (PdhCollectQueryData_i(query->query) != ERROR_SUCCESS) {
- return -1;
- }
- query->lastUpdate = now;
- }
-
- if (PdhGetFormattedCounterValue_i(c, format, NULL, value) != ERROR_SUCCESS) {
- return -2;
- }
- return CONFIG_SUCCESSFUL;
-}
-
-/**
- * Places the resolved counter name of the counter at the specified index in the
- * supplied buffer. There must be enough space in the buffer to hold the counter name.
- *
- * @param index the counter index as specified in the registry.
- * @param buf the buffer in which to place the counter name.
- * @param size the size of the counter name buffer.
- * @param ebuf the error message buffer.
- * @param elen the length of the error buffer.
- * @return CONFIG_SUCCESSFUL if successful, negative on failure.
- */
-static int
-find_name(DWORD index, char *buf, DWORD size) {
- PDH_STATUS res;
-
- if ((res = PdhLookupPerfNameByIndex_i(NULL, index, buf, &size)) != ERROR_SUCCESS) {
-
- /* printf("Could not open counter %d: error=0x%08x", index, res); */
- /* if (res == PDH_CSTATUS_NO_MACHINE) { */
- /* printf("User probably does not have sufficient privileges to use"); */
- /* printf("performance counters. If you are running on Windows 2003"); */
- /* printf("or Windows Vista, make sure the user is in the"); */
- /* printf("Performance Logs user group."); */
- /* } */
- return -1;
- }
-
- if (size == 0) {
- /* printf("Failed to get counter name for %d: empty string", index); */
- return -1;
- }
-
- // windows vista does not null-terminate the string (allthough the docs says it will)
- buf[size - 1] = '\0';
- return CONFIG_SUCCESSFUL;
-}
-
-/**
- * Sets up the supplied SingleCounterQuery to listen for the specified counter.
- * initPDH() must have been run prior to calling this function!
- *
- * @param counterQuery the counter query to set up.
- * @param counterString the string specifying the path to the counter.
- * @param ebuf the error buffer.
- * @param elen the length of the error buffer.
- * @returns CONFIG_SUCCESSFUL if successful, negative on failure.
- */
-static int
-initSingleCounterQuery(SingleCounterQueryP counterQuery, char *counterString) {
- if (PdhOpenQuery_i(NULL, 0, &counterQuery->query.query) != ERROR_SUCCESS) {
- /* printf("Could not open query for %s", counterString); */
- return -1;
- }
- if (PdhAddCounter_i(counterQuery->query.query, counterString, 0, &counterQuery->counter) != ERROR_SUCCESS) {
- /* printf("Could not add counter %s for query", counterString); */
- if (counterQuery->counter != NULL) {
- PdhRemoveCounter_i(counterQuery->counter);
- }
- if (counterQuery->query.query != NULL) {
- PdhCloseQuery_i(counterQuery->query.query);
- }
- memset(counterQuery, 0, sizeof(SingleCounterQueryS));
- return -1;
- }
- return CONFIG_SUCCESSFUL;
-}
-
-/**
- * Sets up the supplied SingleCounterQuery to listen for the time spent
- * by the HotSpot process.
- *
- * @param counterQuery the counter query to set up as a process counter.
- * @param ebuf the error buffer.
- * @param elen the length of the error buffer.
- * @returns CONFIG_SUCCESSFUL if successful, negative on failure.
- */
-static int
-initProcLoadCounter(void) {
- char time[COUNTER_BUF_SIZE];
- char counter[COUNTER_BUF_SIZE*2];
-
- if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
- return -1;
- }
- _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
- return initSingleCounterQuery(&cntProcLoad, counter);
-}
-
-static int
-initProcSystemLoadCounter(void) {
- char time[COUNTER_BUF_SIZE];
- char counter[COUNTER_BUF_SIZE*2];
-
- if (find_name(PDH_PRIV_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
- return -1;
- }
- _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
- return initSingleCounterQuery(&cntProcSystemLoad, counter);
-}
-
-/**
- * Sets up the supplied MultipleCounterQuery to check on the processors.
- * (Comment: Refactor and prettify as with the the SingleCounter queries
- * if more MultipleCounterQueries are discovered.)
- *
- * initPDH() must have been run prior to calling this function.
- *
- * @param multiQuery a pointer to a MultipleCounterQueryS, will be filled in with
- * the necessary info to check the PDH processor counters.
- * @return CONFIG_SUCCESSFUL if successful, negative on failure.
- */
-static int
-initProcessorCounters(void) {
- char processor[COUNTER_BUF_SIZE]; //'Processor' == #238
- char time[COUNTER_BUF_SIZE]; //'Time' == 6
- DWORD c_size, i_size;
- HQUERY tmpQuery;
- DWORD i, p_count;
- BOOL error;
- char *instances, *tmp;
- PDH_STATUS pdhStat;
-
- c_size = i_size = 0;
- tmpQuery = NULL;
- error = false;
-
- // This __try / __except stuff is there since Windows 2000 beta (or so) sometimes triggered
- // an access violation when the user had insufficient privileges to use the performance
- // counters. This was previously guarded by a very ugly piece of code which disabled the
- // global trap handling in JRockit. Don't know if this really is needed anymore, but otoh,
- // if we keep it we don't crash on Win2k beta. /Ihse, 2005-05-30
- __try {
- if (find_name(PDH_PROCESSOR_IDX, processor, sizeof(processor)-1) < 0) {
- return -1;
- }
- } __except (EXCEPTION_EXECUTE_HANDLER) { // We'll catch all exceptions here.
- /* printf("User does not have sufficient privileges to use performance counters"); */
- return -1;
- }
-
- if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
- return -1;
- }
- //ok, now we have enough to enumerate all processors.
- pdhStat = PdhEnumObjectItems_i (
- NULL, // reserved
- NULL, // local machine
- processor, // object to enumerate
- NULL, // pass in NULL buffers
- &c_size, // and 0 length to get
- NULL, // required size
- &i_size, // of the buffers in chars
- PERF_DETAIL_WIZARD, // counter detail level
- 0);
- if (pdh_fail(pdhStat)) {
- /* printf("could not enumerate processors (1) error=%d", pdhStat); */
- return -1;
- }
-
- // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
- instances = calloc(i_size, 1);
- if (instances == NULL) {
- /* printf("could not allocate memory (1) %d bytes", i_size); */
- error = true;
- goto end;
- }
-
- c_size = 0;
- pdhStat = PdhEnumObjectItems_i (
- NULL, // reserved
- NULL, // local machine
- processor, // object to enumerate
- NULL, // pass in NULL buffers
- &c_size, // and 0 length to get
- instances, // required size
- &i_size, // of the buffers in chars
- PERF_DETAIL_WIZARD, // counter detail level
- 0);
-
- if (pdh_fail(pdhStat)) {
- /* printf("could not enumerate processors (2) error=%d", pdhStat); */
- error = true;
- goto end;
- }
- //count perf count instances.
- for (p_count = 0, tmp = instances; *tmp != 0; tmp = &tmp[lstrlen(tmp)+1], p_count++);
-
- //is this correct for HT?
- assert(p_count == num_cpus+1);
-
- //ok, have number of perf counters.
- multiCounterCPULoad.counters = calloc(p_count, sizeof(HCOUNTER));
- if (multiCounterCPULoad.counters == NULL) {
- /* printf("could not allocate memory (2) count=%d", p_count); */
- error = true;
- goto end;
- }
-
- multiCounterCPULoad.noOfCounters = p_count;
-
- if (PdhOpenQuery_i(NULL, 0, &multiCounterCPULoad.query.query) != ERROR_SUCCESS) {
- /* printf("could not create query"); */
- error = true;
- goto end;
- }
- //now, fetch the counters.
- for (i = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[lstrlen(tmp)+1], i++) {
- char counter[2*COUNTER_BUF_SIZE];
-
- _snprintf(counter, sizeof(counter)-1, "\\%s(%s)\\%s", processor, tmp, time);
-
- if (PdhAddCounter_i(multiCounterCPULoad.query.query, counter, 0, &multiCounterCPULoad.counters[i]) != ERROR_SUCCESS) {
- /* printf("error adding processor counter %s", counter); */
- error = true;
- goto end;
- }
- }
-
- free(instances);
- instances = NULL;
-
- // Query once to initialize the counters needing at least two queries
- // (like the % CPU usage) to calculate correctly.
- if (PdhCollectQueryData_i(multiCounterCPULoad.query.query) != ERROR_SUCCESS)
- error = true;
-
- end:
- if (instances != NULL) {
- free(instances);
- }
- if (tmpQuery != NULL) {
- PdhCloseQuery_i(tmpQuery);
- }
- if (error) {
- int i;
-
- if (multiCounterCPULoad.counters != NULL) {
- for (i = 0; i < multiCounterCPULoad.noOfCounters; i++) {
- if (multiCounterCPULoad.counters[i] != NULL) {
- PdhRemoveCounter_i(multiCounterCPULoad.counters[i]);
- }
- }
- free(multiCounterCPULoad.counters[i]);
- }
- if (multiCounterCPULoad.query.query != NULL) {
- PdhCloseQuery_i(multiCounterCPULoad.query.query);
- }
- memset(&multiCounterCPULoad, 0, sizeof(MultipleCounterQueryS));
- return -1;
- }
- return CONFIG_SUCCESSFUL;
-}
-
-/**
- * Help function that initializes the PDH process header for the JRockit process.
- * (You should probably use getProcessPDHHeader() instead!)
- *
- * initPDH() must have been run prior to calling this function.
- *
- * @param ebuf the error buffer.
- * @param elen the length of the error buffer.
- *
- * @return the PDH instance description corresponding to the JVM process.
- */
-static char*
-initProcessPDHHeader(void) {
- static char hotspotheader[2*COUNTER_BUF_SIZE];
-
- char counter[2*COUNTER_BUF_SIZE];
- char processes[COUNTER_BUF_SIZE]; //'Process' == #230
- char pid[COUNTER_BUF_SIZE]; //'ID Process' == 784
- char module_name[MAX_PATH];
- PDH_STATUS pdhStat;
- DWORD c_size = 0, i_size = 0;
- HQUERY tmpQuery = NULL;
- int i, myPid = _getpid();
- BOOL error = false;
- char *instances, *tmp, *instance_name, *dot_pos;
-
- tmpQuery = NULL;
- myPid = _getpid();
- error = false;
-
- if (find_name(PDH_PROCESS_IDX, processes, sizeof(processes) - 1) < 0) {
- return NULL;
- }
-
- if (find_name(PDH_ID_PROCESS_IDX, pid, sizeof(pid) - 1) < 0) {
- return NULL;
- }
- //time is same.
-
- c_size = 0;
- i_size = 0;
-
- pdhStat = PdhEnumObjectItems_i (
- NULL, // reserved
- NULL, // local machine
- processes, // object to enumerate
- NULL, // pass in NULL buffers
- &c_size, // and 0 length to get
- NULL, // required size
- &i_size, // of the buffers in chars
- PERF_DETAIL_WIZARD, // counter detail level
- 0);
-
- //ok, now we have enough to enumerate all processes
- if (pdh_fail(pdhStat)) {
- /* printf("Could not enumerate processes (1) error=%d", pdhStat); */
- return NULL;
- }
-
- // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
- if ((instances = calloc(i_size, 1)) == NULL) {
- /* printf("Could not allocate memory %d bytes", i_size); */
- error = true;
- goto end;
- }
-
- c_size = 0;
-
- pdhStat = PdhEnumObjectItems_i (
- NULL, // reserved
- NULL, // local machine
- processes, // object to enumerate
- NULL, // pass in NULL buffers
- &c_size, // and 0 length to get
- instances, // required size
- &i_size, // of the buffers in chars
- PERF_DETAIL_WIZARD, // counter detail level
- 0);
-
- // ok, now we have enough to enumerate all processes
- if (pdh_fail(pdhStat)) {
- /* printf("Could not enumerate processes (2) error=%d", pdhStat); */
- error = true;
- goto end;
- }
-
- if (PdhOpenQuery_i(NULL, 0, &tmpQuery) != ERROR_SUCCESS) {
- /* printf("Could not create temporary query"); */
- error = true;
- goto end;
- }
-
- // Find our module name and use it to extract the instance name used by PDH
- if (GetModuleFileName(NULL, module_name, MAX_PATH) >= MAX_PATH-1) {
- /* printf("Module name truncated"); */
- error = true;
- goto end;
- }
- instance_name = strrchr(module_name, '\\'); //drop path
- instance_name++; //skip slash
- dot_pos = strchr(instance_name, '.'); //drop .exe
- dot_pos[0] = '\0';
-
- //now, fetch the counters.
- for (tmp = instances; *tmp != 0 && !error; tmp = &tmp[lstrlen(tmp)+1]) {
- HCOUNTER hc = NULL;
- BOOL done = false;
-
- // Skip until we find our own process name
- if (strcmp(tmp, instance_name) != 0) {
- continue;
- }
-
- // iterate over all instance indexes and try to find our own pid
- for (i = 0; !done && !error; i++){
- PDH_STATUS res;
- _snprintf(counter, sizeof(counter)-1, "\\%s(%s#%d)\\%s", processes, tmp, i, pid);
-
- if (PdhAddCounter_i(tmpQuery, counter, 0, &hc) != ERROR_SUCCESS) {
- /* printf("Failed to create process id query"); */
- error = true;
- goto end;
- }
-
- res = PdhCollectQueryData_i(tmpQuery);
-
- if (res == PDH_INVALID_HANDLE) {
- /* printf("Failed to query process id"); */
- res = -1;
- done = true;
- } else if (res == PDH_NO_DATA) {
- done = true;
- } else {
- PDH_FMT_COUNTERVALUE cv;
-
- PdhGetFormattedCounterValue_i(hc, PDH_FMT_LONG, NULL, &cv);
- /*
- * This check seems to be needed for Win2k SMP boxes, since
- * they for some reason don't return PDH_NO_DATA for non existing
- * counters.
- */
- if (cv.CStatus != PDH_CSTATUS_VALID_DATA) {
- done = true;
- } else if (cv.longValue == myPid) {
- _snprintf(hotspotheader, sizeof(hotspotheader)-1, "\\%s(%s#%d)\0", processes, tmp, i);
- PdhRemoveCounter_i(hc);
- goto end;
- }
- }
- PdhRemoveCounter_i(hc);
- }
- }
- end:
- if (instances != NULL) {
- free(instances);
- }
- if (tmpQuery != NULL) {
- PdhCloseQuery_i(tmpQuery);
- }
- if (error) {
- return NULL;
- }
- return hotspotheader;
-}
-
-/**
- * Returns the PDH string prefix identifying the HotSpot process. Use this prefix when getting
- * counters from the PDH process object representing HotSpot.
- *
- * Note: this call may take some time to complete.
- *
- * @param ebuf error buffer.
- * @param elen error buffer length.
- *
- * @return the header to be used when retrieving PDH counters from the HotSpot process.
- * Will return NULL if the call failed.
- */
-static char *
-getProcessPDHHeader(void) {
- static char *processHeader = NULL;
-
- EnterCriticalSection(&processHeaderLock); {
- if (processHeader == NULL) {
- processHeader = initProcessPDHHeader();
- }
- } LeaveCriticalSection(&processHeaderLock);
- return processHeader;
-}
-
-int perfInit(void);
-
-double
-perfGetCPULoad(int which)
-{
- PDH_FMT_COUNTERVALUE cv;
- HCOUNTER c;
-
- if (perfInit() < 0) {
- // warn?
- return -1.0;
- }
-
- if (multiCounterCPULoad.query.query == NULL) {
- // warn?
- return -1.0;
- }
-
- if (which == -1) {
- c = multiCounterCPULoad.counters[multiCounterCPULoad.noOfCounters - 1];
- } else {
- if (which < multiCounterCPULoad.noOfCounters) {
- c = multiCounterCPULoad.counters[which];
- } else {
- return -1.0;
- }
- }
- if (getPerformanceData(&multiCounterCPULoad.query, c, &cv, PDH_FMT_DOUBLE ) == CONFIG_SUCCESSFUL) {
- return cv.doubleValue / 100;
- }
- return -1.0;
-}
-
-double
-perfGetProcessLoad(void)
-{
- PDH_FMT_COUNTERVALUE cv;
-
- if (perfInit() < 0) {
- // warn?
- return -1.0;
- }
-
- if (cntProcLoad.query.query == NULL) {
- // warn?
- return -1.0;
- }
-
- if (getPerformanceData(&cntProcLoad.query, cntProcLoad.counter, &cv, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100) == CONFIG_SUCCESSFUL) {
- double d = cv.doubleValue / cpuFactor;
- d = min(1, d);
- d = max(0, d);
- return d;
- }
- return -1.0;
-}
-
-/**
- * Helper to initialize the PDH library. Loads the library and sets up the functions.
- * Note that once loaded, we will never unload the PDH library.
- *
- * @return CONFIG_SUCCESSFUL if successful, negative on failure.
- */
-int
-perfInit(void) {
- static HMODULE h;
- static BOOL running, inited;
-
- int error;
-
- if (running) {
- return CONFIG_SUCCESSFUL;
- }
-
- error = CONFIG_SUCCESSFUL;
-
- // this is double checked locking again, but we try to bypass the worst by
- // implicit membar at end of lock.
- EnterCriticalSection(&initializationLock); {
- if (!inited) {
- char buf[64] = "";
- SYSTEM_INFO si;
-
- // CMH. But windows will not care about our affinity when giving
- // us measurements. Need the real, raw num cpus.
-
- GetSystemInfo(&si);
- num_cpus = si.dwNumberOfProcessors;
- // Initialize the denominator for the jvm load calculations
- cpuFactor = num_cpus * 100;
-
- /**
- * Do this dynamically, so we don't fail to start on systems without pdh.
- */
- if ((h = LoadLibrary("pdh.dll")) == NULL) {
- /* printf("Could not load pdh.dll (%d)", GetLastError()); */
- error = -2;
- } else if (get_functions(h, buf, sizeof(buf)) < 0) {
- FreeLibrary(h);
- h = NULL;
- error = -2;
- /* printf("Failed to init pdh functions: %s.\n", buf); */
- } else {
- if (initProcessorCounters() != 0) {
- /* printf("Failed to init system load counters.\n"); */
- } else if (initProcLoadCounter() != 0) {
- /* printf("Failed to init process load counter.\n"); */
- } else if (initProcSystemLoadCounter() != 0) {
- /* printf("Failed to init process system load counter.\n"); */
- } else {
- inited = true;
- }
- }
- }
- } LeaveCriticalSection(&initializationLock);
-
- if (inited && error == CONFIG_SUCCESSFUL) {
- running = true;
- }
-
- return error;
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_OperatingSystem_getSystemCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- return perfGetCPULoad(-1);
-}
-
-JNIEXPORT jdouble JNICALL
-Java_com_sun_management_OperatingSystem_getProcessCpuLoad
-(JNIEnv *env, jobject dummy)
-{
- return perfGetProcessLoad();
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/native/sun/management/OperatingSystemImpl.c Fri Nov 08 12:13:02 2013 -0800
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+#include "management.h"
+#include "sun_management_OperatingSystemImpl.h"
+
+#include <psapi.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <malloc.h>
+#pragma warning (push,0)
+#include <windows.h>
+#pragma warning (pop)
+#include <stdio.h>
+#include <time.h>
+#include <stdint.h>
+#include <assert.h>
+
+/* Disable warnings due to broken header files from Microsoft... */
+#pragma warning(push, 3)
+#include <pdh.h>
+#include <pdhmsg.h>
+#include <process.h>
+#pragma warning(pop)
+
+typedef unsigned __int32 juint;
+typedef unsigned __int64 julong;
+
+typedef enum boolean_values { false=0, true=1};
+
+static void set_low(jlong* value, jint low) {
+ *value &= (jlong)0xffffffff << 32;
+ *value |= (jlong)(julong)(juint)low;
+}
+
+static void set_high(jlong* value, jint high) {
+ *value &= (jlong)(julong)(juint)0xffffffff;
+ *value |= (jlong)high << 32;
+}
+
+static jlong jlong_from(jint h, jint l) {
+ jlong result = 0; // initialization to avoid warning
+ set_high(&result, h);
+ set_low(&result, l);
+ return result;
+}
+
+static HANDLE main_process;
+
+int perfiInit(void);
+
+JNIEXPORT void JNICALL
+Java_sun_management_OperatingSystemImpl_initialize
+ (JNIEnv *env, jclass cls)
+{
+ main_process = GetCurrentProcess();
+ perfiInit();
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0
+ (JNIEnv *env, jobject mbean)
+{
+ PROCESS_MEMORY_COUNTERS pmc;
+ if (GetProcessMemoryInfo(main_process, &pmc, sizeof(PROCESS_MEMORY_COUNTERS)) == 0) {
+ return (jlong)-1L;
+ } else {
+ return (jlong) pmc.PagefileUsage;
+ }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize
+ (JNIEnv *env, jobject mbean)
+{
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullTotalPageFile;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize
+ (JNIEnv *env, jobject mbean)
+{
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullAvailPageFile;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuTime
+ (JNIEnv *env, jobject mbean)
+{
+
+ FILETIME process_creation_time, process_exit_time,
+ process_user_time, process_kernel_time;
+
+ // Using static variables declared above
+ // Units are 100-ns intervals. Convert to ns.
+ GetProcessTimes(main_process, &process_creation_time,
+ &process_exit_time,
+ &process_kernel_time, &process_user_time);
+ return (jlong_from(process_user_time.dwHighDateTime,
+ process_user_time.dwLowDateTime) +
+ jlong_from(process_kernel_time.dwHighDateTime,
+ process_kernel_time.dwLowDateTime)) * 100;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize
+ (JNIEnv *env, jobject mbean)
+{
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullAvailPhys;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize
+ (JNIEnv *env, jobject mbean)
+{
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullTotalPhys;
+}
+
+// Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer.
+// Let's just ignore it, since we make sure we have enough buffer anyway.
+static int
+pdh_fail(PDH_STATUS pdhStat) {
+ return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA;
+}
+
+// INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
+// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
+// The index value for the base system counters and objects like processor,
+// process, thread, memory, and so forth are always the same irrespective
+// of the localized version of the operating system or service pack installed.
+#define PDH_PROCESSOR_IDX ((DWORD) 238)
+#define PDH_PROCESSOR_TIME_IDX ((DWORD) 6)
+#define PDH_PRIV_PROCESSOR_TIME_IDX ((DWORD) 144)
+#define PDH_PROCESS_IDX ((DWORD) 230)
+#define PDH_ID_PROCESS_IDX ((DWORD) 784)
+#define PDH_CONTEXT_SWITCH_RATE_IDX ((DWORD) 146)
+#define PDH_SYSTEM_IDX ((DWORD) 2)
+#define PDH_VIRTUAL_BYTES_IDX ((DWORD) 174)
+
+typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)(
+ HQUERY hQuery,
+ LPCSTR szFullCounterPath,
+ DWORD dwUserData,
+ HCOUNTER *phCounter
+ );
+typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)(
+ LPCWSTR szDataSource,
+ DWORD dwUserData,
+ HQUERY *phQuery
+ );
+typedef DWORD (WINAPI *PdhCloseQueryFunc)(
+ HQUERY hQuery
+ );
+typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)(
+ HQUERY hQuery
+ );
+typedef DWORD (WINAPI *PdhGetFormattedCounterValueFunc)(
+ HCOUNTER hCounter,
+ DWORD dwFormat,
+ LPDWORD lpdwType,
+ PPDH_FMT_COUNTERVALUE pValue
+ );
+typedef PDH_STATUS (WINAPI *PdhEnumObjectItemsFunc)(
+ LPCTSTR szDataSource,
+ LPCTSTR szMachineName,
+ LPCTSTR szObjectName,
+ LPTSTR mszCounterList,
+ LPDWORD pcchCounterListLength,
+ LPTSTR mszInstanceList,
+ LPDWORD pcchInstanceListLength,
+ DWORD dwDetailLevel,
+ DWORD dwFlags
+ );
+typedef PDH_STATUS (WINAPI *PdhRemoveCounterFunc)(
+ HCOUNTER hCounter
+ );
+typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndexFunc)(
+ LPCSTR szMachineName,
+ DWORD dwNameIndex,
+ LPSTR szNameBuffer,
+ LPDWORD pcchNameBufferSize
+ );
+typedef PDH_STATUS (WINAPI *PdhMakeCounterPathFunc)(
+ PDH_COUNTER_PATH_ELEMENTS *pCounterPathElements,
+ LPTSTR szFullPathBuffer,
+ LPDWORD pcchBufferSize,
+ DWORD dwFlags
+ );
+
+static PdhAddCounterFunc PdhAddCounter_i;
+static PdhOpenQueryFunc PdhOpenQuery_i;
+static PdhCloseQueryFunc PdhCloseQuery_i;
+static PdhCollectQueryDataFunc PdhCollectQueryData_i;
+static PdhGetFormattedCounterValueFunc PdhGetFormattedCounterValue_i;
+static PdhEnumObjectItemsFunc PdhEnumObjectItems_i;
+static PdhRemoveCounterFunc PdhRemoveCounter_i;
+static PdhLookupPerfNameByIndexFunc PdhLookupPerfNameByIndex_i;
+static PdhMakeCounterPathFunc PdhMakeCounterPath_i;
+
+static HANDLE thisProcess;
+static double cpuFactor;
+static DWORD num_cpus;
+
+#define FT2JLONG(X) ((((jlong)X.dwHighDateTime) << 32) | ((jlong)X.dwLowDateTime))
+#define COUNTER_BUF_SIZE 256
+// Min time between query updates.
+#define MIN_UPDATE_INTERVAL 500
+#define CONFIG_SUCCESSFUL 0
+
+/**
+ * Struct for PDH queries.
+ */
+typedef struct {
+ HQUERY query;
+ uint64_t lastUpdate; // Last time query was updated (current millis).
+} UpdateQueryS, *UpdateQueryP;
+
+/**
+ * Struct for the processor load counters.
+ */
+typedef struct {
+ UpdateQueryS query;
+ HCOUNTER* counters;
+ int noOfCounters;
+} MultipleCounterQueryS, *MultipleCounterQueryP;
+
+/**
+ * Struct for the jvm process load counter.
+ */
+typedef struct {
+ UpdateQueryS query;
+ HCOUNTER counter;
+} SingleCounterQueryS, *SingleCounterQueryP;
+
+static char* getProcessPDHHeader(void);
+
+/**
+ * Currently available counters.
+ */
+static SingleCounterQueryS cntCtxtSwitchRate;
+static SingleCounterQueryS cntVirtualSize;
+static SingleCounterQueryS cntProcLoad;
+static SingleCounterQueryS cntProcSystemLoad;
+static MultipleCounterQueryS multiCounterCPULoad;
+
+static CRITICAL_SECTION processHeaderLock;
+static CRITICAL_SECTION initializationLock;
+
+/**
+ * Initialize the perf module at startup.
+ */
+int
+perfiInit(void)
+{
+ InitializeCriticalSection(&processHeaderLock);
+ InitializeCriticalSection(&initializationLock);
+ return 0;
+}
+
+/**
+ * Dynamically sets up function pointers to the PDH library.
+ *
+ * @return CONFIG_SUCCESSFUL on success, negative on failure.
+ */
+static int
+get_functions(HMODULE h, char *ebuf, size_t elen) {
+ // The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
+ PdhAddCounter_i = (PdhAddCounterFunc)GetProcAddress(h, "PdhAddCounterA");
+ PdhOpenQuery_i = (PdhOpenQueryFunc)GetProcAddress(h, "PdhOpenQueryA");
+ PdhCloseQuery_i = (PdhCloseQueryFunc)GetProcAddress(h, "PdhCloseQuery");
+ PdhCollectQueryData_i = (PdhCollectQueryDataFunc)GetProcAddress(h, "PdhCollectQueryData");
+ PdhGetFormattedCounterValue_i = (PdhGetFormattedCounterValueFunc)GetProcAddress(h, "PdhGetFormattedCounterValue");
+ PdhEnumObjectItems_i = (PdhEnumObjectItemsFunc)GetProcAddress(h, "PdhEnumObjectItemsA");
+ PdhRemoveCounter_i = (PdhRemoveCounterFunc)GetProcAddress(h, "PdhRemoveCounter");
+ PdhLookupPerfNameByIndex_i = (PdhLookupPerfNameByIndexFunc)GetProcAddress(h, "PdhLookupPerfNameByIndexA");
+ PdhMakeCounterPath_i = (PdhMakeCounterPathFunc)GetProcAddress(h, "PdhMakeCounterPathA");
+
+ if (PdhAddCounter_i == NULL || PdhOpenQuery_i == NULL ||
+ PdhCloseQuery_i == NULL || PdhCollectQueryData_i == NULL ||
+ PdhGetFormattedCounterValue_i == NULL || PdhEnumObjectItems_i == NULL ||
+ PdhRemoveCounter_i == NULL || PdhLookupPerfNameByIndex_i == NULL || PdhMakeCounterPath_i == NULL)
+ {
+ _snprintf(ebuf, elen, "Required method could not be found.");
+ return -1;
+ }
+ return CONFIG_SUCCESSFUL;
+}
+
+/**
+ * Returns the counter value as a double for the specified query.
+ * Will collect the query data and update the counter values as necessary.
+ *
+ * @param query the query to update (if needed).
+ * @param c the counter to read.
+ * @param value where to store the formatted value.
+ * @param format the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc)
+ * @return CONFIG_SUCCESSFUL if no error
+ * -1 if PdhCollectQueryData fails
+ * -2 if PdhGetFormattedCounterValue fails
+ */
+static int
+getPerformanceData(UpdateQueryP query, HCOUNTER c, PDH_FMT_COUNTERVALUE* value, DWORD format) {
+ clock_t now;
+ now = clock();
+
+ // Need to limit how often we update the query
+ // to mimise the heisenberg effect.
+ // (PDH behaves erratically if the counters are
+ // queried too often, especially counters that
+ // store and use values from two consecutive updates,
+ // like cpu load.)
+ if (now - query->lastUpdate > MIN_UPDATE_INTERVAL) {
+ if (PdhCollectQueryData_i(query->query) != ERROR_SUCCESS) {
+ return -1;
+ }
+ query->lastUpdate = now;
+ }
+
+ if (PdhGetFormattedCounterValue_i(c, format, NULL, value) != ERROR_SUCCESS) {
+ return -2;
+ }
+ return CONFIG_SUCCESSFUL;
+}
+
+/**
+ * Places the resolved counter name of the counter at the specified index in the
+ * supplied buffer. There must be enough space in the buffer to hold the counter name.
+ *
+ * @param index the counter index as specified in the registry.
+ * @param buf the buffer in which to place the counter name.
+ * @param size the size of the counter name buffer.
+ * @param ebuf the error message buffer.
+ * @param elen the length of the error buffer.
+ * @return CONFIG_SUCCESSFUL if successful, negative on failure.
+ */
+static int
+find_name(DWORD index, char *buf, DWORD size) {
+ PDH_STATUS res;
+
+ if ((res = PdhLookupPerfNameByIndex_i(NULL, index, buf, &size)) != ERROR_SUCCESS) {
+
+ /* printf("Could not open counter %d: error=0x%08x", index, res); */
+ /* if (res == PDH_CSTATUS_NO_MACHINE) { */
+ /* printf("User probably does not have sufficient privileges to use"); */
+ /* printf("performance counters. If you are running on Windows 2003"); */
+ /* printf("or Windows Vista, make sure the user is in the"); */
+ /* printf("Performance Logs user group."); */
+ /* } */
+ return -1;
+ }
+
+ if (size == 0) {
+ /* printf("Failed to get counter name for %d: empty string", index); */
+ return -1;
+ }
+
+ // windows vista does not null-terminate the string (allthough the docs says it will)
+ buf[size - 1] = '\0';
+ return CONFIG_SUCCESSFUL;
+}
+
+/**
+ * Sets up the supplied SingleCounterQuery to listen for the specified counter.
+ * initPDH() must have been run prior to calling this function!
+ *
+ * @param counterQuery the counter query to set up.
+ * @param counterString the string specifying the path to the counter.
+ * @param ebuf the error buffer.
+ * @param elen the length of the error buffer.
+ * @returns CONFIG_SUCCESSFUL if successful, negative on failure.
+ */
+static int
+initSingleCounterQuery(SingleCounterQueryP counterQuery, char *counterString) {
+ if (PdhOpenQuery_i(NULL, 0, &counterQuery->query.query) != ERROR_SUCCESS) {
+ /* printf("Could not open query for %s", counterString); */
+ return -1;
+ }
+ if (PdhAddCounter_i(counterQuery->query.query, counterString, 0, &counterQuery->counter) != ERROR_SUCCESS) {
+ /* printf("Could not add counter %s for query", counterString); */
+ if (counterQuery->counter != NULL) {
+ PdhRemoveCounter_i(counterQuery->counter);
+ }
+ if (counterQuery->query.query != NULL) {
+ PdhCloseQuery_i(counterQuery->query.query);
+ }
+ memset(counterQuery, 0, sizeof(SingleCounterQueryS));
+ return -1;
+ }
+ return CONFIG_SUCCESSFUL;
+}
+
+/**
+ * Sets up the supplied SingleCounterQuery to listen for the time spent
+ * by the HotSpot process.
+ *
+ * @param counterQuery the counter query to set up as a process counter.
+ * @param ebuf the error buffer.
+ * @param elen the length of the error buffer.
+ * @returns CONFIG_SUCCESSFUL if successful, negative on failure.
+ */
+static int
+initProcLoadCounter(void) {
+ char time[COUNTER_BUF_SIZE];
+ char counter[COUNTER_BUF_SIZE*2];
+
+ if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
+ return -1;
+ }
+ _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
+ return initSingleCounterQuery(&cntProcLoad, counter);
+}
+
+static int
+initProcSystemLoadCounter(void) {
+ char time[COUNTER_BUF_SIZE];
+ char counter[COUNTER_BUF_SIZE*2];
+
+ if (find_name(PDH_PRIV_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
+ return -1;
+ }
+ _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
+ return initSingleCounterQuery(&cntProcSystemLoad, counter);
+}
+
+/**
+ * Sets up the supplied MultipleCounterQuery to check on the processors.
+ * (Comment: Refactor and prettify as with the the SingleCounter queries
+ * if more MultipleCounterQueries are discovered.)
+ *
+ * initPDH() must have been run prior to calling this function.
+ *
+ * @param multiQuery a pointer to a MultipleCounterQueryS, will be filled in with
+ * the necessary info to check the PDH processor counters.
+ * @return CONFIG_SUCCESSFUL if successful, negative on failure.
+ */
+static int
+initProcessorCounters(void) {
+ char processor[COUNTER_BUF_SIZE]; //'Processor' == #238
+ char time[COUNTER_BUF_SIZE]; //'Time' == 6
+ DWORD c_size, i_size;
+ HQUERY tmpQuery;
+ DWORD i, p_count;
+ BOOL error;
+ char *instances, *tmp;
+ PDH_STATUS pdhStat;
+
+ c_size = i_size = 0;
+ tmpQuery = NULL;
+ error = false;
+
+ // This __try / __except stuff is there since Windows 2000 beta (or so) sometimes triggered
+ // an access violation when the user had insufficient privileges to use the performance
+ // counters. This was previously guarded by a very ugly piece of code which disabled the
+ // global trap handling in JRockit. Don't know if this really is needed anymore, but otoh,
+ // if we keep it we don't crash on Win2k beta. /Ihse, 2005-05-30
+ __try {
+ if (find_name(PDH_PROCESSOR_IDX, processor, sizeof(processor)-1) < 0) {
+ return -1;
+ }
+ } __except (EXCEPTION_EXECUTE_HANDLER) { // We'll catch all exceptions here.
+ /* printf("User does not have sufficient privileges to use performance counters"); */
+ return -1;
+ }
+
+ if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
+ return -1;
+ }
+ //ok, now we have enough to enumerate all processors.
+ pdhStat = PdhEnumObjectItems_i (
+ NULL, // reserved
+ NULL, // local machine
+ processor, // object to enumerate
+ NULL, // pass in NULL buffers
+ &c_size, // and 0 length to get
+ NULL, // required size
+ &i_size, // of the buffers in chars
+ PERF_DETAIL_WIZARD, // counter detail level
+ 0);
+ if (pdh_fail(pdhStat)) {
+ /* printf("could not enumerate processors (1) error=%d", pdhStat); */
+ return -1;
+ }
+
+ // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
+ instances = calloc(i_size, 1);
+ if (instances == NULL) {
+ /* printf("could not allocate memory (1) %d bytes", i_size); */
+ error = true;
+ goto end;
+ }
+
+ c_size = 0;
+ pdhStat = PdhEnumObjectItems_i (
+ NULL, // reserved
+ NULL, // local machine
+ processor, // object to enumerate
+ NULL, // pass in NULL buffers
+ &c_size, // and 0 length to get
+ instances, // required size
+ &i_size, // of the buffers in chars
+ PERF_DETAIL_WIZARD, // counter detail level
+ 0);
+
+ if (pdh_fail(pdhStat)) {
+ /* printf("could not enumerate processors (2) error=%d", pdhStat); */
+ error = true;
+ goto end;
+ }
+ //count perf count instances.
+ for (p_count = 0, tmp = instances; *tmp != 0; tmp = &tmp[lstrlen(tmp)+1], p_count++);
+
+ //is this correct for HT?
+ assert(p_count == num_cpus+1);
+
+ //ok, have number of perf counters.
+ multiCounterCPULoad.counters = calloc(p_count, sizeof(HCOUNTER));
+ if (multiCounterCPULoad.counters == NULL) {
+ /* printf("could not allocate memory (2) count=%d", p_count); */
+ error = true;
+ goto end;
+ }
+
+ multiCounterCPULoad.noOfCounters = p_count;
+
+ if (PdhOpenQuery_i(NULL, 0, &multiCounterCPULoad.query.query) != ERROR_SUCCESS) {
+ /* printf("could not create query"); */
+ error = true;
+ goto end;
+ }
+ //now, fetch the counters.
+ for (i = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[lstrlen(tmp)+1], i++) {
+ char counter[2*COUNTER_BUF_SIZE];
+
+ _snprintf(counter, sizeof(counter)-1, "\\%s(%s)\\%s", processor, tmp, time);
+
+ if (PdhAddCounter_i(multiCounterCPULoad.query.query, counter, 0, &multiCounterCPULoad.counters[i]) != ERROR_SUCCESS) {
+ /* printf("error adding processor counter %s", counter); */
+ error = true;
+ goto end;
+ }
+ }
+
+ free(instances);
+ instances = NULL;
+
+ // Query once to initialize the counters needing at least two queries
+ // (like the % CPU usage) to calculate correctly.
+ if (PdhCollectQueryData_i(multiCounterCPULoad.query.query) != ERROR_SUCCESS)
+ error = true;
+
+ end:
+ if (instances != NULL) {
+ free(instances);
+ }
+ if (tmpQuery != NULL) {
+ PdhCloseQuery_i(tmpQuery);
+ }
+ if (error) {
+ int i;
+
+ if (multiCounterCPULoad.counters != NULL) {
+ for (i = 0; i < multiCounterCPULoad.noOfCounters; i++) {
+ if (multiCounterCPULoad.counters[i] != NULL) {
+ PdhRemoveCounter_i(multiCounterCPULoad.counters[i]);
+ }
+ }
+ free(multiCounterCPULoad.counters[i]);
+ }
+ if (multiCounterCPULoad.query.query != NULL) {
+ PdhCloseQuery_i(multiCounterCPULoad.query.query);
+ }
+ memset(&multiCounterCPULoad, 0, sizeof(MultipleCounterQueryS));
+ return -1;
+ }
+ return CONFIG_SUCCESSFUL;
+}
+
+/**
+ * Help function that initializes the PDH process header for the JRockit process.
+ * (You should probably use getProcessPDHHeader() instead!)
+ *
+ * initPDH() must have been run prior to calling this function.
+ *
+ * @param ebuf the error buffer.
+ * @param elen the length of the error buffer.
+ *
+ * @return the PDH instance description corresponding to the JVM process.
+ */
+static char*
+initProcessPDHHeader(void) {
+ static char hotspotheader[2*COUNTER_BUF_SIZE];
+
+ char counter[2*COUNTER_BUF_SIZE];
+ char processes[COUNTER_BUF_SIZE]; //'Process' == #230
+ char pid[COUNTER_BUF_SIZE]; //'ID Process' == 784
+ char module_name[MAX_PATH];
+ PDH_STATUS pdhStat;
+ DWORD c_size = 0, i_size = 0;
+ HQUERY tmpQuery = NULL;
+ int i, myPid = _getpid();
+ BOOL error = false;
+ char *instances, *tmp, *instance_name, *dot_pos;
+
+ tmpQuery = NULL;
+ myPid = _getpid();
+ error = false;
+
+ if (find_name(PDH_PROCESS_IDX, processes, sizeof(processes) - 1) < 0) {
+ return NULL;
+ }
+
+ if (find_name(PDH_ID_PROCESS_IDX, pid, sizeof(pid) - 1) < 0) {
+ return NULL;
+ }
+ //time is same.
+
+ c_size = 0;
+ i_size = 0;
+
+ pdhStat = PdhEnumObjectItems_i (
+ NULL, // reserved
+ NULL, // local machine
+ processes, // object to enumerate
+ NULL, // pass in NULL buffers
+ &c_size, // and 0 length to get
+ NULL, // required size
+ &i_size, // of the buffers in chars
+ PERF_DETAIL_WIZARD, // counter detail level
+ 0);
+
+ //ok, now we have enough to enumerate all processes
+ if (pdh_fail(pdhStat)) {
+ /* printf("Could not enumerate processes (1) error=%d", pdhStat); */
+ return NULL;
+ }
+
+ // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
+ if ((instances = calloc(i_size, 1)) == NULL) {
+ /* printf("Could not allocate memory %d bytes", i_size); */
+ error = true;
+ goto end;
+ }
+
+ c_size = 0;
+
+ pdhStat = PdhEnumObjectItems_i (
+ NULL, // reserved
+ NULL, // local machine
+ processes, // object to enumerate
+ NULL, // pass in NULL buffers
+ &c_size, // and 0 length to get
+ instances, // required size
+ &i_size, // of the buffers in chars
+ PERF_DETAIL_WIZARD, // counter detail level
+ 0);
+
+ // ok, now we have enough to enumerate all processes
+ if (pdh_fail(pdhStat)) {
+ /* printf("Could not enumerate processes (2) error=%d", pdhStat); */
+ error = true;
+ goto end;
+ }
+
+ if (PdhOpenQuery_i(NULL, 0, &tmpQuery) != ERROR_SUCCESS) {
+ /* printf("Could not create temporary query"); */
+ error = true;
+ goto end;
+ }
+
+ // Find our module name and use it to extract the instance name used by PDH
+ if (GetModuleFileName(NULL, module_name, MAX_PATH) >= MAX_PATH-1) {
+ /* printf("Module name truncated"); */
+ error = true;
+ goto end;
+ }
+ instance_name = strrchr(module_name, '\\'); //drop path
+ instance_name++; //skip slash
+ dot_pos = strchr(instance_name, '.'); //drop .exe
+ dot_pos[0] = '\0';
+
+ //now, fetch the counters.
+ for (tmp = instances; *tmp != 0 && !error; tmp = &tmp[lstrlen(tmp)+1]) {
+ HCOUNTER hc = NULL;
+ BOOL done = false;
+
+ // Skip until we find our own process name
+ if (strcmp(tmp, instance_name) != 0) {
+ continue;
+ }
+
+ // iterate over all instance indexes and try to find our own pid
+ for (i = 0; !done && !error; i++){
+ PDH_STATUS res;
+ _snprintf(counter, sizeof(counter)-1, "\\%s(%s#%d)\\%s", processes, tmp, i, pid);
+
+ if (PdhAddCounter_i(tmpQuery, counter, 0, &hc) != ERROR_SUCCESS) {
+ /* printf("Failed to create process id query"); */
+ error = true;
+ goto end;
+ }
+
+ res = PdhCollectQueryData_i(tmpQuery);
+
+ if (res == PDH_INVALID_HANDLE) {
+ /* printf("Failed to query process id"); */
+ res = -1;
+ done = true;
+ } else if (res == PDH_NO_DATA) {
+ done = true;
+ } else {
+ PDH_FMT_COUNTERVALUE cv;
+
+ PdhGetFormattedCounterValue_i(hc, PDH_FMT_LONG, NULL, &cv);
+ /*
+ * This check seems to be needed for Win2k SMP boxes, since
+ * they for some reason don't return PDH_NO_DATA for non existing
+ * counters.
+ */
+ if (cv.CStatus != PDH_CSTATUS_VALID_DATA) {
+ done = true;
+ } else if (cv.longValue == myPid) {
+ _snprintf(hotspotheader, sizeof(hotspotheader)-1, "\\%s(%s#%d)\0", processes, tmp, i);
+ PdhRemoveCounter_i(hc);
+ goto end;
+ }
+ }
+ PdhRemoveCounter_i(hc);
+ }
+ }
+ end:
+ if (instances != NULL) {
+ free(instances);
+ }
+ if (tmpQuery != NULL) {
+ PdhCloseQuery_i(tmpQuery);
+ }
+ if (error) {
+ return NULL;
+ }
+ return hotspotheader;
+}
+
+/**
+ * Returns the PDH string prefix identifying the HotSpot process. Use this prefix when getting
+ * counters from the PDH process object representing HotSpot.
+ *
+ * Note: this call may take some time to complete.
+ *
+ * @param ebuf error buffer.
+ * @param elen error buffer length.
+ *
+ * @return the header to be used when retrieving PDH counters from the HotSpot process.
+ * Will return NULL if the call failed.
+ */
+static char *
+getProcessPDHHeader(void) {
+ static char *processHeader = NULL;
+
+ EnterCriticalSection(&processHeaderLock); {
+ if (processHeader == NULL) {
+ processHeader = initProcessPDHHeader();
+ }
+ } LeaveCriticalSection(&processHeaderLock);
+ return processHeader;
+}
+
+int perfInit(void);
+
+double
+perfGetCPULoad(int which)
+{
+ PDH_FMT_COUNTERVALUE cv;
+ HCOUNTER c;
+
+ if (perfInit() < 0) {
+ // warn?
+ return -1.0;
+ }
+
+ if (multiCounterCPULoad.query.query == NULL) {
+ // warn?
+ return -1.0;
+ }
+
+ if (which == -1) {
+ c = multiCounterCPULoad.counters[multiCounterCPULoad.noOfCounters - 1];
+ } else {
+ if (which < multiCounterCPULoad.noOfCounters) {
+ c = multiCounterCPULoad.counters[which];
+ } else {
+ return -1.0;
+ }
+ }
+ if (getPerformanceData(&multiCounterCPULoad.query, c, &cv, PDH_FMT_DOUBLE ) == CONFIG_SUCCESSFUL) {
+ return cv.doubleValue / 100;
+ }
+ return -1.0;
+}
+
+double
+perfGetProcessLoad(void)
+{
+ PDH_FMT_COUNTERVALUE cv;
+
+ if (perfInit() < 0) {
+ // warn?
+ return -1.0;
+ }
+
+ if (cntProcLoad.query.query == NULL) {
+ // warn?
+ return -1.0;
+ }
+
+ if (getPerformanceData(&cntProcLoad.query, cntProcLoad.counter, &cv, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100) == CONFIG_SUCCESSFUL) {
+ double d = cv.doubleValue / cpuFactor;
+ d = min(1, d);
+ d = max(0, d);
+ return d;
+ }
+ return -1.0;
+}
+
+/**
+ * Helper to initialize the PDH library. Loads the library and sets up the functions.
+ * Note that once loaded, we will never unload the PDH library.
+ *
+ * @return CONFIG_SUCCESSFUL if successful, negative on failure.
+ */
+int
+perfInit(void) {
+ static HMODULE h;
+ static BOOL running, inited;
+
+ int error;
+
+ if (running) {
+ return CONFIG_SUCCESSFUL;
+ }
+
+ error = CONFIG_SUCCESSFUL;
+
+ // this is double checked locking again, but we try to bypass the worst by
+ // implicit membar at end of lock.
+ EnterCriticalSection(&initializationLock); {
+ if (!inited) {
+ char buf[64] = "";
+ SYSTEM_INFO si;
+
+ // CMH. But windows will not care about our affinity when giving
+ // us measurements. Need the real, raw num cpus.
+
+ GetSystemInfo(&si);
+ num_cpus = si.dwNumberOfProcessors;
+ // Initialize the denominator for the jvm load calculations
+ cpuFactor = num_cpus * 100;
+
+ /**
+ * Do this dynamically, so we don't fail to start on systems without pdh.
+ */
+ if ((h = LoadLibrary("pdh.dll")) == NULL) {
+ /* printf("Could not load pdh.dll (%d)", GetLastError()); */
+ error = -2;
+ } else if (get_functions(h, buf, sizeof(buf)) < 0) {
+ FreeLibrary(h);
+ h = NULL;
+ error = -2;
+ /* printf("Failed to init pdh functions: %s.\n", buf); */
+ } else {
+ if (initProcessorCounters() != 0) {
+ /* printf("Failed to init system load counters.\n"); */
+ } else if (initProcLoadCounter() != 0) {
+ /* printf("Failed to init process load counter.\n"); */
+ } else if (initProcSystemLoadCounter() != 0) {
+ /* printf("Failed to init process system load counter.\n"); */
+ } else {
+ inited = true;
+ }
+ }
+ }
+ } LeaveCriticalSection(&initializationLock);
+
+ if (inited && error == CONFIG_SUCCESSFUL) {
+ running = true;
+ }
+
+ return error;
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getSystemCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ return perfGetCPULoad(-1);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_sun_management_OperatingSystemImpl_getProcessCpuLoad
+(JNIEnv *env, jobject dummy)
+{
+ return perfGetProcessLoad();
+}