1/* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include "com_sun_management_internal_OperatingSystemImpl.h" 27 28#include <sys/time.h> 29#include <mach/mach.h> 30#include <mach/task_info.h> 31 32#include "jvm.h" 33 34JNIEXPORT jdouble JNICALL 35Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0 36(JNIEnv *env, jobject dummy) 37{ 38 // This code is influenced by the darwin top source 39 40 kern_return_t kr; 41 mach_msg_type_number_t count; 42 host_cpu_load_info_data_t load; 43 44 static jlong last_used = 0; 45 static jlong last_total = 0; 46 47 count = HOST_CPU_LOAD_INFO_COUNT; 48 kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&load, &count); 49 if (kr != KERN_SUCCESS) { 50 return -1; 51 } 52 53 jlong used = load.cpu_ticks[CPU_STATE_USER] + load.cpu_ticks[CPU_STATE_NICE] + load.cpu_ticks[CPU_STATE_SYSTEM]; 54 jlong total = used + load.cpu_ticks[CPU_STATE_IDLE]; 55 56 if (last_used == 0 || last_total == 0) { 57 // First call, just set the last values 58 last_used = used; 59 last_total = total; 60 // return 0 since we have no data, not -1 which indicates error 61 return 0; 62 } 63 64 jlong used_delta = used - last_used; 65 jlong total_delta = total - last_total; 66 67 jdouble cpu = (jdouble) used_delta / total_delta; 68 69 last_used = used; 70 last_total = total; 71 72 return cpu; 73} 74 75 76#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ 77 (r)->tv_sec = (a)->seconds; \ 78 (r)->tv_usec = (a)->microseconds; \ 79} while (0) 80 81 82#define TIME_VALUE_TO_MICROSECONDS(TV) \ 83 ((TV).tv_sec * 1000 * 1000 + (TV).tv_usec) 84 85 86JNIEXPORT jdouble JNICALL 87Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 88(JNIEnv *env, jobject dummy) 89{ 90 // This code is influenced by the darwin top source 91 92 struct task_basic_info_64 task_info_data; 93 struct task_thread_times_info thread_info_data; 94 struct timeval user_timeval, system_timeval, task_timeval; 95 struct timeval now; 96 mach_port_t task = mach_task_self(); 97 kern_return_t kr; 98 99 static jlong last_task_time = 0; 100 static jlong last_time = 0; 101 102 mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; 103 kr = task_info(task, 104 TASK_THREAD_TIMES_INFO, 105 (task_info_t)&thread_info_data, 106 &thread_info_count); 107 if (kr != KERN_SUCCESS) { 108 // Most likely cause: |task| is a zombie. 109 return -1; 110 } 111 112 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; 113 kr = task_info(task, 114 TASK_BASIC_INFO_64, 115 (task_info_t)&task_info_data, 116 &count); 117 if (kr != KERN_SUCCESS) { 118 // Most likely cause: |task| is a zombie. 119 return -1; 120 } 121 122 /* Set total_time. */ 123 // thread info contains live time... 124 TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); 125 TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); 126 timeradd(&user_timeval, &system_timeval, &task_timeval); 127 128 // ... task info contains terminated time. 129 TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); 130 TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); 131 timeradd(&user_timeval, &task_timeval, &task_timeval); 132 timeradd(&system_timeval, &task_timeval, &task_timeval); 133 134 if (gettimeofday(&now, NULL) < 0) { 135 return -1; 136 } 137 jint ncpus = JVM_ActiveProcessorCount(); 138 jlong time = TIME_VALUE_TO_MICROSECONDS(now) * ncpus; 139 jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval); 140 141 if ((last_task_time == 0) || (last_time == 0)) { 142 // First call, just set the last values. 143 last_task_time = task_time; 144 last_time = time; 145 // return 0 since we have no data, not -1 which indicates error 146 return 0; 147 } 148 149 jlong task_time_delta = task_time - last_task_time; 150 jlong time_delta = time - last_time; 151 if (time_delta == 0) { 152 return -1; 153 } 154 155 jdouble cpu = (jdouble) task_time_delta / time_delta; 156 157 last_task_time = task_time; 158 last_time = time; 159 160 return cpu; 161 } 162