Merge jdk7-b142
authorschien
Wed, 11 May 2011 18:52:46 -0700
changeset 4213312612e89ece
parent 4212 caed82420c5d
parent 4196 0f4a9ce78cf9
child 4214 2e430b88b949
child 4219 cb71f8f695f5
Merge
     1.1 --- a/make/java/management/Makefile	Wed May 11 14:12:50 2011 -0700
     1.2 +++ b/make/java/management/Makefile	Wed May 11 18:52:46 2011 -0700
     1.3 @@ -63,6 +63,20 @@
     1.4  FILES_c     +=  UnixOperatingSystem_md.c
     1.5  
     1.6  FILES_export +=	com/sun/management/UnixOperatingSystem.java
     1.7 +
     1.8 +ifeq ($(PLATFORM),solaris)
     1.9 +
    1.10 +FILES_c     += SolarisOperatingSystem.c
    1.11 +OTHER_LDLIBS += -lkstat
    1.12 +
    1.13 +endif # PLATFORM solaris
    1.14 +
    1.15 +ifeq ($(PLATFORM),linux)
    1.16 +
    1.17 +FILES_c     += LinuxOperatingSystem.c
    1.18 +
    1.19 +endif # PLATFORM linux
    1.20 +
    1.21  endif # PLATFORM
    1.22  
    1.23  #
     2.1 --- a/make/java/management/mapfile-vers	Wed May 11 14:12:50 2011 -0700
     2.2 +++ b/make/java/management/mapfile-vers	Wed May 11 18:52:46 2011 -0700
     2.3 @@ -32,7 +32,9 @@
     2.4  	    Java_com_sun_management_UnixOperatingSystem_getFreeSwapSpaceSize;
     2.5  	    Java_com_sun_management_UnixOperatingSystem_getMaxFileDescriptorCount;
     2.6  	    Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount;
     2.7 +	    Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad;
     2.8  	    Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime;
     2.9 +	    Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad;
    2.10  	    Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize;
    2.11  	    Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
    2.12  	    Java_com_sun_management_UnixOperatingSystem_initialize;
     3.1 --- a/src/share/classes/com/sun/management/OperatingSystemMXBean.java	Wed May 11 14:12:50 2011 -0700
     3.2 +++ b/src/share/classes/com/sun/management/OperatingSystemMXBean.java	Wed May 11 18:52:46 2011 -0700
     3.3 @@ -92,4 +92,39 @@
     3.4       * @return the total amount of physical memory in  bytes.
     3.5       */
     3.6      public long getTotalPhysicalMemorySize();
     3.7 +
     3.8 +    /**
     3.9 +     * Returns the "recent cpu usage" for the whole system. This value is a
    3.10 +     * double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs
    3.11 +     * were idle during the recent period of time observed, while a value
    3.12 +     * of 1.0 means that all CPUs were actively running 100% of the time
    3.13 +     * during the recent period being observed. All values betweens 0.0 and
    3.14 +     * 1.0 are possible depending of the activities going on in the system.
    3.15 +     * If the system recent cpu usage is not available, the method returns a
    3.16 +     * negative value.
    3.17 +     *
    3.18 +     * @return the "recent cpu usage" for the whole system; a negative
    3.19 +     * value if not available.
    3.20 +     * @since   1.7
    3.21 +     */
    3.22 +    public double getSystemCpuLoad();
    3.23 +
    3.24 +    /**
    3.25 +     * Returns the "recent cpu usage" for the Java Virtual Machine process.
    3.26 +     * This value is a double in the [0.0,1.0] interval. A value of 0.0 means
    3.27 +     * that none of the CPUs were running threads from the JVM process during
    3.28 +     * the recent period of time observed, while a value of 1.0 means that all
    3.29 +     * CPUs were actively running threads from the JVM 100% of the time
    3.30 +     * during the recent period being observed. Threads from the JVM include
    3.31 +     * the application threads as well as the JVM internal threads. All values
    3.32 +     * betweens 0.0 and 1.0 are possible depending of the activities going on
    3.33 +     * in the JVM process and the whole system. If the Java Virtual Machine
    3.34 +     * recent CPU usage is not available, the method returns a negative value.
    3.35 +     *
    3.36 +     * @return the "recent cpu usage" for the Java Virtual Machine process;
    3.37 +     * a negative value if not available.
    3.38 +     * @since   1.7
    3.39 +     */
    3.40 +    public double getProcessCpuLoad();
    3.41 +
    3.42  }
     4.1 --- a/src/solaris/classes/com/sun/management/UnixOperatingSystem.java	Wed May 11 14:12:50 2011 -0700
     4.2 +++ b/src/solaris/classes/com/sun/management/UnixOperatingSystem.java	Wed May 11 18:52:46 2011 -0700
     4.3 @@ -50,6 +50,8 @@
     4.4      public native long getTotalPhysicalMemorySize();
     4.5      public native long getOpenFileDescriptorCount();
     4.6      public native long getMaxFileDescriptorCount();
     4.7 +    public native double getSystemCpuLoad();
     4.8 +    public native double getProcessCpuLoad();
     4.9  
    4.10      static {
    4.11          initialize();
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/solaris/native/com/sun/management/LinuxOperatingSystem.c	Wed May 11 18:52:46 2011 -0700
     5.3 @@ -0,0 +1,332 @@
     5.4 +/*
     5.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Oracle designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Oracle in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.25 + * or visit www.oracle.com if you need additional information or have any
    5.26 + * questions.
    5.27 + */
    5.28 +
    5.29 +#include <stdio.h>
    5.30 +#include <stdint.h>
    5.31 +#include <stdarg.h>
    5.32 +#include <unistd.h>
    5.33 +#include <errno.h>
    5.34 +#include <string.h>
    5.35 +#include <sys/resource.h>
    5.36 +#include <sys/types.h>
    5.37 +#include <dirent.h>
    5.38 +#include <stdlib.h>
    5.39 +#include <dlfcn.h>
    5.40 +#include <pthread.h>
    5.41 +#include "com_sun_management_UnixOperatingSystem.h"
    5.42 +
    5.43 +struct ticks {
    5.44 +    uint64_t  used;
    5.45 +    uint64_t  usedKernel;
    5.46 +    uint64_t  total;
    5.47 +};
    5.48 +
    5.49 +typedef struct ticks ticks;
    5.50 +
    5.51 +typedef enum {
    5.52 +    CPU_LOAD_VM_ONLY,
    5.53 +    CPU_LOAD_GLOBAL,
    5.54 +} CpuLoadTarget;
    5.55 +
    5.56 +static struct perfbuf {
    5.57 +    int   nProcs;
    5.58 +    ticks jvmTicks;
    5.59 +    ticks cpuTicks;
    5.60 +    ticks *cpus;
    5.61 +} counters;
    5.62 +
    5.63 +#define DEC_64 "%lld"
    5.64 +
    5.65 +static void next_line(FILE *f) {
    5.66 +    while (fgetc(f) != '\n');
    5.67 +}
    5.68 +
    5.69 +/**
    5.70 + * Return the total number of ticks since the system was booted.
    5.71 + * If the usedTicks parameter is not NULL, it will be filled with
    5.72 + * the number of ticks spent on actual processes (user, system or
    5.73 + * nice processes) since system boot. Note that this is the total number
    5.74 + * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
    5.75 + * n times the number of ticks that has passed in clock time.
    5.76 + *
    5.77 + * Returns a negative value if the reading of the ticks failed.
    5.78 + */
    5.79 +static int get_totalticks(int which, ticks *pticks) {
    5.80 +    FILE         *fh;
    5.81 +    uint64_t        userTicks, niceTicks, systemTicks, idleTicks;
    5.82 +    int             n;
    5.83 +
    5.84 +    if((fh = fopen("/proc/stat", "r")) == NULL) {
    5.85 +        return -1;
    5.86 +    }
    5.87 +
    5.88 +    n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64,
    5.89 +           &userTicks, &niceTicks, &systemTicks, &idleTicks);
    5.90 +
    5.91 +    // Move to next line
    5.92 +    next_line(fh);
    5.93 +
    5.94 +    //find the line for requested cpu faster to just iterate linefeeds?
    5.95 +    if (which != -1) {
    5.96 +        int i;
    5.97 +        for (i = 0; i < which; i++) {
    5.98 +            if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) {
    5.99 +                fclose(fh);
   5.100 +                return -2;
   5.101 +            }
   5.102 +            next_line(fh);
   5.103 +        }
   5.104 +        n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n",
   5.105 +           &userTicks, &niceTicks, &systemTicks, &idleTicks);
   5.106 +    }
   5.107 +
   5.108 +    fclose(fh);
   5.109 +    if (n != 4) {
   5.110 +        return -2;
   5.111 +    }
   5.112 +
   5.113 +    pticks->used       = userTicks + niceTicks;
   5.114 +    pticks->usedKernel = systemTicks;
   5.115 +    pticks->total      = userTicks + niceTicks + systemTicks + idleTicks;
   5.116 +
   5.117 +    return 0;
   5.118 +}
   5.119 +
   5.120 +static int vread_statdata(const char *procfile, const char *fmt, va_list args) {
   5.121 +    FILE    *f;
   5.122 +    int     n;
   5.123 +    char     buf[2048];
   5.124 +
   5.125 +    if ((f = fopen(procfile, "r")) == NULL) {
   5.126 +        return -1;
   5.127 +    }
   5.128 +
   5.129 +    if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
   5.130 +    char *tmp;
   5.131 +
   5.132 +    buf[n-1] = '\0';
   5.133 +    /** skip through pid and exec name. the exec name _could be wacky_ (renamed) and
   5.134 +     *  make scanf go mupp.
   5.135 +     */
   5.136 +    if ((tmp = strrchr(buf, ')')) != NULL) {
   5.137 +        // skip the ')' and the following space but check that the buffer is long enough
   5.138 +        tmp += 2;
   5.139 +        if (tmp < buf + n) {
   5.140 +        n = vsscanf(tmp, fmt, args);
   5.141 +        }
   5.142 +    }
   5.143 +    }
   5.144 +
   5.145 +    fclose(f);
   5.146 +
   5.147 +    return n;
   5.148 +}
   5.149 +
   5.150 +static int read_statdata(const char *procfile, const char *fmt, ...) {
   5.151 +    int       n;
   5.152 +    va_list args;
   5.153 +
   5.154 +    va_start(args, fmt);
   5.155 +    n = vread_statdata(procfile, fmt, args);
   5.156 +    va_end(args);
   5.157 +    return n;
   5.158 +}
   5.159 +
   5.160 +/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
   5.161 +static int read_ticks(const char *procfile, uint64_t *userTicks, uint64_t *systemTicks) {
   5.162 +    return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "DEC_64" "DEC_64,
   5.163 +             userTicks, systemTicks
   5.164 +             );
   5.165 +}
   5.166 +
   5.167 +/**
   5.168 + * Return the number of ticks spent in any of the processes belonging
   5.169 + * to the JVM on any CPU.
   5.170 + */
   5.171 +static int get_jvmticks(ticks *pticks) {
   5.172 +    uint64_t userTicks;
   5.173 +    uint64_t systemTicks;
   5.174 +
   5.175 +    if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) {
   5.176 +        return -1;
   5.177 +    }
   5.178 +
   5.179 +    // get the total
   5.180 +    if (get_totalticks(-1, pticks) < 0) {
   5.181 +        return -1;
   5.182 +    }
   5.183 +
   5.184 +    pticks->used       = userTicks;
   5.185 +    pticks->usedKernel = systemTicks;
   5.186 +
   5.187 +    return 0;
   5.188 +}
   5.189 +
   5.190 +/**
   5.191 + * This method must be called first, before any data can be gathererd.
   5.192 + */
   5.193 +int perfInit() {
   5.194 +    static int initialized=1;
   5.195 +
   5.196 +    if (!initialized) {
   5.197 +        int  i;
   5.198 +
   5.199 +        int n = sysconf(_SC_NPROCESSORS_ONLN);
   5.200 +        if (n <= 0) {
   5.201 +            n = 1;
   5.202 +        }
   5.203 +
   5.204 +        counters.cpus = calloc(n,sizeof(ticks));
   5.205 +        if (counters.cpus != NULL)  {
   5.206 +            // For the CPU load
   5.207 +            get_totalticks(-1, &counters.cpuTicks);
   5.208 +
   5.209 +            for (i = 0; i < n; i++) {
   5.210 +                get_totalticks(i, &counters.cpus[i]);
   5.211 +            }
   5.212 +            // For JVM load
   5.213 +            get_jvmticks(&counters.jvmTicks);
   5.214 +            initialized = 1;
   5.215 +        }
   5.216 +    }
   5.217 +
   5.218 +    return initialized ? 0 : -1;
   5.219 +}
   5.220 +
   5.221 +#define MAX(a,b) (a>b?a:b)
   5.222 +#define MIN(a,b) (a<b?a:b)
   5.223 +
   5.224 +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
   5.225 +
   5.226 +/**
   5.227 + * Return the load of the CPU as a double. 1.0 means the CPU process uses all
   5.228 + * available time for user or system processes, 0.0 means the CPU uses all time
   5.229 + * being idle.
   5.230 + *
   5.231 + * Returns a negative value if there is a problem in determining the CPU load.
   5.232 + */
   5.233 +
   5.234 +static double get_cpuload_internal(int which, double *pkernelLoad, CpuLoadTarget target) {
   5.235 +    uint64_t udiff, kdiff, tdiff;
   5.236 +    ticks *pticks, tmp;
   5.237 +    double user_load = -1.0;
   5.238 +    int failed = 0;
   5.239 +
   5.240 +    *pkernelLoad = 0.0;
   5.241 +
   5.242 +    pthread_mutex_lock(&lock);
   5.243 +
   5.244 +    if(perfInit() == 0) {
   5.245 +
   5.246 +        if (target == CPU_LOAD_VM_ONLY) {
   5.247 +            pticks = &counters.jvmTicks;
   5.248 +        } else if (which == -1) {
   5.249 +            pticks = &counters.cpuTicks;
   5.250 +        } else {
   5.251 +            pticks = &counters.cpus[which];
   5.252 +        }
   5.253 +
   5.254 +        tmp = *pticks;
   5.255 +
   5.256 +        if (target == CPU_LOAD_VM_ONLY) {
   5.257 +            if (get_jvmticks(pticks) != 0) {
   5.258 +                failed = 1;
   5.259 +            }
   5.260 +        } else if (get_totalticks(which, pticks) < 0) {
   5.261 +            failed = 1;
   5.262 +        }
   5.263 +
   5.264 +        if(!failed) {
   5.265 +            // seems like we sometimes end up with less kernel ticks when
   5.266 +            // reading /proc/self/stat a second time, timing issue between cpus?
   5.267 +            if (pticks->usedKernel < tmp.usedKernel) {
   5.268 +                kdiff = 0;
   5.269 +            } else {
   5.270 +                kdiff = pticks->usedKernel - tmp.usedKernel;
   5.271 +            }
   5.272 +            tdiff = pticks->total - tmp.total;
   5.273 +            udiff = pticks->used - tmp.used;
   5.274 +
   5.275 +            if (tdiff == 0) {
   5.276 +                user_load = 0;
   5.277 +            } else {
   5.278 +                if (tdiff < (udiff + kdiff)) {
   5.279 +                    tdiff = udiff + kdiff;
   5.280 +                }
   5.281 +                *pkernelLoad = (kdiff / (double)tdiff);
   5.282 +                // BUG9044876, normalize return values to sane values
   5.283 +                *pkernelLoad = MAX(*pkernelLoad, 0.0);
   5.284 +                *pkernelLoad = MIN(*pkernelLoad, 1.0);
   5.285 +
   5.286 +                user_load = (udiff / (double)tdiff);
   5.287 +                user_load = MAX(user_load, 0.0);
   5.288 +                user_load = MIN(user_load, 1.0);
   5.289 +            }
   5.290 +        }
   5.291 +    }
   5.292 +    pthread_mutex_unlock(&lock);
   5.293 +    return user_load;
   5.294 +}
   5.295 +
   5.296 +double get_cpu_load(int which) {
   5.297 +    double u, s;
   5.298 +    u = get_cpuload_internal(which, &s, CPU_LOAD_GLOBAL);
   5.299 +    if (u < 0) {
   5.300 +        return -1.0;
   5.301 +    }
   5.302 +    // Cap total systemload to 1.0
   5.303 +    return MIN((u + s), 1.0);
   5.304 +}
   5.305 +
   5.306 +double get_process_load() {
   5.307 +    double u, s;
   5.308 +    u = get_cpuload_internal(-1, &s, CPU_LOAD_VM_ONLY);
   5.309 +    if (u < 0) {
   5.310 +        return -1.0;
   5.311 +    }
   5.312 +    return u + s;
   5.313 +}
   5.314 +
   5.315 +JNIEXPORT jdouble JNICALL
   5.316 +Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
   5.317 +(JNIEnv *env, jobject dummy)
   5.318 +{
   5.319 +    if(perfInit() == 0) {
   5.320 +        return get_cpu_load(-1);
   5.321 +    } else {
   5.322 +        return -1.0;
   5.323 +    }
   5.324 +}
   5.325 +
   5.326 +JNIEXPORT jdouble JNICALL
   5.327 +Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
   5.328 +(JNIEnv *env, jobject dummy)
   5.329 +{
   5.330 +    if(perfInit() == 0) {
   5.331 +        return get_process_load();
   5.332 +    } else {
   5.333 +        return -1.0;
   5.334 +    }
   5.335 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/solaris/native/com/sun/management/SolarisOperatingSystem.c	Wed May 11 18:52:46 2011 -0700
     6.3 @@ -0,0 +1,241 @@
     6.4 +/*
     6.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +
    6.29 +#include <fcntl.h>
    6.30 +#include <kstat.h>
    6.31 +#include <procfs.h>
    6.32 +#include <unistd.h>
    6.33 +#include <stdlib.h>
    6.34 +#include <stdio.h>
    6.35 +#include <string.h>
    6.36 +#include <sys/sysinfo.h>
    6.37 +#include <sys/lwp.h>
    6.38 +#include <pthread.h>
    6.39 +#include <utmpx.h>
    6.40 +#include <dlfcn.h>
    6.41 +#include <sys/loadavg.h>
    6.42 +#include <jni.h>
    6.43 +#include "jvm.h"
    6.44 +#include "com_sun_management_UnixOperatingSystem.h"
    6.45 +
    6.46 +typedef struct {
    6.47 +    kstat_t *kstat;
    6.48 +    uint64_t  last_idle;
    6.49 +    uint64_t  last_total;
    6.50 +    double  last_ratio;
    6.51 +} cpuload_t;
    6.52 +
    6.53 +static cpuload_t   *cpu_loads = NULL;
    6.54 +static unsigned int num_cpus;
    6.55 +static kstat_ctl_t *kstat_ctrl = NULL;
    6.56 +
    6.57 +static void map_cpu_kstat_counters() {
    6.58 +    kstat_t     *kstat;
    6.59 +    int          i;
    6.60 +
    6.61 +    // Get number of CPU(s)
    6.62 +    if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
    6.63 +        num_cpus = 1;
    6.64 +    }
    6.65 +
    6.66 +    // Data structure for saving CPU load
    6.67 +    if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
    6.68 +        return;
    6.69 +    }
    6.70 +
    6.71 +    // Get kstat cpu_stat counters for every CPU
    6.72 +    // (loop over kstat to find our cpu_stat(s)
    6.73 +    i = 0;
    6.74 +    for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
    6.75 +        if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
    6.76 +
    6.77 +            if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
    6.78 +            // Failed to initialize kstat for this CPU so ignore it
    6.79 +            continue;
    6.80 +            }
    6.81 +
    6.82 +            if (i == num_cpus) {
    6.83 +            // Found more cpu_stats than reported CPUs
    6.84 +            break;
    6.85 +            }
    6.86 +
    6.87 +            cpu_loads[i++].kstat = kstat;
    6.88 +        }
    6.89 +    }
    6.90 +}
    6.91 +
    6.92 +static int init_cpu_kstat_counters() {
    6.93 +    static int initialized = 0;
    6.94 +
    6.95 +    // Concurrence in this method is prevented by the lock in
    6.96 +    // the calling method get_cpu_load();
    6.97 +    if(!initialized) {
    6.98 +        if ((kstat_ctrl = kstat_open()) != NULL) {
    6.99 +            map_cpu_kstat_counters();
   6.100 +            initialized = 1;
   6.101 +        }
   6.102 +    }
   6.103 +    return initialized ? 0 : -1;
   6.104 +}
   6.105 +
   6.106 +static void update_cpu_kstat_counters() {
   6.107 +    if(kstat_chain_update(kstat_ctrl) != 0) {
   6.108 +        free(cpu_loads);
   6.109 +        map_cpu_kstat_counters();
   6.110 +    }
   6.111 +}
   6.112 +
   6.113 +int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
   6.114 +    if (load->kstat == NULL) {
   6.115 +        // no handle.
   6.116 +        return -1;
   6.117 +    }
   6.118 +    if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
   6.119 +        //  disabling for now, a kstat chain update is likely to happen next time
   6.120 +        load->kstat = NULL;
   6.121 +        return -1;
   6.122 +    }
   6.123 +    return 0;
   6.124 +}
   6.125 +
   6.126 +double get_single_cpu_load(unsigned int n) {
   6.127 +    cpuload_t  *load;
   6.128 +    cpu_stat_t  cpu_stat;
   6.129 +    uint_t     *usage;
   6.130 +    uint64_t          c_idle;
   6.131 +    uint64_t          c_total;
   6.132 +    uint64_t          d_idle;
   6.133 +    uint64_t          d_total;
   6.134 +    int           i;
   6.135 +
   6.136 +    if (n >= num_cpus) {
   6.137 +        return -1.0;
   6.138 +    }
   6.139 +
   6.140 +    load = &cpu_loads[n];
   6.141 +    if (read_cpustat(load, &cpu_stat) < 0) {
   6.142 +        return -1.0;
   6.143 +    }
   6.144 +
   6.145 +    usage   = cpu_stat.cpu_sysinfo.cpu;
   6.146 +    c_idle  = usage[CPU_IDLE];
   6.147 +
   6.148 +    for (c_total = 0, i = 0; i < CPU_STATES; i++) {
   6.149 +        c_total += usage[i];
   6.150 +    }
   6.151 +
   6.152 +    // Calculate diff against previous snapshot
   6.153 +    d_idle  = c_idle - load->last_idle;
   6.154 +    d_total = c_total - load->last_total;
   6.155 +
   6.156 +    /** update if weve moved */
   6.157 +    if (d_total > 0) {
   6.158 +        // Save current values for next time around
   6.159 +        load->last_idle  = c_idle;
   6.160 +        load->last_total = c_total;
   6.161 +        load->last_ratio = (double) (d_total - d_idle) / d_total;
   6.162 +    }
   6.163 +
   6.164 +    return load->last_ratio;
   6.165 +}
   6.166 +
   6.167 +int get_info(const char *path, void *info, size_t s, off_t o) {
   6.168 +    int fd;
   6.169 +    int ret = 0;
   6.170 +    if ((fd = open(path, O_RDONLY)) < 0) {
   6.171 +        return -1;
   6.172 +    }
   6.173 +    if (pread(fd, info, s, o) != s) {
   6.174 +        ret = -1;
   6.175 +    }
   6.176 +    close(fd);
   6.177 +    return ret;
   6.178 +}
   6.179 +
   6.180 +#define MIN(a, b)           ((a < b) ? a : b)
   6.181 +
   6.182 +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
   6.183 +
   6.184 +/**
   6.185 + * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
   6.186 + */
   6.187 +double  get_cpu_load(int which) {
   6.188 +    double load =.0;
   6.189 +
   6.190 +    pthread_mutex_lock(&lock);
   6.191 +    if(init_cpu_kstat_counters()==0) {
   6.192 +
   6.193 +        update_cpu_kstat_counters();
   6.194 +
   6.195 +        if (which == -1) {
   6.196 +            unsigned int i;
   6.197 +            double       t;
   6.198 +
   6.199 +            for (t = .0, i = 0; i < num_cpus; i++) {
   6.200 +                t += get_single_cpu_load(i);
   6.201 +            }
   6.202 +
   6.203 +            // Cap total systemload to 1.0
   6.204 +            load = MIN((t / num_cpus), 1.0);
   6.205 +        } else {
   6.206 +            load = MIN(get_single_cpu_load(which), 1.0);
   6.207 +        }
   6.208 +    } else {
   6.209 +        load = -1.0;
   6.210 +    }
   6.211 +    pthread_mutex_unlock(&lock);
   6.212 +
   6.213 +    return load;
   6.214 +}
   6.215 +
   6.216 +/**
   6.217 + * Return the cpu load (0-1) for the current process (i.e the JVM)
   6.218 + * or -1.0 if the get_info() call failed
   6.219 + */
   6.220 +double get_process_load(void) {
   6.221 +    psinfo_t info;
   6.222 +
   6.223 +    // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
   6.224 +    // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
   6.225 +    if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
   6.226 +        return (double) info.pr_pctcpu / 0x8000;
   6.227 +    }
   6.228 +    return -1.0;
   6.229 +}
   6.230 +
   6.231 +JNIEXPORT jdouble JNICALL
   6.232 +Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
   6.233 +(JNIEnv *env, jobject dummy)
   6.234 +{
   6.235 +    return get_cpu_load(-1);
   6.236 +}
   6.237 +
   6.238 +JNIEXPORT jdouble JNICALL
   6.239 +Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
   6.240 +(JNIEnv *env, jobject dummy)
   6.241 +{
   6.242 +    return get_process_load();
   6.243 +}
   6.244 +
     7.1 --- a/src/windows/classes/com/sun/management/OperatingSystem.java	Wed May 11 14:12:50 2011 -0700
     7.2 +++ b/src/windows/classes/com/sun/management/OperatingSystem.java	Wed May 11 18:52:46 2011 -0700
     7.3 @@ -58,6 +58,8 @@
     7.4      public native long getProcessCpuTime();
     7.5      public native long getFreePhysicalMemorySize();
     7.6      public native long getTotalPhysicalMemorySize();
     7.7 +    public native double getSystemCpuLoad();
     7.8 +    public native double getProcessCpuLoad();
     7.9  
    7.10      static {
    7.11          initialize();
     8.1 --- a/src/windows/native/com/sun/management/OperatingSystem_md.c	Wed May 11 14:12:50 2011 -0700
     8.2 +++ b/src/windows/native/com/sun/management/OperatingSystem_md.c	Wed May 11 18:52:46 2011 -0700
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -34,9 +34,27 @@
    8.11  #include <errno.h>
    8.12  #include <stdlib.h>
    8.13  
    8.14 +#include <malloc.h>
    8.15 +#pragma warning (push,0)
    8.16 +#include <windows.h>
    8.17 +#pragma warning (pop)
    8.18 +#include <stdio.h>
    8.19 +#include <time.h>
    8.20 +#include <stdint.h>
    8.21 +#include <assert.h>
    8.22 +
    8.23 +/* Disable warnings due to broken header files from Microsoft... */
    8.24 +#pragma warning(push, 3)
    8.25 +#include <pdh.h>
    8.26 +#include <pdhmsg.h>
    8.27 +#include <process.h>
    8.28 +#pragma warning(pop)
    8.29 +
    8.30  typedef unsigned __int32 juint;
    8.31  typedef unsigned __int64 julong;
    8.32  
    8.33 +typedef enum boolean_values { false=0, true=1};
    8.34 +
    8.35  static void set_low(jlong* value, jint low) {
    8.36      *value &= (jlong)0xffffffff << 32;
    8.37      *value |= (jlong)(julong)(juint)low;
    8.38 @@ -56,11 +74,14 @@
    8.39  
    8.40  static HANDLE main_process;
    8.41  
    8.42 +int perfiInit(void);
    8.43 +
    8.44  JNIEXPORT void JNICALL
    8.45  Java_com_sun_management_OperatingSystem_initialize
    8.46    (JNIEnv *env, jclass cls)
    8.47  {
    8.48      main_process = GetCurrentProcess();
    8.49 +     perfiInit();
    8.50  }
    8.51  
    8.52  JNIEXPORT jlong JNICALL
    8.53 @@ -132,3 +153,788 @@
    8.54      GlobalMemoryStatus(&ms);
    8.55      return ms.dwTotalPhys;
    8.56  }
    8.57 +
    8.58 +// Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer.
    8.59 +// Let's just ignore it, since we make sure we have enough buffer anyway.
    8.60 +static int
    8.61 +pdh_fail(PDH_STATUS pdhStat) {
    8.62 +    return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA;
    8.63 +}
    8.64 +
    8.65 +// INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
    8.66 +//       http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
    8.67 +// The index value for the base system counters and objects like processor,
    8.68 +// process, thread, memory, and so forth are always the same irrespective
    8.69 +// of the localized version of the operating system or service pack installed.
    8.70 +#define PDH_PROCESSOR_IDX        ((DWORD) 238)
    8.71 +#define PDH_PROCESSOR_TIME_IDX        ((DWORD)   6)
    8.72 +#define PDH_PRIV_PROCESSOR_TIME_IDX ((DWORD) 144)
    8.73 +#define PDH_PROCESS_IDX            ((DWORD) 230)
    8.74 +#define PDH_ID_PROCESS_IDX        ((DWORD) 784)
    8.75 +#define PDH_CONTEXT_SWITCH_RATE_IDX ((DWORD) 146)
    8.76 +#define PDH_SYSTEM_IDX            ((DWORD)   2)
    8.77 +#define PDH_VIRTUAL_BYTES_IDX        ((DWORD) 174)
    8.78 +
    8.79 +typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)(
    8.80 +                           HQUERY      hQuery,
    8.81 +                           LPCSTR      szFullCounterPath,
    8.82 +                           DWORD       dwUserData,
    8.83 +                           HCOUNTER    *phCounter
    8.84 +                           );
    8.85 +typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)(
    8.86 +                          LPCWSTR     szDataSource,
    8.87 +                          DWORD       dwUserData,
    8.88 +                          HQUERY      *phQuery
    8.89 +                          );
    8.90 +typedef DWORD (WINAPI *PdhCloseQueryFunc)(
    8.91 +                      HQUERY      hQuery
    8.92 +                      );
    8.93 +typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)(
    8.94 +                             HQUERY      hQuery
    8.95 +                             );
    8.96 +typedef DWORD (WINAPI *PdhGetFormattedCounterValueFunc)(
    8.97 +                            HCOUNTER                hCounter,
    8.98 +                            DWORD                   dwFormat,
    8.99 +                            LPDWORD                 lpdwType,
   8.100 +                            PPDH_FMT_COUNTERVALUE   pValue
   8.101 +                            );
   8.102 +typedef PDH_STATUS (WINAPI *PdhEnumObjectItemsFunc)(
   8.103 +                            LPCTSTR    szDataSource,
   8.104 +                            LPCTSTR    szMachineName,
   8.105 +                            LPCTSTR    szObjectName,
   8.106 +                            LPTSTR     mszCounterList,
   8.107 +                            LPDWORD    pcchCounterListLength,
   8.108 +                            LPTSTR     mszInstanceList,
   8.109 +                            LPDWORD    pcchInstanceListLength,
   8.110 +                            DWORD      dwDetailLevel,
   8.111 +                            DWORD      dwFlags
   8.112 +                            );
   8.113 +typedef PDH_STATUS (WINAPI *PdhRemoveCounterFunc)(
   8.114 +                          HCOUNTER  hCounter
   8.115 +                          );
   8.116 +typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndexFunc)(
   8.117 +                              LPCSTR  szMachineName,
   8.118 +                              DWORD   dwNameIndex,
   8.119 +                              LPSTR   szNameBuffer,
   8.120 +                              LPDWORD pcchNameBufferSize
   8.121 +                              );
   8.122 +typedef PDH_STATUS (WINAPI *PdhMakeCounterPathFunc)(
   8.123 +                            PDH_COUNTER_PATH_ELEMENTS *pCounterPathElements,
   8.124 +                            LPTSTR szFullPathBuffer,
   8.125 +                            LPDWORD pcchBufferSize,
   8.126 +                            DWORD dwFlags
   8.127 +                            );
   8.128 +
   8.129 +static PdhAddCounterFunc PdhAddCounter_i;
   8.130 +static PdhOpenQueryFunc PdhOpenQuery_i;
   8.131 +static PdhCloseQueryFunc PdhCloseQuery_i;
   8.132 +static PdhCollectQueryDataFunc PdhCollectQueryData_i;
   8.133 +static PdhGetFormattedCounterValueFunc PdhGetFormattedCounterValue_i;
   8.134 +static PdhEnumObjectItemsFunc PdhEnumObjectItems_i;
   8.135 +static PdhRemoveCounterFunc PdhRemoveCounter_i;
   8.136 +static PdhLookupPerfNameByIndexFunc PdhLookupPerfNameByIndex_i;
   8.137 +static PdhMakeCounterPathFunc PdhMakeCounterPath_i;
   8.138 +
   8.139 +static HANDLE thisProcess;
   8.140 +static double cpuFactor;
   8.141 +static DWORD  num_cpus;
   8.142 +
   8.143 +#define FT2JLONG(X)  ((((jlong)X.dwHighDateTime) << 32) | ((jlong)X.dwLowDateTime))
   8.144 +#define COUNTER_BUF_SIZE 256
   8.145 +// Min time between query updates.
   8.146 +#define MIN_UPDATE_INTERVAL 500
   8.147 +#define CONFIG_SUCCESSFUL 0
   8.148 +
   8.149 +/**
   8.150 + * Struct for PDH queries.
   8.151 + */
   8.152 +typedef struct {
   8.153 +    HQUERY      query;
   8.154 +    uint64_t      lastUpdate; // Last time query was updated (current millis).
   8.155 +} UpdateQueryS, *UpdateQueryP;
   8.156 +
   8.157 +/**
   8.158 + * Struct for the processor load counters.
   8.159 + */
   8.160 +typedef struct {
   8.161 +    UpdateQueryS      query;
   8.162 +    HCOUNTER*      counters;
   8.163 +    int          noOfCounters;
   8.164 +} MultipleCounterQueryS, *MultipleCounterQueryP;
   8.165 +
   8.166 +/**
   8.167 + * Struct for the jvm process load counter.
   8.168 + */
   8.169 +typedef struct {
   8.170 +    UpdateQueryS      query;
   8.171 +    HCOUNTER      counter;
   8.172 +} SingleCounterQueryS, *SingleCounterQueryP;
   8.173 +
   8.174 +static char* getProcessPDHHeader(void);
   8.175 +
   8.176 +/**
   8.177 + * Currently available counters.
   8.178 + */
   8.179 +static SingleCounterQueryS cntCtxtSwitchRate;
   8.180 +static SingleCounterQueryS cntVirtualSize;
   8.181 +static SingleCounterQueryS cntProcLoad;
   8.182 +static SingleCounterQueryS cntProcSystemLoad;
   8.183 +static MultipleCounterQueryS multiCounterCPULoad;
   8.184 +
   8.185 +static CRITICAL_SECTION processHeaderLock;
   8.186 +static CRITICAL_SECTION initializationLock;
   8.187 +
   8.188 +/**
   8.189 + * Initialize the perf module at startup.
   8.190 + */
   8.191 +int
   8.192 +perfiInit(void)
   8.193 +{
   8.194 +    InitializeCriticalSection(&processHeaderLock);
   8.195 +    InitializeCriticalSection(&initializationLock);
   8.196 +    return 0;
   8.197 +}
   8.198 +
   8.199 +/**
   8.200 + * Dynamically sets up function pointers to the PDH library.
   8.201 + *
   8.202 + * @return CONFIG_SUCCESSFUL on success, negative on failure.
   8.203 + */
   8.204 +static int
   8.205 +get_functions(HMODULE h, char *ebuf, size_t elen) {
   8.206 +    // The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
   8.207 +    PdhAddCounter_i         = (PdhAddCounterFunc)GetProcAddress(h, "PdhAddCounterA");
   8.208 +    PdhOpenQuery_i         = (PdhOpenQueryFunc)GetProcAddress(h, "PdhOpenQueryA");
   8.209 +    PdhCloseQuery_i         = (PdhCloseQueryFunc)GetProcAddress(h, "PdhCloseQuery");
   8.210 +    PdhCollectQueryData_i     = (PdhCollectQueryDataFunc)GetProcAddress(h, "PdhCollectQueryData");
   8.211 +    PdhGetFormattedCounterValue_i = (PdhGetFormattedCounterValueFunc)GetProcAddress(h, "PdhGetFormattedCounterValue");
   8.212 +    PdhEnumObjectItems_i         = (PdhEnumObjectItemsFunc)GetProcAddress(h, "PdhEnumObjectItemsA");
   8.213 +    PdhRemoveCounter_i         = (PdhRemoveCounterFunc)GetProcAddress(h, "PdhRemoveCounter");
   8.214 +    PdhLookupPerfNameByIndex_i     = (PdhLookupPerfNameByIndexFunc)GetProcAddress(h, "PdhLookupPerfNameByIndexA");
   8.215 +    PdhMakeCounterPath_i         = (PdhMakeCounterPathFunc)GetProcAddress(h, "PdhMakeCounterPathA");
   8.216 +
   8.217 +    if (PdhAddCounter_i == NULL || PdhOpenQuery_i == NULL ||
   8.218 +    PdhCloseQuery_i == NULL || PdhCollectQueryData_i == NULL ||
   8.219 +    PdhGetFormattedCounterValue_i == NULL || PdhEnumObjectItems_i == NULL ||
   8.220 +    PdhRemoveCounter_i == NULL || PdhLookupPerfNameByIndex_i == NULL || PdhMakeCounterPath_i == NULL)
   8.221 +    {
   8.222 +        _snprintf(ebuf, elen, "Required method could not be found.");
   8.223 +        return -1;
   8.224 +    }
   8.225 +    return CONFIG_SUCCESSFUL;
   8.226 +}
   8.227 +
   8.228 +/**
   8.229 + * Returns the counter value as a double for the specified query.
   8.230 + * Will collect the query data and update the counter values as necessary.
   8.231 + *
   8.232 + * @param query       the query to update (if needed).
   8.233 + * @param c          the counter to read.
   8.234 + * @param value       where to store the formatted value.
   8.235 + * @param format      the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc)
   8.236 + * @return            CONFIG_SUCCESSFUL if no error
   8.237 + *                    -1 if PdhCollectQueryData fails
   8.238 + *                    -2 if PdhGetFormattedCounterValue fails
   8.239 + */
   8.240 +static int
   8.241 +getPerformanceData(UpdateQueryP query, HCOUNTER c, PDH_FMT_COUNTERVALUE* value, DWORD format) {
   8.242 +    clock_t now;
   8.243 +    now = clock();
   8.244 +
   8.245 +    // Need to limit how often we update the query
   8.246 +    // to mimise the heisenberg effect.
   8.247 +    // (PDH behaves erratically if the counters are
   8.248 +    // queried too often, especially counters that
   8.249 +    // store and use values from two consecutive updates,
   8.250 +    // like cpu load.)
   8.251 +    if (now - query->lastUpdate > MIN_UPDATE_INTERVAL) {
   8.252 +        if (PdhCollectQueryData_i(query->query) != ERROR_SUCCESS) {
   8.253 +            return -1;
   8.254 +        }
   8.255 +        query->lastUpdate = now;
   8.256 +    }
   8.257 +
   8.258 +    if (PdhGetFormattedCounterValue_i(c, format, NULL, value) != ERROR_SUCCESS) {
   8.259 +        return -2;
   8.260 +    }
   8.261 +    return CONFIG_SUCCESSFUL;
   8.262 +}
   8.263 +
   8.264 +/**
   8.265 + * Places the resolved counter name of the counter at the specified index in the
   8.266 + * supplied buffer. There must be enough space in the buffer to hold the counter name.
   8.267 + *
   8.268 + * @param index   the counter index as specified in the registry.
   8.269 + * @param buf     the buffer in which to place the counter name.
   8.270 + * @param size      the size of the counter name buffer.
   8.271 + * @param ebuf    the error message buffer.
   8.272 + * @param elen    the length of the error buffer.
   8.273 + * @return        CONFIG_SUCCESSFUL if successful, negative on failure.
   8.274 + */
   8.275 +static int
   8.276 +find_name(DWORD index, char *buf, DWORD size) {
   8.277 +    PDH_STATUS res;
   8.278 +
   8.279 +    if ((res = PdhLookupPerfNameByIndex_i(NULL, index, buf, &size)) != ERROR_SUCCESS) {
   8.280 +
   8.281 +        /* printf("Could not open counter %d: error=0x%08x", index, res); */
   8.282 +        /* if (res == PDH_CSTATUS_NO_MACHINE) { */
   8.283 +        /*      printf("User probably does not have sufficient privileges to use"); */
   8.284 +        /*      printf("performance counters. If you are running on Windows 2003"); */
   8.285 +        /*      printf("or Windows Vista, make sure the user is in the"); */
   8.286 +        /*      printf("Performance Logs user group."); */
   8.287 +        /* } */
   8.288 +        return -1;
   8.289 +    }
   8.290 +
   8.291 +    if (size == 0) {
   8.292 +        /* printf("Failed to get counter name for %d: empty string", index); */
   8.293 +        return -1;
   8.294 +    }
   8.295 +
   8.296 +    // windows vista does not null-terminate the string (allthough the docs says it will)
   8.297 +    buf[size - 1] = '\0';
   8.298 +    return CONFIG_SUCCESSFUL;
   8.299 +}
   8.300 +
   8.301 +/**
   8.302 + * Sets up the supplied SingleCounterQuery to listen for the specified counter.
   8.303 + * initPDH() must have been run prior to calling this function!
   8.304 + *
   8.305 + * @param counterQuery   the counter query to set up.
   8.306 + * @param counterString  the string specifying the path to the counter.
   8.307 + * @param ebuf           the error buffer.
   8.308 + * @param elen           the length of the error buffer.
   8.309 + * @returns              CONFIG_SUCCESSFUL if successful, negative on failure.
   8.310 + */
   8.311 +static int
   8.312 +initSingleCounterQuery(SingleCounterQueryP counterQuery, char *counterString) {
   8.313 +    if (PdhOpenQuery_i(NULL, 0, &counterQuery->query.query) != ERROR_SUCCESS) {
   8.314 +        /* printf("Could not open query for %s", counterString); */
   8.315 +        return -1;
   8.316 +    }
   8.317 +    if (PdhAddCounter_i(counterQuery->query.query, counterString, 0, &counterQuery->counter) != ERROR_SUCCESS) {
   8.318 +        /* printf("Could not add counter %s for query", counterString); */
   8.319 +        if (counterQuery->counter != NULL) {
   8.320 +            PdhRemoveCounter_i(counterQuery->counter);
   8.321 +        }
   8.322 +        if (counterQuery->query.query != NULL) {
   8.323 +            PdhCloseQuery_i(counterQuery->query.query);
   8.324 +        }
   8.325 +        memset(counterQuery, 0, sizeof(SingleCounterQueryS));
   8.326 +        return -1;
   8.327 +    }
   8.328 +    return CONFIG_SUCCESSFUL;
   8.329 +}
   8.330 +
   8.331 +/**
   8.332 + * Sets up the supplied SingleCounterQuery to listen for the time spent
   8.333 + * by the HotSpot process.
   8.334 + *
   8.335 + * @param counterQuery   the counter query to set up as a process counter.
   8.336 + * @param ebuf           the error buffer.
   8.337 + * @param elen           the length of the error buffer.
   8.338 + * @returns              CONFIG_SUCCESSFUL if successful, negative on failure.
   8.339 + */
   8.340 +static int
   8.341 +initProcLoadCounter(void) {
   8.342 +    char time[COUNTER_BUF_SIZE];
   8.343 +    char counter[COUNTER_BUF_SIZE*2];
   8.344 +
   8.345 +    if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
   8.346 +        return -1;
   8.347 +    }
   8.348 +    _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
   8.349 +    return initSingleCounterQuery(&cntProcLoad, counter);
   8.350 +}
   8.351 +
   8.352 +static int
   8.353 +initProcSystemLoadCounter(void) {
   8.354 +    char time[COUNTER_BUF_SIZE];
   8.355 +    char counter[COUNTER_BUF_SIZE*2];
   8.356 +
   8.357 +    if (find_name(PDH_PRIV_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
   8.358 +        return -1;
   8.359 +    }
   8.360 +    _snprintf(counter, sizeof(counter)-1, "%s\\%s", getProcessPDHHeader(), time);
   8.361 +    return initSingleCounterQuery(&cntProcSystemLoad, counter);
   8.362 +}
   8.363 +
   8.364 +/**
   8.365 + * Sets up the supplied MultipleCounterQuery to check on the processors.
   8.366 + * (Comment: Refactor and prettify as with the the SingleCounter queries
   8.367 + * if more MultipleCounterQueries are discovered.)
   8.368 + *
   8.369 + * initPDH() must have been run prior to calling this function.
   8.370 + *
   8.371 + * @param multiQuery  a pointer to a MultipleCounterQueryS, will be filled in with
   8.372 + *                    the necessary info to check the PDH processor counters.
   8.373 + * @return            CONFIG_SUCCESSFUL if successful, negative on failure.
   8.374 + */
   8.375 +static int
   8.376 +initProcessorCounters(void) {
   8.377 +    char          processor[COUNTER_BUF_SIZE]; //'Processor' == #238
   8.378 +    char          time[COUNTER_BUF_SIZE];      //'Time' == 6
   8.379 +    DWORD      c_size, i_size;
   8.380 +    HQUERY     tmpQuery;
   8.381 +    DWORD      i, p_count;
   8.382 +    BOOL          error;
   8.383 +    char         *instances, *tmp;
   8.384 +    PDH_STATUS pdhStat;
   8.385 +
   8.386 +    c_size   = i_size = 0;
   8.387 +    tmpQuery = NULL;
   8.388 +    error    = false;
   8.389 +
   8.390 +    // This __try / __except stuff is there since Windows 2000 beta (or so) sometimes triggered
   8.391 +    // an access violation when the user had insufficient privileges to use the performance
   8.392 +    // counters. This was previously guarded by a very ugly piece of code which disabled the
   8.393 +    // global trap handling in JRockit. Don't know if this really is needed anymore, but otoh,
   8.394 +    // if we keep it we don't crash on Win2k beta. /Ihse, 2005-05-30
   8.395 +    __try {
   8.396 +        if (find_name(PDH_PROCESSOR_IDX, processor, sizeof(processor)-1) < 0) {
   8.397 +            return -1;
   8.398 +        }
   8.399 +    } __except (EXCEPTION_EXECUTE_HANDLER) { // We'll catch all exceptions here.
   8.400 +        /* printf("User does not have sufficient privileges to use performance counters"); */
   8.401 +        return -1;
   8.402 +    }
   8.403 +
   8.404 +    if (find_name(PDH_PROCESSOR_TIME_IDX, time, sizeof(time)-1) < 0) {
   8.405 +        return -1;
   8.406 +    }
   8.407 +    //ok, now we have enough to enumerate all processors.
   8.408 +    pdhStat = PdhEnumObjectItems_i (
   8.409 +                    NULL,                   // reserved
   8.410 +                    NULL,                   // local machine
   8.411 +                    processor,          // object to enumerate
   8.412 +                    NULL,              // pass in NULL buffers
   8.413 +                    &c_size,              // and 0 length to get
   8.414 +                    NULL,              // required size
   8.415 +                    &i_size,              // of the buffers in chars
   8.416 +                    PERF_DETAIL_WIZARD,     // counter detail level
   8.417 +                    0);
   8.418 +    if (pdh_fail(pdhStat)) {
   8.419 +        /* printf("could not enumerate processors (1) error=%d", pdhStat); */
   8.420 +        return -1;
   8.421 +    }
   8.422 +
   8.423 +    // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
   8.424 +    instances = calloc(i_size, 1);
   8.425 +    if (instances == NULL) {
   8.426 +        /* printf("could not allocate memory (1) %d bytes", i_size); */
   8.427 +        error = true;
   8.428 +        goto end;
   8.429 +    }
   8.430 +
   8.431 +    c_size  = 0;
   8.432 +    pdhStat = PdhEnumObjectItems_i (
   8.433 +                    NULL,                   // reserved
   8.434 +                    NULL,                   // local machine
   8.435 +                    processor,              // object to enumerate
   8.436 +                    NULL,              // pass in NULL buffers
   8.437 +                    &c_size,              // and 0 length to get
   8.438 +                    instances,          // required size
   8.439 +                    &i_size,              // of the buffers in chars
   8.440 +                    PERF_DETAIL_WIZARD,     // counter detail level
   8.441 +                    0);
   8.442 +
   8.443 +    if (pdh_fail(pdhStat)) {
   8.444 +        /* printf("could not enumerate processors (2) error=%d", pdhStat); */
   8.445 +        error = true;
   8.446 +        goto end;
   8.447 +    }
   8.448 +    //count perf count instances.
   8.449 +    for (p_count = 0, tmp = instances; *tmp != 0; tmp = &tmp[lstrlen(tmp)+1], p_count++);
   8.450 +
   8.451 +    //is this correct for HT?
   8.452 +    assert(p_count == num_cpus+1);
   8.453 +
   8.454 +    //ok, have number of perf counters.
   8.455 +    multiCounterCPULoad.counters = calloc(p_count, sizeof(HCOUNTER));
   8.456 +    if (multiCounterCPULoad.counters == NULL) {
   8.457 +        /* printf("could not allocate memory (2) count=%d", p_count); */
   8.458 +        error = true;
   8.459 +        goto end;
   8.460 +    }
   8.461 +
   8.462 +    multiCounterCPULoad.noOfCounters = p_count;
   8.463 +
   8.464 +    if (PdhOpenQuery_i(NULL, 0, &multiCounterCPULoad.query.query) != ERROR_SUCCESS) {
   8.465 +        /* printf("could not create query"); */
   8.466 +        error = true;
   8.467 +        goto end;
   8.468 +    }
   8.469 +    //now, fetch the counters.
   8.470 +    for (i = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[lstrlen(tmp)+1], i++) {
   8.471 +    char counter[2*COUNTER_BUF_SIZE];
   8.472 +
   8.473 +    _snprintf(counter, sizeof(counter)-1, "\\%s(%s)\\%s", processor, tmp, time);
   8.474 +
   8.475 +    if (PdhAddCounter_i(multiCounterCPULoad.query.query, counter, 0, &multiCounterCPULoad.counters[i]) != ERROR_SUCCESS) {
   8.476 +            /* printf("error adding processor counter %s", counter); */
   8.477 +            error = true;
   8.478 +            goto end;
   8.479 +        }
   8.480 +    }
   8.481 +
   8.482 +    free(instances);
   8.483 +    instances = NULL;
   8.484 +
   8.485 +    // Query once to initialize the counters needing at least two queries
   8.486 +    // (like the % CPU usage) to calculate correctly.
   8.487 +    if (PdhCollectQueryData_i(multiCounterCPULoad.query.query) != ERROR_SUCCESS)
   8.488 +        error = true;
   8.489 +
   8.490 + end:
   8.491 +    if (instances != NULL) {
   8.492 +        free(instances);
   8.493 +    }
   8.494 +    if (tmpQuery != NULL) {
   8.495 +        PdhCloseQuery_i(tmpQuery);
   8.496 +    }
   8.497 +    if (error) {
   8.498 +        int i;
   8.499 +
   8.500 +        if (multiCounterCPULoad.counters != NULL) {
   8.501 +            for (i = 0; i < multiCounterCPULoad.noOfCounters; i++) {
   8.502 +                if (multiCounterCPULoad.counters[i] != NULL) {
   8.503 +                    PdhRemoveCounter_i(multiCounterCPULoad.counters[i]);
   8.504 +                }
   8.505 +            }
   8.506 +            free(multiCounterCPULoad.counters[i]);
   8.507 +        }
   8.508 +        if (multiCounterCPULoad.query.query != NULL) {
   8.509 +            PdhCloseQuery_i(multiCounterCPULoad.query.query);
   8.510 +        }
   8.511 +        memset(&multiCounterCPULoad, 0, sizeof(MultipleCounterQueryS));
   8.512 +        return -1;
   8.513 +    }
   8.514 +    return CONFIG_SUCCESSFUL;
   8.515 +}
   8.516 +
   8.517 +/**
   8.518 + * Help function that initializes the PDH process header for the JRockit process.
   8.519 + * (You should probably use getProcessPDHHeader() instead!)
   8.520 + *
   8.521 + * initPDH() must have been run prior to calling this function.
   8.522 + *
   8.523 + * @param ebuf the error buffer.
   8.524 + * @param elen the length of the error buffer.
   8.525 + *
   8.526 + * @return the PDH instance description corresponding to the JVM process.
   8.527 + */
   8.528 +static char*
   8.529 +initProcessPDHHeader(void) {
   8.530 +    static char hotspotheader[2*COUNTER_BUF_SIZE];
   8.531 +
   8.532 +    char           counter[2*COUNTER_BUF_SIZE];
   8.533 +    char           processes[COUNTER_BUF_SIZE];   //'Process' == #230
   8.534 +    char           pid[COUNTER_BUF_SIZE];           //'ID Process' == 784
   8.535 +    char           module_name[MAX_PATH];
   8.536 +    PDH_STATUS  pdhStat;
   8.537 +    DWORD       c_size = 0, i_size = 0;
   8.538 +    HQUERY      tmpQuery = NULL;
   8.539 +    int           i, myPid = _getpid();
   8.540 +    BOOL           error = false;
   8.541 +    char          *instances, *tmp, *instance_name, *dot_pos;
   8.542 +
   8.543 +    tmpQuery = NULL;
   8.544 +    myPid    = _getpid();
   8.545 +    error    = false;
   8.546 +
   8.547 +    if (find_name(PDH_PROCESS_IDX, processes, sizeof(processes) - 1) < 0) {
   8.548 +        return NULL;
   8.549 +    }
   8.550 +
   8.551 +    if (find_name(PDH_ID_PROCESS_IDX, pid, sizeof(pid) - 1) < 0) {
   8.552 +        return NULL;
   8.553 +    }
   8.554 +    //time is same.
   8.555 +
   8.556 +    c_size = 0;
   8.557 +    i_size = 0;
   8.558 +
   8.559 +    pdhStat = PdhEnumObjectItems_i (
   8.560 +                    NULL,                   // reserved
   8.561 +                    NULL,                   // local machine
   8.562 +                    processes,              // object to enumerate
   8.563 +                    NULL,                   // pass in NULL buffers
   8.564 +                    &c_size,              // and 0 length to get
   8.565 +                    NULL,              // required size
   8.566 +                    &i_size,              // of the buffers in chars
   8.567 +                    PERF_DETAIL_WIZARD,     // counter detail level
   8.568 +                    0);
   8.569 +
   8.570 +    //ok, now we have enough to enumerate all processes
   8.571 +    if (pdh_fail(pdhStat)) {
   8.572 +        /* printf("Could not enumerate processes (1) error=%d", pdhStat); */
   8.573 +        return NULL;
   8.574 +    }
   8.575 +
   8.576 +    // use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
   8.577 +    if ((instances = calloc(i_size, 1)) == NULL) {
   8.578 +        /* printf("Could not allocate memory %d bytes", i_size); */
   8.579 +        error = true;
   8.580 +        goto end;
   8.581 +    }
   8.582 +
   8.583 +    c_size = 0;
   8.584 +
   8.585 +    pdhStat = PdhEnumObjectItems_i (
   8.586 +                    NULL,                   // reserved
   8.587 +                    NULL,                   // local machine
   8.588 +                    processes,              // object to enumerate
   8.589 +                    NULL,              // pass in NULL buffers
   8.590 +                    &c_size,              // and 0 length to get
   8.591 +                    instances,          // required size
   8.592 +                    &i_size,              // of the buffers in chars
   8.593 +                    PERF_DETAIL_WIZARD,     // counter detail level
   8.594 +                    0);
   8.595 +
   8.596 +    // ok, now we have enough to enumerate all processes
   8.597 +    if (pdh_fail(pdhStat)) {
   8.598 +        /* printf("Could not enumerate processes (2) error=%d", pdhStat); */
   8.599 +        error = true;
   8.600 +        goto end;
   8.601 +    }
   8.602 +
   8.603 +    if (PdhOpenQuery_i(NULL, 0, &tmpQuery) != ERROR_SUCCESS) {
   8.604 +        /* printf("Could not create temporary query"); */
   8.605 +        error = true;
   8.606 +        goto end;
   8.607 +    }
   8.608 +
   8.609 +    // Find our module name and use it to extract the instance name used by PDH
   8.610 +    if (GetModuleFileName(NULL, module_name, MAX_PATH) >= MAX_PATH-1) {
   8.611 +        /* printf("Module name truncated"); */
   8.612 +        error = true;
   8.613 +        goto end;
   8.614 +    }
   8.615 +    instance_name = strrchr(module_name, '\\'); //drop path
   8.616 +    instance_name++;                            //skip slash
   8.617 +    dot_pos = strchr(instance_name, '.');       //drop .exe
   8.618 +    dot_pos[0] = '\0';
   8.619 +
   8.620 +    //now, fetch the counters.
   8.621 +    for (tmp = instances; *tmp != 0 && !error; tmp = &tmp[lstrlen(tmp)+1]) {
   8.622 +        HCOUNTER  hc = NULL;
   8.623 +        BOOL done = false;
   8.624 +
   8.625 +        // Skip until we find our own process name
   8.626 +        if (strcmp(tmp, instance_name) != 0) {
   8.627 +            continue;
   8.628 +        }
   8.629 +
   8.630 +        // iterate over all instance indexes and try to find our own pid
   8.631 +        for (i = 0; !done && !error; i++){
   8.632 +            PDH_STATUS res;
   8.633 +            _snprintf(counter, sizeof(counter)-1, "\\%s(%s#%d)\\%s", processes, tmp, i, pid);
   8.634 +
   8.635 +            if (PdhAddCounter_i(tmpQuery, counter, 0, &hc) != ERROR_SUCCESS) {
   8.636 +                /* printf("Failed to create process id query"); */
   8.637 +                error = true;
   8.638 +                goto end;
   8.639 +            }
   8.640 +
   8.641 +            res = PdhCollectQueryData_i(tmpQuery);
   8.642 +
   8.643 +            if (res == PDH_INVALID_HANDLE) {
   8.644 +                /* printf("Failed to query process id"); */
   8.645 +                res = -1;
   8.646 +                done = true;
   8.647 +            } else if (res == PDH_NO_DATA) {
   8.648 +                done = true;
   8.649 +            } else {
   8.650 +                PDH_FMT_COUNTERVALUE cv;
   8.651 +
   8.652 +                PdhGetFormattedCounterValue_i(hc, PDH_FMT_LONG, NULL, &cv);
   8.653 +               /*
   8.654 +                 * This check seems to be needed for Win2k SMP boxes, since
   8.655 +                 * they for some reason don't return PDH_NO_DATA for non existing
   8.656 +                 * counters.
   8.657 +                 */
   8.658 +                if (cv.CStatus != PDH_CSTATUS_VALID_DATA) {
   8.659 +                    done = true;
   8.660 +                } else if (cv.longValue == myPid) {
   8.661 +                    _snprintf(hotspotheader, sizeof(hotspotheader)-1, "\\%s(%s#%d)\0", processes, tmp, i);
   8.662 +                    PdhRemoveCounter_i(hc);
   8.663 +                    goto end;
   8.664 +                }
   8.665 +            }
   8.666 +            PdhRemoveCounter_i(hc);
   8.667 +        }
   8.668 +    }
   8.669 + end:
   8.670 +    if (instances != NULL) {
   8.671 +        free(instances);
   8.672 +    }
   8.673 +    if (tmpQuery != NULL) {
   8.674 +        PdhCloseQuery_i(tmpQuery);
   8.675 +    }
   8.676 +    if (error) {
   8.677 +        return NULL;
   8.678 +    }
   8.679 +    return hotspotheader;
   8.680 +}
   8.681 +
   8.682 +/**
   8.683 + * Returns the PDH string prefix identifying the HotSpot process. Use this prefix when getting
   8.684 + * counters from the PDH process object representing HotSpot.
   8.685 + *
   8.686 + * Note: this call may take some time to complete.
   8.687 + *
   8.688 + * @param ebuf error buffer.
   8.689 + * @param elen error buffer length.
   8.690 + *
   8.691 + * @return the header to be used when retrieving PDH counters from the HotSpot process.
   8.692 + * Will return NULL if the call failed.
   8.693 + */
   8.694 +static char *
   8.695 +getProcessPDHHeader(void) {
   8.696 +    static char *processHeader = NULL;
   8.697 +
   8.698 +    EnterCriticalSection(&processHeaderLock); {
   8.699 +        if (processHeader == NULL) {
   8.700 +            processHeader = initProcessPDHHeader();
   8.701 +        }
   8.702 +    } LeaveCriticalSection(&processHeaderLock);
   8.703 +    return processHeader;
   8.704 +}
   8.705 +
   8.706 +int perfInit(void);
   8.707 +
   8.708 +double
   8.709 +perfGetCPULoad(int which)
   8.710 +{
   8.711 +    PDH_FMT_COUNTERVALUE cv;
   8.712 +    HCOUNTER            c;
   8.713 +
   8.714 +    if (perfInit() < 0) {
   8.715 +        // warn?
   8.716 +        return -1.0;
   8.717 +    }
   8.718 +
   8.719 +    if (multiCounterCPULoad.query.query == NULL) {
   8.720 +        // warn?
   8.721 +        return -1.0;
   8.722 +    }
   8.723 +
   8.724 +    if (which == -1) {
   8.725 +        c = multiCounterCPULoad.counters[multiCounterCPULoad.noOfCounters - 1];
   8.726 +    } else {
   8.727 +        if (which < multiCounterCPULoad.noOfCounters) {
   8.728 +            c = multiCounterCPULoad.counters[which];
   8.729 +        } else {
   8.730 +            return -1.0;
   8.731 +        }
   8.732 +    }
   8.733 +    if (getPerformanceData(&multiCounterCPULoad.query, c, &cv, PDH_FMT_DOUBLE ) == CONFIG_SUCCESSFUL) {
   8.734 +        return cv.doubleValue / 100;
   8.735 +    }
   8.736 +    return -1.0;
   8.737 +}
   8.738 +
   8.739 +double
   8.740 +perfGetProcessLoad(void)
   8.741 +{
   8.742 +    PDH_FMT_COUNTERVALUE cv;
   8.743 +
   8.744 +    if (perfInit() < 0) {
   8.745 +        // warn?
   8.746 +        return -1.0;
   8.747 +    }
   8.748 +
   8.749 +    if (cntProcLoad.query.query == NULL) {
   8.750 +        // warn?
   8.751 +        return -1.0;
   8.752 +    }
   8.753 +
   8.754 +    if (getPerformanceData(&cntProcLoad.query, cntProcLoad.counter, &cv, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100) == CONFIG_SUCCESSFUL) {
   8.755 +        double d = cv.doubleValue / cpuFactor;
   8.756 +        d = min(1, d);
   8.757 +        d = max(0, d);
   8.758 +        return d;
   8.759 +    }
   8.760 +    return -1.0;
   8.761 +}
   8.762 +
   8.763 +/**
   8.764 + * Helper to initialize the PDH library. Loads the library and sets up the functions.
   8.765 + * Note that once loaded, we will never unload the PDH library.
   8.766 + *
   8.767 + * @return  CONFIG_SUCCESSFUL if successful, negative on failure.
   8.768 + */
   8.769 +int
   8.770 +perfInit(void) {
   8.771 +    static HMODULE    h;
   8.772 +    static BOOL        running, inited;
   8.773 +
   8.774 +    int error;
   8.775 +
   8.776 +    if (running) {
   8.777 +        return CONFIG_SUCCESSFUL;
   8.778 +    }
   8.779 +
   8.780 +    error = CONFIG_SUCCESSFUL;
   8.781 +
   8.782 +    // this is double checked locking again, but we try to bypass the worst by
   8.783 +    // implicit membar at end of lock.
   8.784 +    EnterCriticalSection(&initializationLock); {
   8.785 +        if (!inited) {
   8.786 +            char         buf[64] = "";
   8.787 +            SYSTEM_INFO si;
   8.788 +
   8.789 +            // CMH. But windows will not care about our affinity when giving
   8.790 +            // us measurements. Need the real, raw num cpus.
   8.791 +
   8.792 +            GetSystemInfo(&si);
   8.793 +            num_cpus  = si.dwNumberOfProcessors;
   8.794 +            // Initialize the denominator for the jvm load calculations
   8.795 +            cpuFactor = num_cpus * 100;
   8.796 +
   8.797 +            /**
   8.798 +             * Do this dynamically, so we don't fail to start on systems without pdh.
   8.799 +             */
   8.800 +            if ((h = LoadLibrary("pdh.dll")) == NULL) {
   8.801 +                /* printf("Could not load pdh.dll (%d)", GetLastError()); */
   8.802 +                error = -2;
   8.803 +            } else if (get_functions(h, buf, sizeof(buf)) < 0) {
   8.804 +                FreeLibrary(h);
   8.805 +                h = NULL;
   8.806 +                error = -2;
   8.807 +               /* printf("Failed to init pdh functions: %s.\n", buf); */
   8.808 +            } else {
   8.809 +                if (initProcessorCounters() != 0) {
   8.810 +                    /* printf("Failed to init system load counters.\n"); */
   8.811 +                } else if (initProcLoadCounter() != 0) {
   8.812 +                    /* printf("Failed to init process load counter.\n"); */
   8.813 +                } else if (initProcSystemLoadCounter() != 0) {
   8.814 +                    /* printf("Failed to init process system load counter.\n"); */
   8.815 +                } else {
   8.816 +                    inited = true;
   8.817 +                }
   8.818 +            }
   8.819 +        }
   8.820 +    } LeaveCriticalSection(&initializationLock);
   8.821 +
   8.822 +    if (inited && error == CONFIG_SUCCESSFUL) {
   8.823 +        running = true;
   8.824 +    }
   8.825 +
   8.826 +    return error;
   8.827 +}
   8.828 +
   8.829 +JNIEXPORT jdouble JNICALL
   8.830 +Java_com_sun_management_OperatingSystem_getSystemCpuLoad
   8.831 +(JNIEnv *env, jobject dummy)
   8.832 +{
   8.833 +    return perfGetCPULoad(-1);
   8.834 +}
   8.835 +
   8.836 +JNIEXPORT jdouble JNICALL
   8.837 +Java_com_sun_management_OperatingSystem_getProcessCpuLoad
   8.838 +(JNIEnv *env, jobject dummy)
   8.839 +{
   8.840 +    return perfGetProcessLoad();
   8.841 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java	Wed May 11 18:52:46 2011 -0700
     9.3 @@ -0,0 +1,53 @@
     9.4 +/*
     9.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.
    9.11 + *
    9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.15 + * version 2 for more details (a copy is included in the LICENSE file that
    9.16 + * accompanied this code).
    9.17 + *
    9.18 + * You should have received a copy of the GNU General Public License version
    9.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.21 + *
    9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.23 + * or visit www.oracle.com if you need additional information or have any
    9.24 + * questions.
    9.25 + */
    9.26 +
    9.27 +/*
    9.28 + * @test
    9.29 + * @bug     7028071
    9.30 + * @summary Basic unit test of OperatingSystemMXBean.getProcessCpuLoad()
    9.31 + *
    9.32 + * @run main GetProcessCpuLoad
    9.33 + */
    9.34 +
    9.35 +import java.lang.management.*;
    9.36 +import com.sun.management.OperatingSystemMXBean;
    9.37 +
    9.38 +public class GetProcessCpuLoad {
    9.39 +    public static void main(String[] argv) throws Exception {
    9.40 +        OperatingSystemMXBean mbean = (com.sun.management.OperatingSystemMXBean)
    9.41 +            ManagementFactory.getOperatingSystemMXBean();
    9.42 +        double load;
    9.43 +        for(int i=0; i<10; i++) {
    9.44 +            load = mbean.getProcessCpuLoad();
    9.45 +            if((load<0.0 || load>1.0) && load != -1.0) {
    9.46 +                throw new RuntimeException("getProcessCpuLoad() returns " + load
    9.47 +                       +   " which is not in the [0.0,1.0] interval");
    9.48 +            }
    9.49 +            try {
    9.50 +                Thread.sleep(200);
    9.51 +            } catch(InterruptedException e) {
    9.52 +                e.printStackTrace();
    9.53 +            }
    9.54 +        }
    9.55 +    }
    9.56 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java	Wed May 11 18:52:46 2011 -0700
    10.3 @@ -0,0 +1,53 @@
    10.4 +/*
    10.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.
   10.11 + *
   10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.15 + * version 2 for more details (a copy is included in the LICENSE file that
   10.16 + * accompanied this code).
   10.17 + *
   10.18 + * You should have received a copy of the GNU General Public License version
   10.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.21 + *
   10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.23 + * or visit www.oracle.com if you need additional information or have any
   10.24 + * questions.
   10.25 + */
   10.26 +
   10.27 +/*
   10.28 + * @test
   10.29 + * @bug     7028071
   10.30 + * @summary Basic unit test of OperatingSystemMXBean.getProcessCpuLoad()
   10.31 + *
   10.32 + * @run main GetSystemCpuLoad
   10.33 + */
   10.34 +
   10.35 +import java.lang.management.*;
   10.36 +import com.sun.management.OperatingSystemMXBean;
   10.37 +
   10.38 +public class GetSystemCpuLoad {
   10.39 +    public static void main(String[] argv) throws Exception {
   10.40 +        OperatingSystemMXBean mbean = (com.sun.management.OperatingSystemMXBean)
   10.41 +            ManagementFactory.getOperatingSystemMXBean();
   10.42 +        double load;
   10.43 +        for(int i=0; i<10; i++) {
   10.44 +            load = mbean.getSystemCpuLoad();
   10.45 +            if((load<0.0 || load>1.0) && load != -1.0) {
   10.46 +                throw new RuntimeException("getSystemCpuLoad() returns " + load
   10.47 +                       +  " which is not in the [0.0,1.0] interval");
   10.48 +            }
   10.49 +            try {
   10.50 +                Thread.sleep(200);
   10.51 +            } catch(InterruptedException e) {
   10.52 +                e.printStackTrace();
   10.53 +            }
   10.54 +        }
   10.55 +    }
   10.56 +}