Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/bsd/vm/os_perf_bsd.cpp
32284 views
/*1* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/23#include "precompiled.hpp"24#include "memory/allocation.inline.hpp"25#include "memory/resourceArea.hpp"26#include "runtime/os.hpp"27#include "runtime/os_perf.hpp"28#ifdef AARCH6429#include "vm_version_ext_aarch64.hpp"30#else31#include "vm_version_ext_x86.hpp"32#endif3334#ifdef __APPLE__35#import <libproc.h>36#include <sys/time.h>37#include <sys/sysctl.h>38#include <mach/mach.h>39#include <mach/task_info.h>40#include <sys/socket.h>41#include <net/if.h>42#include <net/if_dl.h>43#include <net/route.h>44#endif4546static const double NANOS_PER_SEC = 1000000000.0;4748class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {49friend class CPUPerformanceInterface;50private:51long _total_cpu_nanos;52long _total_csr_nanos;53long _jvm_user_nanos;54long _jvm_system_nanos;55long _jvm_context_switches;56long _used_ticks;57long _total_ticks;58int _active_processor_count;5960bool now_in_nanos(long* resultp) {61timeval current_time;62if (gettimeofday(¤t_time, NULL) != 0) {63// Error getting current time64return false;65}66*resultp = (long)(current_time.tv_sec * NANOS_PER_SEC + 1000L * current_time.tv_usec);67return true;68}6970double normalize(double value) {71return MIN2<double>(MAX2<double>(value, 0.0), 1.0);72}73int cpu_load(int which_logical_cpu, double* cpu_load);74int context_switch_rate(double* rate);75int cpu_load_total_process(double* cpu_load);76int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);7778CPUPerformance(const CPUPerformance& rhs); // no impl79CPUPerformance& operator=(const CPUPerformance& rhs); // no impl80public:81CPUPerformance();82bool initialize();83~CPUPerformance();84};8586CPUPerformanceInterface::CPUPerformance::CPUPerformance() {87_total_cpu_nanos= 0;88_total_csr_nanos= 0;89_jvm_context_switches = 0;90_jvm_user_nanos = 0;91_jvm_system_nanos = 0;92_used_ticks = 0;93_total_ticks = 0;94_active_processor_count = 0;95}9697bool CPUPerformanceInterface::CPUPerformance::initialize() {98return true;99}100101CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {102}103104int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {105return FUNCTIONALITY_NOT_IMPLEMENTED;106}107108int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {109#ifdef __APPLE__110host_name_port_t host = mach_host_self();111host_flavor_t flavor = HOST_CPU_LOAD_INFO;112mach_msg_type_number_t host_info_count = HOST_CPU_LOAD_INFO_COUNT;113host_cpu_load_info_data_t cpu_load_info;114115kern_return_t kr = host_statistics(host, flavor, (host_info_t)&cpu_load_info, &host_info_count);116if (kr != KERN_SUCCESS) {117return OS_ERR;118}119120long used_ticks = cpu_load_info.cpu_ticks[CPU_STATE_USER] + cpu_load_info.cpu_ticks[CPU_STATE_NICE] + cpu_load_info.cpu_ticks[CPU_STATE_SYSTEM];121long total_ticks = used_ticks + cpu_load_info.cpu_ticks[CPU_STATE_IDLE];122123if (_used_ticks == 0 || _total_ticks == 0) {124// First call, just set the values125_used_ticks = used_ticks;126_total_ticks = total_ticks;127return OS_ERR;128}129130long used_delta = used_ticks - _used_ticks;131long total_delta = total_ticks - _total_ticks;132133_used_ticks = used_ticks;134_total_ticks = total_ticks;135136if (total_delta == 0) {137// Avoid division by zero138return OS_ERR;139}140141*cpu_load = (double)used_delta / total_delta;142143return OS_OK;144#else145return FUNCTIONALITY_NOT_IMPLEMENTED;146#endif147}148149int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {150#ifdef __APPLE__151int result = cpu_load_total_process(psystemTotalLoad);152mach_port_t task = mach_task_self();153mach_msg_type_number_t task_info_count = TASK_INFO_MAX;154task_info_data_t task_info_data;155kern_return_t kr = task_info(task, TASK_ABSOLUTETIME_INFO, (task_info_t)task_info_data, &task_info_count);156if (kr != KERN_SUCCESS) {157return OS_ERR;158}159task_absolutetime_info_t absolutetime_info = (task_absolutetime_info_t)task_info_data;160161int active_processor_count = os::active_processor_count();162long jvm_user_nanos = absolutetime_info->total_user;163long jvm_system_nanos = absolutetime_info->total_system;164165long total_cpu_nanos;166if(!now_in_nanos(&total_cpu_nanos)) {167return OS_ERR;168}169170if (_total_cpu_nanos == 0 || active_processor_count != _active_processor_count) {171// First call or change in active processor count172result = OS_ERR;173}174175long delta_nanos = active_processor_count * (total_cpu_nanos - _total_cpu_nanos);176if (delta_nanos == 0) {177// Avoid division by zero178return OS_ERR;179}180181*pjvmUserLoad = normalize((double)(jvm_user_nanos - _jvm_user_nanos)/delta_nanos);182*pjvmKernelLoad = normalize((double)(jvm_system_nanos - _jvm_system_nanos)/delta_nanos);183184_active_processor_count = active_processor_count;185_total_cpu_nanos = total_cpu_nanos;186_jvm_user_nanos = jvm_user_nanos;187_jvm_system_nanos = jvm_system_nanos;188189return result;190#else191return FUNCTIONALITY_NOT_IMPLEMENTED;192#endif193}194195int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {196#ifdef __APPLE__197mach_port_t task = mach_task_self();198mach_msg_type_number_t task_info_count = TASK_INFO_MAX;199task_info_data_t task_info_data;200kern_return_t kr = task_info(task, TASK_EVENTS_INFO, (task_info_t)task_info_data, &task_info_count);201if (kr != KERN_SUCCESS) {202return OS_ERR;203}204205int result = OS_OK;206if (_total_csr_nanos == 0 || _jvm_context_switches == 0) {207// First call just set initial values.208result = OS_ERR;209}210211long jvm_context_switches = ((task_events_info_t)task_info_data)->csw;212213long total_csr_nanos;214if(!now_in_nanos(&total_csr_nanos)) {215return OS_ERR;216}217double delta_in_sec = (double)(total_csr_nanos - _total_csr_nanos) / NANOS_PER_SEC;218if (delta_in_sec == 0.0) {219// Avoid division by zero220return OS_ERR;221}222223*rate = (jvm_context_switches - _jvm_context_switches) / delta_in_sec;224225_jvm_context_switches = jvm_context_switches;226_total_csr_nanos = total_csr_nanos;227228return result;229#else230return FUNCTIONALITY_NOT_IMPLEMENTED;231#endif232}233234CPUPerformanceInterface::CPUPerformanceInterface() {235_impl = NULL;236}237238bool CPUPerformanceInterface::initialize() {239_impl = new CPUPerformanceInterface::CPUPerformance();240return _impl != NULL && _impl->initialize();241}242243CPUPerformanceInterface::~CPUPerformanceInterface() {244if (_impl != NULL) {245delete _impl;246}247}248249int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {250return _impl->cpu_load(which_logical_cpu, cpu_load);251}252253int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {254return _impl->cpu_load_total_process(cpu_load);255}256257int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {258return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);259}260261int CPUPerformanceInterface::context_switch_rate(double* rate) const {262return _impl->context_switch_rate(rate);263}264265class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {266friend class SystemProcessInterface;267private:268SystemProcesses();269bool initialize();270SystemProcesses(const SystemProcesses& rhs); // no impl271SystemProcesses& operator=(const SystemProcesses& rhs); // no impl272~SystemProcesses();273274//information about system processes275int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;276};277278SystemProcessInterface::SystemProcesses::SystemProcesses() {279}280281bool SystemProcessInterface::SystemProcesses::initialize() {282return true;283}284285SystemProcessInterface::SystemProcesses::~SystemProcesses() {286}287int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {288assert(system_processes != NULL, "system_processes pointer is NULL!");289assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");290#ifdef __APPLE__291pid_t* pids = NULL;292int pid_count = 0;293ResourceMark rm;294295int try_count = 0;296while (pids == NULL) {297// Find out buffer size298size_t pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);299if (pids_bytes <= 0) {300return OS_ERR;301}302pid_count = pids_bytes / sizeof(pid_t);303pids = NEW_RESOURCE_ARRAY(pid_t, pid_count);304memset(pids, 0, pids_bytes);305306pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids, pids_bytes);307if (pids_bytes <= 0) {308// couldn't fit buffer, retry.309FREE_RESOURCE_ARRAY(pid_t, pids, pid_count);310pids = NULL;311try_count++;312if (try_count > 3) {313return OS_ERR;314}315} else {316pid_count = pids_bytes / sizeof(pid_t);317}318}319320int process_count = 0;321SystemProcess* next = NULL;322for (int i = 0; i < pid_count; i++) {323pid_t pid = pids[i];324if (pid != 0) {325char buffer[PROC_PIDPATHINFO_MAXSIZE];326memset(buffer, 0 , sizeof(buffer));327if (proc_pidpath(pid, buffer, sizeof(buffer)) != -1) {328int length = strlen(buffer);329if (length > 0) {330SystemProcess* current = new SystemProcess();331char * path = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);332strcpy(path, buffer);333current->set_path(path);334current->set_pid((int)pid);335current->set_next(next);336next = current;337process_count++;338}339}340}341}342343*no_of_sys_processes = process_count;344*system_processes = next;345346return OS_OK;347#endif348return FUNCTIONALITY_NOT_IMPLEMENTED;349}350351int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {352return _impl->system_processes(system_procs, no_of_sys_processes);353}354355SystemProcessInterface::SystemProcessInterface() {356_impl = NULL;357}358359bool SystemProcessInterface::initialize() {360_impl = new SystemProcessInterface::SystemProcesses();361return _impl != NULL && _impl->initialize();362}363364SystemProcessInterface::~SystemProcessInterface() {365if (_impl != NULL) {366delete _impl;367}368}369370CPUInformationInterface::CPUInformationInterface() {371_cpu_info = NULL;372}373374bool CPUInformationInterface::initialize() {375_cpu_info = new CPUInformation();376377if (NULL == _cpu_info) {378return false;379}380_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());381_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());382_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());383_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());384_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());385386return true;387}388389CPUInformationInterface::~CPUInformationInterface() {390if (_cpu_info != NULL) {391if (_cpu_info->cpu_name() != NULL) {392const char* cpu_name = _cpu_info->cpu_name();393FREE_C_HEAP_ARRAY(char, cpu_name, mtInternal);394_cpu_info->set_cpu_name(NULL);395}396if (_cpu_info->cpu_description() != NULL) {397const char* cpu_desc = _cpu_info->cpu_description();398FREE_C_HEAP_ARRAY(char, cpu_desc, mtInternal);399_cpu_info->set_cpu_description(NULL);400}401delete _cpu_info;402}403}404405int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {406if (NULL == _cpu_info) {407return OS_ERR;408}409410cpu_info = *_cpu_info; // shallow copy assignment411return OS_OK;412}413414class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {415friend class NetworkPerformanceInterface;416private:417NetworkPerformance();418NetworkPerformance(const NetworkPerformance& rhs); // no impl419NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl420bool initialize();421~NetworkPerformance();422int network_utilization(NetworkInterface** network_interfaces) const;423};424425NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {426}427428bool NetworkPerformanceInterface::NetworkPerformance::initialize() {429return true;430}431432NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {433}434435int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const {436size_t len;437int mib[] = {CTL_NET, PF_ROUTE, /* protocol number */ 0, /* address family */ 0, NET_RT_IFLIST2, /* NET_RT_FLAGS mask*/ 0};438if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) != 0) {439return OS_ERR;440}441uint8_t* buf = NEW_RESOURCE_ARRAY(uint8_t, len);442if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &len, NULL, 0) != 0) {443return OS_ERR;444}445446size_t index = 0;447NetworkInterface* ret = NULL;448while (index < len) {449if_msghdr* msghdr = reinterpret_cast<if_msghdr*>(buf + index);450index += msghdr->ifm_msglen;451452if (msghdr->ifm_type != RTM_IFINFO2) {453continue;454}455456if_msghdr2* msghdr2 = reinterpret_cast<if_msghdr2*>(msghdr);457sockaddr_dl* sockaddr = reinterpret_cast<sockaddr_dl*>(msghdr2 + 1);458459// The interface name is not necessarily NUL-terminated460char name_buf[128];461size_t name_len = MIN2(sizeof(name_buf) - 1, static_cast<size_t>(sockaddr->sdl_nlen));462strncpy(name_buf, sockaddr->sdl_data, name_len);463name_buf[name_len] = '\0';464465uint64_t bytes_in = msghdr2->ifm_data.ifi_ibytes;466uint64_t bytes_out = msghdr2->ifm_data.ifi_obytes;467468NetworkInterface* cur = new NetworkInterface(name_buf, bytes_in, bytes_out, ret);469ret = cur;470}471472*network_interfaces = ret;473474return OS_OK;475}476477NetworkPerformanceInterface::NetworkPerformanceInterface() {478_impl = NULL;479}480481NetworkPerformanceInterface::~NetworkPerformanceInterface() {482if (_impl != NULL) {483delete _impl;484}485}486487bool NetworkPerformanceInterface::initialize() {488_impl = new NetworkPerformanceInterface::NetworkPerformance();489return _impl != NULL && _impl->initialize();490}491492int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {493return _impl->network_utilization(network_interfaces);494}495496497