From 044015f43a416d5e6727b7202ded4222489a8a75 Mon Sep 17 00:00:00 2001 From: sla Date: Tue, 17 Apr 2012 06:45:57 +0200 Subject: [PATCH] 7147848: com.sun.management.UnixOperatingSystem uses hardcoded dummy values [macosx] Summary: Provide the missing implementation UnixOperatingSystem on Mac OS X Reviewed-by: dsamersoff, dcubed --- .../sun/management/MacosxOperatingSystem.c | 126 +++++++++++++++++- .../sun/management/UnixOperatingSystem_md.c | 114 ++++++++++++++-- .../OperatingSystemMXBean/TestTotalSwap.sh | 7 + 3 files changed, 234 insertions(+), 13 deletions(-) diff --git a/src/solaris/native/com/sun/management/MacosxOperatingSystem.c b/src/solaris/native/com/sun/management/MacosxOperatingSystem.c index e2c561bf4..3e7ac65fa 100644 --- a/src/solaris/native/com/sun/management/MacosxOperatingSystem.c +++ b/src/solaris/native/com/sun/management/MacosxOperatingSystem.c @@ -25,16 +25,136 @@ #include "com_sun_management_UnixOperatingSystem.h" +#include +#include +#include + + JNIEXPORT jdouble JNICALL Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad (JNIEnv *env, jobject dummy) { - return -1.0; // not available + // 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) { - return -1.0; // not available -} + // 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; + } diff --git a/src/solaris/native/com/sun/management/UnixOperatingSystem_md.c b/src/solaris/native/com/sun/management/UnixOperatingSystem_md.c index 088b3cfe8..656306c83 100644 --- a/src/solaris/native/com/sun/management/UnixOperatingSystem_md.c +++ b/src/solaris/native/com/sun/management/UnixOperatingSystem_md.c @@ -34,6 +34,13 @@ #include #if defined(_ALLBSD_SOURCE) #include +#ifdef __APPLE__ +#include +#include +#include +#include +#include +#endif #else #include #endif @@ -150,6 +157,13 @@ static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean availa 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 @@ -216,6 +230,15 @@ Java_com_sun_management_UnixOperatingSystem_getCommittedVirtualMemorySize 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. @@ -243,6 +266,17 @@ 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; @@ -267,19 +301,32 @@ Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime 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 _ALLBSD_SOURCE +#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 +#else // solaris / linux jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES); return (num_avail_physical_pages * page_size); #endif @@ -290,28 +337,75 @@ Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize (JNIEnv *env, jobject mbean) { #ifdef _ALLBSD_SOURCE - jlong result; + jlong result = 0; int mib[2]; size_t rlen; mib[0] = CTL_HW; - mib[1] = HW_PHYSMEM; + mib[1] = HW_MEMSIZE; rlen = sizeof(result); - if (sysctl(mib, 2, &result, &rlen, NULL, 0) == -1) - result = 256 * MB; - - return (result); -#else + 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 _ALLBSD_SOURCE +#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 (res != 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. */ diff --git a/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.sh b/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.sh index 63bff977e..009be0034 100644 --- a/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.sh +++ b/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.sh @@ -83,6 +83,13 @@ case `uname -s` in total_swap=`free -b | grep -i swap | awk '{print $2}'` runOne GetTotalSwapSpaceSize $total_swap ;; + Darwin ) + # $ sysctl -n vm.swapusage + # total = 8192.00M used = 7471.11M free = 720.89M (encrypted) + swap=`/usr/sbin/sysctl -n vm.swapusage | awk '{ print $3 }' | awk -F . '{ print $1 }'` || exit 2 + total_swap=`expr $swap \* 1024 \* 1024` || exit 2 + runOne GetTotalSwapSpaceSize $total_swap + ;; * ) runOne GetTotalSwapSpaceSize "sanity-only" ;; -- GitLab