Path: blob/master/src/hotspot/os/linux/os_perf_linux.cpp
40951 views
/*1* Copyright (c) 2012, 2020, 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*/2324#include "precompiled.hpp"25#include "jvm.h"26#include "memory/allocation.inline.hpp"27#include "os_linux.inline.hpp"28#include "runtime/os.hpp"29#include "runtime/os_perf.hpp"30#include "utilities/globalDefinitions.hpp"3132#include CPU_HEADER(vm_version_ext)3334#include <stdio.h>35#include <stdarg.h>36#include <unistd.h>37#include <errno.h>38#include <string.h>39#include <sys/resource.h>40#include <sys/types.h>41#include <sys/stat.h>42#include <dirent.h>43#include <stdlib.h>44#include <dlfcn.h>45#include <pthread.h>46#include <limits.h>47#ifndef __ANDROID__48#include <ifaddrs.h>49#else50#include <sys/cdefs.h>51#include <netinet/in.h>52#include <sys/socket.h>53#include <linux/if_packet.h>54#include <linux/netlink.h>55#include <linux/rtnetlink.h>56#include <net/if.h>57#include <stdint.h>58#endif59#include <fcntl.h>6061#ifdef __ANDROID__62/*63* Copyright (C) 2015 The Android Open Source Project64* All rights reserved.65*66* Redistribution and use in source and binary forms, with or without67* modification, are permitted provided that the following conditions68* are met:69* * Redistributions of source code must retain the above copyright70* notice, this list of conditions and the following disclaimer.71* * Redistributions in binary form must reproduce the above copyright72* notice, this list of conditions and the following disclaimer in73* the documentation and/or other materials provided with the74* distribution.75*76* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS77* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT78* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS79* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE80* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,81* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,82* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS83* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED84* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,85* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT86* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF87* SUCH DAMAGE.88*/8990__BEGIN_DECLS9192/**93* Returned by getifaddrs() and freed by freeifaddrs().94*/95struct ifaddrs {96/** Pointer to the next element in the linked list. */97struct ifaddrs* ifa_next;9899/** Interface name. */100char* ifa_name;101102/** Interface flags (like `SIOCGIFFLAGS`). */103unsigned int ifa_flags;104105/** Interface address. */106struct sockaddr* ifa_addr;107108/** Interface netmask. */109struct sockaddr* ifa_netmask;110111union {112/** Interface broadcast address (if IFF_BROADCAST is set). */113struct sockaddr* ifu_broadaddr;114115/** Interface destination address (if IFF_POINTOPOINT is set). */116struct sockaddr* ifu_dstaddr;117} ifa_ifu;118119/** Unused. */120void* ifa_data;121};122123/** Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. */124#define ifa_broadaddr ifa_ifu.ifu_broadaddr125126/** Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. */127#define ifa_dstaddr ifa_ifu.ifu_dstaddr128129/**130* [getifaddrs(3)](http://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list131* of `struct ifaddrs`. The list must be freed by freeifaddrs().132*133* Returns 0 and stores the list in `*__list_ptr` on success,134* and returns -1 and sets `errno` on failure.135*136* Available since API level 24.137*/138int getifaddrs(struct ifaddrs** __list_ptr); // __INTRODUCED_IN(24);139140/**141* [freeifaddrs(3)](http://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list142* of `struct ifaddrs` returned by getifaddrs().143*144* Available since API level 24.145*/146void freeifaddrs(struct ifaddrs* __ptr); // __INTRODUCED_IN(24);147148__END_DECLS149150#define nullptr 0151152// The public ifaddrs struct is full of pointers. Rather than track several153// different allocations, we use a maximally-sized structure with the public154// part at offset 0, and pointers into its hidden tail.155struct ifaddrs_storage {156// Must come first, so that `ifaddrs_storage` is-a `ifaddrs`.157ifaddrs ifa;158// The interface index, so we can match RTM_NEWADDR messages with159// earlier RTM_NEWLINK messages (to copy the interface flags).160int interface_index;161// Storage for the pointers in `ifa`.162sockaddr_storage addr;163sockaddr_storage netmask;164sockaddr_storage ifa_ifu;165char name[IFNAMSIZ + 1];166// Netlink gives us the address family in the header, and the167// sockaddr_in or sockaddr_in6 bytes as the payload. We need to168// stitch the two bits together into the sockaddr that's part of169// our portable interface.170void SetAddress(int family, const void* data, size_t byteCount) {171addr.ss_family = family;172memcpy(SockaddrBytes(family, &addr), data, byteCount);173ifa.ifa_addr = reinterpret_cast<sockaddr*>(&addr);174}175void SetBroadcastAddress(int family, const void* data, size_t byteCount) {176ifa_ifu.ss_family = family;177memcpy(SockaddrBytes(family, &ifa_ifu), data, byteCount);178ifa.ifa_dstaddr = reinterpret_cast<sockaddr*>(&ifa_ifu);179}180// Netlink gives us the prefix length as a bit count. We need to turn181// that into a BSD-compatible netmask represented by a sockaddr*.182void SetNetmask(int family, size_t prefix_length) {183// ...and work out the netmask from the prefix length.184netmask.ss_family = family;185uint8_t* dst = SockaddrBytes(family, &netmask);186memset(dst, 0xff, prefix_length / 8);187if ((prefix_length % 8) != 0) {188dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));189}190ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);191}192void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) {193sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(&addr);194sll->sll_ifindex = ifindex;195sll->sll_hatype = hatype;196sll->sll_halen = halen;197}198private:199// Returns a pointer to the first byte in the address data (which is200// stored in network byte order).201uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) {202if (family == AF_INET) {203sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);204return reinterpret_cast<uint8_t*>(&ss4->sin_addr);205} else if (family == AF_INET6) {206sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);207return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);208} else if (family == AF_PACKET) {209sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ss);210return reinterpret_cast<uint8_t*>(&sll->sll_addr);211}212return nullptr;213}214};215ifaddrs_storage* new_ifaddrs_storage(ifaddrs** list) {216ifaddrs_storage *storage;217memset(storage, 0, sizeof(*storage));218// push_front onto `list`.219storage->ifa.ifa_next = *list;220*list = reinterpret_cast<ifaddrs*>(storage);221return storage;222}223#if !defined(__clang__)224// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style225// cast is from a system header and should be ignored.226#pragma GCC diagnostic ignored "-Wold-style-cast"227#endif228static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {229if (hdr->nlmsg_type == RTM_NEWLINK) {230ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));231// Create a new ifaddr entry, and set the interface index and flags.232ifaddrs_storage* new_addr = new_ifaddrs_storage(out);233new_addr->interface_index = ifi->ifi_index;234new_addr->ifa.ifa_flags = ifi->ifi_flags;235// Go through the various bits of information and find the name.236rtattr* rta = IFLA_RTA(ifi);237size_t rta_len = IFLA_PAYLOAD(hdr);238while (RTA_OK(rta, rta_len)) {239if (rta->rta_type == IFLA_ADDRESS) {240if (RTA_PAYLOAD(rta) < sizeof(new_addr->addr)) {241new_addr->SetAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));242new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));243}244} else if (rta->rta_type == IFLA_BROADCAST) {245if (RTA_PAYLOAD(rta) < sizeof(new_addr->ifa_ifu)) {246new_addr->SetBroadcastAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));247new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));248}249} else if (rta->rta_type == IFLA_IFNAME) {250if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) {251memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta));252new_addr->ifa.ifa_name = new_addr->name;253}254}255rta = RTA_NEXT(rta, rta_len);256}257} else if (hdr->nlmsg_type == RTM_NEWADDR) {258ifaddrmsg* msg = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));259// We should already know about this from an RTM_NEWLINK message.260const ifaddrs_storage* addr = reinterpret_cast<const ifaddrs_storage*>(*out);261while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {262addr = reinterpret_cast<const ifaddrs_storage*>(addr->ifa.ifa_next);263}264// If this is an unknown interface, ignore whatever we're being told about it.265if (addr == nullptr) return;266// Create a new ifaddr entry and copy what we already know.267ifaddrs_storage* new_addr = new_ifaddrs_storage(out);268// We can just copy the name rather than look for IFA_LABEL.269strcpy(new_addr->name, addr->name);270new_addr->ifa.ifa_name = new_addr->name;271new_addr->ifa.ifa_flags = addr->ifa.ifa_flags;272new_addr->interface_index = addr->interface_index;273// Go through the various bits of information and find the address274// and any broadcast/destination address.275rtattr* rta = IFA_RTA(msg);276size_t rta_len = IFA_PAYLOAD(hdr);277while (RTA_OK(rta, rta_len)) {278if (rta->rta_type == IFA_ADDRESS) {279if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {280new_addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));281new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);282}283} else if (rta->rta_type == IFA_BROADCAST) {284if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {285new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));286}287}288rta = RTA_NEXT(rta, rta_len);289}290}291}292static bool __send_netlink_request(int fd, int type) {293struct NetlinkMessage {294nlmsghdr hdr;295rtgenmsg msg;296} request;297memset(&request, 0, sizeof(request));298request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;299request.hdr.nlmsg_type = type;300request.hdr.nlmsg_len = sizeof(request);301request.msg.rtgen_family = AF_UNSPEC; // All families.302return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request));303}304static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) {305ssize_t bytes_read;306// Read through all the responses, handing interesting ones to __handle_netlink_response.307while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) {308nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf);309for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {310if (hdr->nlmsg_type == NLMSG_DONE) return true;311if (hdr->nlmsg_type == NLMSG_ERROR) return false;312__handle_netlink_response(out, hdr);313}314}315// We only get here if recv fails before we see a NLMSG_DONE.316return false;317}318int getifaddrs(ifaddrs** out) {319// Make cleanup easy.320*out = nullptr;321// The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),322// but that's a bit too large to go on the stack.323size_t buf_len = 8192;324char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);325if (buf == nullptr) return -1;326// Open the netlink socket and ask for all the links and addresses.327int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);328bool okay = fd != -1 &&329__send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) &&330__send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len);331if (!okay) {332freeifaddrs(*out);333// Ensure that callers crash if they forget to check for success.334*out = nullptr;335}336{337int saved_errno = errno;338close(fd);339FREE_C_HEAP_ARRAY(char, buf);340errno = saved_errno;341}342return okay ? 0 : -1;343}344void freeifaddrs(ifaddrs* list) {345while (list != nullptr) {346ifaddrs* current = list;347list = list->ifa_next;348free(current);349}350}351#endif352353/**354/proc/[number]/stat355Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c.356357The fields, in order, with their proper scanf(3) format specifiers, are:3583591. pid %d The process id.3603612. comm %s362The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out.3633643. state %c365One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk366sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging.3673684. ppid %d369The PID of the parent.3703715. pgrp %d372The process group ID of the process.3733746. session %d375The session ID of the process.3763777. tty_nr %d378The tty the process uses.3793808. tpgid %d381The process group ID of the process which currently owns the tty that the process is connected to.3823839. flags %lu384The flags of the process. The math bit is decimal 4, and the traced bit is decimal 10.38538610. minflt %lu387The number of minor faults the process has made which have not required loading a memory page from disk.38838911. cminflt %lu390The number of minor faults that the process's waited-for children have made.39139212. majflt %lu393The number of major faults the process has made which have required loading a memory page from disk.39439513. cmajflt %lu396The number of major faults that the process's waited-for children have made.39739814. utime %lu399The number of jiffies that this process has been scheduled in user mode.40040115. stime %lu402The number of jiffies that this process has been scheduled in kernel mode.40340416. cutime %ld405The number of jiffies that this process's waited-for children have been scheduled in user mode. (See also times(2).)40640717. cstime %ld408The number of jiffies that this process' waited-for children have been scheduled in kernel mode.40941018. priority %ld411The standard nice value, plus fifteen. The value is never negative in the kernel.41241319. nice %ld414The nice value ranges from 19 (nicest) to -19 (not nice to others).41541620. 0 %ld This value is hard coded to 0 as a placeholder for a removed field.41741821. itrealvalue %ld419The time in jiffies before the next SIGALRM is sent to the process due to an interval timer.42042122. starttime %lu422The time in jiffies the process started after system boot.42342423. vsize %lu425Virtual memory size in bytes.42642724. rss %ld428Resident Set Size: number of pages the process has in real memory, minus 3 for administrative purposes. This is just the pages which count429towards text, data, or stack space. This does not include pages which have not been demand-loaded in, or which are swapped out.43043125. rlim %lu432Current limit in bytes on the rss of the process (usually 4294967295 on i386).43343426. startcode %lu435The address above which program text can run.43643727. endcode %lu438The address below which program text can run.43944028. startstack %lu441The address of the start of the stack.44244329. kstkesp %lu444The current value of esp (stack pointer), as found in the kernel stack page for the process.44544630. kstkeip %lu447The current EIP (instruction pointer).44844931. signal %lu450The bitmap of pending signals (usually 0).45145232. blocked %lu453The bitmap of blocked signals (usually 0, 2 for shells).45445533. sigignore %lu456The bitmap of ignored signals.45745834. sigcatch %lu459The bitmap of catched signals.46046135. wchan %lu462This is the "channel" in which the process is waiting. It is the address of a system call, and can be looked up in a namelist if you need463a textual name. (If you have an up-to-date /etc/psdatabase, then try ps -l to see the WCHAN field in action.)46446536. nswap %lu466Number of pages swapped - not maintained.46746837. cnswap %lu469Cumulative nswap for child processes.47047138. exit_signal %d472Signal to be sent to parent when we die.47347439. processor %d475CPU number last executed on.476477478479///// SSCANF FORMAT STRING. Copy and use.480481field: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39482format: %d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d483484485*/486487/**488* For platforms that have them, when declaring489* a printf-style function,490* formatSpec is the parameter number (starting at 1)491* that is the format argument ("%d pid %s")492* params is the parameter number where the actual args to493* the format starts. If the args are in a va_list, this494* should be 0.495*/496#ifndef PRINTF_ARGS497# define PRINTF_ARGS(formatSpec, params) ATTRIBUTE_PRINTF(formatSpec, params)498#endif499500#ifndef SCANF_ARGS501# define SCANF_ARGS(formatSpec, params) ATTRIBUTE_SCANF(formatSpec, params)502#endif503504#ifndef _PRINTFMT_505# define _PRINTFMT_506#endif507508#ifndef _SCANFMT_509# define _SCANFMT_510#endif511512typedef enum {513CPU_LOAD_VM_ONLY,514CPU_LOAD_GLOBAL,515} CpuLoadTarget;516517enum {518UNDETECTED,519UNDETECTABLE,520LINUX26_NPTL,521BAREMETAL522};523524struct CPUPerfCounters {525int nProcs;526os::Linux::CPUPerfTicks jvmTicks;527os::Linux::CPUPerfTicks* cpus;528};529530static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);531532/** reads /proc/<pid>/stat data, with some checks and some skips.533* Ensure that 'fmt' does _NOT_ contain the first two "%d %s"534*/535static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) {536FILE*f;537int n;538char buf[2048];539540if ((f = fopen(procfile, "r")) == NULL) {541return -1;542}543544if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {545char *tmp;546547buf[n-1] = '\0';548/** skip through pid and exec name. */549if ((tmp = strrchr(buf, ')')) != NULL) {550// skip the ')' and the following space551// but check that buffer is long enough552tmp += 2;553if (tmp < buf + n) {554n = vsscanf(tmp, fmt, args);555}556}557}558559fclose(f);560561return n;562}563564static int SCANF_ARGS(2, 3) read_statdata(const char* procfile, _SCANFMT_ const char* fmt, ...) {565int n;566va_list args;567568va_start(args, fmt);569n = vread_statdata(procfile, fmt, args);570va_end(args);571return n;572}573574static FILE* open_statfile(void) {575FILE *f;576577if ((f = fopen("/proc/stat", "r")) == NULL) {578static int haveWarned = 0;579if (!haveWarned) {580haveWarned = 1;581}582}583return f;584}585586static int get_systemtype(void) {587static int procEntriesType = UNDETECTED;588DIR *taskDir;589590if (procEntriesType != UNDETECTED) {591return procEntriesType;592}593594// Check whether we have a task subdirectory595if ((taskDir = opendir("/proc/self/task")) == NULL) {596procEntriesType = UNDETECTABLE;597} else {598// The task subdirectory exists; we're on a Linux >= 2.6 system599closedir(taskDir);600procEntriesType = LINUX26_NPTL;601}602603return procEntriesType;604}605606/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */607static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* systemTicks) {608return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u " UINT64_FORMAT " " UINT64_FORMAT,609userTicks, systemTicks);610}611612/**613* Return the number of ticks spent in any of the processes belonging614* to the JVM on any CPU.615*/616static OSReturn get_jvm_ticks(os::Linux::CPUPerfTicks* pticks) {617uint64_t userTicks;618uint64_t systemTicks;619620if (get_systemtype() != LINUX26_NPTL) {621return OS_ERR;622}623624if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) {625return OS_ERR;626}627628// get the total629if (! os::Linux::get_tick_information(pticks, -1)) {630return OS_ERR;631}632633pticks->used = userTicks;634pticks->usedKernel = systemTicks;635636return OS_OK;637}638639/**640* Return the load of the CPU as a double. 1.0 means the CPU process uses all641* available time for user or system processes, 0.0 means the CPU uses all time642* being idle.643*644* Returns a negative value if there is a problem in determining the CPU load.645*/646static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {647uint64_t udiff, kdiff, tdiff;648os::Linux::CPUPerfTicks* pticks;649os::Linux::CPUPerfTicks tmp;650double user_load;651652*pkernelLoad = 0.0;653654if (target == CPU_LOAD_VM_ONLY) {655pticks = &counters->jvmTicks;656} else if (-1 == which_logical_cpu) {657pticks = &counters->cpus[counters->nProcs];658} else {659pticks = &counters->cpus[which_logical_cpu];660}661662tmp = *pticks;663664if (target == CPU_LOAD_VM_ONLY) {665if (get_jvm_ticks(pticks) != OS_OK) {666return -1.0;667}668} else if (! os::Linux::get_tick_information(pticks, which_logical_cpu)) {669return -1.0;670}671672// seems like we sometimes end up with less kernel ticks when673// reading /proc/self/stat a second time, timing issue between cpus?674if (pticks->usedKernel < tmp.usedKernel) {675kdiff = 0;676} else {677kdiff = pticks->usedKernel - tmp.usedKernel;678}679tdiff = pticks->total - tmp.total;680udiff = pticks->used - tmp.used;681682if (tdiff == 0) {683return 0.0;684} else if (tdiff < (udiff + kdiff)) {685tdiff = udiff + kdiff;686}687*pkernelLoad = (kdiff / (double)tdiff);688// BUG9044876, normalize return values to sane values689*pkernelLoad = MAX2<double>(*pkernelLoad, 0.0);690*pkernelLoad = MIN2<double>(*pkernelLoad, 1.0);691692user_load = (udiff / (double)tdiff);693user_load = MAX2<double>(user_load, 0.0);694user_load = MIN2<double>(user_load, 1.0);695696return user_load;697}698699static int SCANF_ARGS(1, 2) parse_stat(_SCANFMT_ const char* fmt, ...) {700FILE *f;701va_list args;702703va_start(args, fmt);704705if ((f = open_statfile()) == NULL) {706va_end(args);707return OS_ERR;708}709for (;;) {710char line[80];711if (fgets(line, sizeof(line), f) != NULL) {712if (vsscanf(line, fmt, args) == 1) {713fclose(f);714va_end(args);715return OS_OK;716}717} else {718fclose(f);719va_end(args);720return OS_ERR;721}722}723}724725static int get_noof_context_switches(uint64_t* switches) {726return parse_stat("ctxt " UINT64_FORMAT "\n", switches);727}728729/** returns boot time in _seconds_ since epoch */730static int get_boot_time(uint64_t* time) {731return parse_stat("btime " UINT64_FORMAT "\n", time);732}733734static int perf_context_switch_rate(double* rate) {735static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;736static uint64_t bootTime;737static uint64_t lastTimeNanos;738static uint64_t lastSwitches;739static double lastRate;740741uint64_t bt = 0;742int res = 0;743744// First time through bootTime will be zero.745if (bootTime == 0) {746uint64_t tmp;747if (get_boot_time(&tmp) < 0) {748return OS_ERR;749}750bt = tmp * 1000;751}752753res = OS_OK;754755pthread_mutex_lock(&contextSwitchLock);756{757758uint64_t sw;759s8 t, d;760761if (bootTime == 0) {762// First interval is measured from boot time which is763// seconds since the epoch. Thereafter we measure the764// elapsed time using javaTimeNanos as it is monotonic-765// non-decreasing.766lastTimeNanos = os::javaTimeNanos();767t = os::javaTimeMillis();768d = t - bt;769// keep bootTime zero for now to use as a first-time-through flag770} else {771t = os::javaTimeNanos();772d = nanos_to_millis(t - lastTimeNanos);773}774775if (d == 0) {776*rate = lastRate;777} else if (get_noof_context_switches(&sw) == 0) {778*rate = ( (double)(sw - lastSwitches) / d ) * 1000;779lastRate = *rate;780lastSwitches = sw;781if (bootTime != 0) {782lastTimeNanos = t;783}784} else {785*rate = 0;786res = OS_ERR;787}788if (*rate <= 0) {789*rate = 0;790lastRate = 0;791}792793if (bootTime == 0) {794bootTime = bt;795}796}797pthread_mutex_unlock(&contextSwitchLock);798799return res;800}801802class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {803friend class CPUPerformanceInterface;804private:805CPUPerfCounters _counters;806807int cpu_load(int which_logical_cpu, double* cpu_load);808int context_switch_rate(double* rate);809int cpu_load_total_process(double* cpu_load);810int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);811812public:813CPUPerformance();814bool initialize();815~CPUPerformance();816};817818CPUPerformanceInterface::CPUPerformance::CPUPerformance() {819_counters.nProcs = os::active_processor_count();820_counters.cpus = NULL;821}822823bool CPUPerformanceInterface::CPUPerformance::initialize() {824size_t array_entry_count = _counters.nProcs + 1;825_counters.cpus = NEW_C_HEAP_ARRAY(os::Linux::CPUPerfTicks, array_entry_count, mtInternal);826memset(_counters.cpus, 0, array_entry_count * sizeof(*_counters.cpus));827828// For the CPU load total829os::Linux::get_tick_information(&_counters.cpus[_counters.nProcs], -1);830831// For each CPU832for (int i = 0; i < _counters.nProcs; i++) {833os::Linux::get_tick_information(&_counters.cpus[i], i);834}835// For JVM load836get_jvm_ticks(&_counters.jvmTicks);837838// initialize context switch system839// the double is only for init840double init_ctx_switch_rate;841perf_context_switch_rate(&init_ctx_switch_rate);842843return true;844}845846CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {847if (_counters.cpus != NULL) {848FREE_C_HEAP_ARRAY(char, _counters.cpus);849}850}851852int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {853double u, s;854u = get_cpu_load(which_logical_cpu, &_counters, &s, CPU_LOAD_GLOBAL);855if (u < 0) {856*cpu_load = 0.0;857return OS_ERR;858}859// Cap total systemload to 1.0860*cpu_load = MIN2<double>((u + s), 1.0);861return OS_OK;862}863864int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {865double u, s;866u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY);867if (u < 0) {868*cpu_load = 0.0;869return OS_ERR;870}871*cpu_load = u + s;872return OS_OK;873}874875int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {876double u, s, t;877878assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");879assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");880assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");881882u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY);883if (u < 0) {884*pjvmUserLoad = 0.0;885*pjvmKernelLoad = 0.0;886*psystemTotalLoad = 0.0;887return OS_ERR;888}889890cpu_load(-1, &t);891// clamp at user+system and 1.0892if (u + s > t) {893t = MIN2<double>(u + s, 1.0);894}895896*pjvmUserLoad = u;897*pjvmKernelLoad = s;898*psystemTotalLoad = t;899900return OS_OK;901}902903int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {904return perf_context_switch_rate(rate);905}906907CPUPerformanceInterface::CPUPerformanceInterface() {908_impl = NULL;909}910911bool CPUPerformanceInterface::initialize() {912_impl = new CPUPerformanceInterface::CPUPerformance();913return _impl->initialize();914}915916CPUPerformanceInterface::~CPUPerformanceInterface() {917if (_impl != NULL) {918delete _impl;919}920}921922int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {923return _impl->cpu_load(which_logical_cpu, cpu_load);924}925926int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {927return _impl->cpu_load_total_process(cpu_load);928}929930int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {931return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);932}933934int CPUPerformanceInterface::context_switch_rate(double* rate) const {935return _impl->context_switch_rate(rate);936}937938class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {939friend class SystemProcessInterface;940private:941class ProcessIterator : public CHeapObj<mtInternal> {942friend class SystemProcessInterface::SystemProcesses;943private:944DIR* _dir;945struct dirent* _entry;946bool _valid;947char _exeName[PATH_MAX];948char _exePath[PATH_MAX];949950ProcessIterator();951~ProcessIterator();952bool initialize();953954bool is_valid() const { return _valid; }955bool is_valid_entry(struct dirent* entry) const;956bool is_dir(const char* name) const;957int fsize(const char* name, uint64_t& size) const;958959char* allocate_string(const char* str) const;960void get_exe_name();961char* get_exe_path();962char* get_cmdline();963964int current(SystemProcess* process_info);965int next_process();966};967968ProcessIterator* _iterator;969SystemProcesses();970bool initialize();971~SystemProcesses();972973//information about system processes974int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;975};976977bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {978struct stat mystat;979int ret_val = 0;980981ret_val = stat(name, &mystat);982if (ret_val < 0) {983return false;984}985ret_val = S_ISDIR(mystat.st_mode);986return ret_val > 0;987}988989int SystemProcessInterface::SystemProcesses::ProcessIterator::fsize(const char* name, uint64_t& size) const {990assert(name != NULL, "name pointer is NULL!");991size = 0;992struct stat fbuf;993994if (stat(name, &fbuf) < 0) {995return OS_ERR;996}997size = fbuf.st_size;998return OS_OK;999}10001001// if it has a numeric name, is a directory and has a 'stat' file in it1002bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {1003char buffer[PATH_MAX];1004uint64_t size = 0;10051006if (atoi(entry->d_name) != 0) {1007jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);1008buffer[PATH_MAX - 1] = '\0';10091010if (is_dir(buffer)) {1011jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", entry->d_name);1012buffer[PATH_MAX - 1] = '\0';1013if (fsize(buffer, size) != OS_ERR) {1014return true;1015}1016}1017}1018return false;1019}10201021// get exe-name from /proc/<pid>/stat1022void SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_name() {1023FILE* fp;1024char buffer[PATH_MAX];10251026jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", _entry->d_name);1027buffer[PATH_MAX - 1] = '\0';1028if ((fp = fopen(buffer, "r")) != NULL) {1029if (fgets(buffer, PATH_MAX, fp) != NULL) {1030char* start, *end;1031// exe-name is between the first pair of ( and )1032start = strchr(buffer, '(');1033if (start != NULL && start[1] != '\0') {1034start++;1035end = strrchr(start, ')');1036if (end != NULL) {1037size_t len;1038len = MIN2<size_t>(end - start, sizeof(_exeName) - 1);1039memcpy(_exeName, start, len);1040_exeName[len] = '\0';1041}1042}1043}1044fclose(fp);1045}1046}10471048// get command line from /proc/<pid>/cmdline1049char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_cmdline() {1050FILE* fp;1051char buffer[PATH_MAX];1052char* cmdline = NULL;10531054jio_snprintf(buffer, PATH_MAX, "/proc/%s/cmdline", _entry->d_name);1055buffer[PATH_MAX - 1] = '\0';1056if ((fp = fopen(buffer, "r")) != NULL) {1057size_t size = 0;1058char dummy;10591060// find out how long the file is (stat always returns 0)1061while (fread(&dummy, 1, 1, fp) == 1) {1062size++;1063}1064if (size > 0) {1065cmdline = NEW_C_HEAP_ARRAY(char, size + 1, mtInternal);1066cmdline[0] = '\0';1067if (fseek(fp, 0, SEEK_SET) == 0) {1068if (fread(cmdline, 1, size, fp) == size) {1069// the file has the arguments separated by '\0',1070// so we translate '\0' to ' '1071for (size_t i = 0; i < size; i++) {1072if (cmdline[i] == '\0') {1073cmdline[i] = ' ';1074}1075}1076cmdline[size] = '\0';1077}1078}1079}1080fclose(fp);1081}1082return cmdline;1083}10841085// get full path to exe from /proc/<pid>/exe symlink1086char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_path() {1087char buffer[PATH_MAX];10881089jio_snprintf(buffer, PATH_MAX, "/proc/%s/exe", _entry->d_name);1090buffer[PATH_MAX - 1] = '\0';1091return realpath(buffer, _exePath);1092}10931094char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {1095if (str != NULL) {1096return os::strdup_check_oom(str, mtInternal);1097}1098return NULL;1099}11001101int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {1102if (!is_valid()) {1103return OS_ERR;1104}11051106process_info->set_pid(atoi(_entry->d_name));11071108get_exe_name();1109process_info->set_name(allocate_string(_exeName));11101111if (get_exe_path() != NULL) {1112process_info->set_path(allocate_string(_exePath));1113}11141115char* cmdline = NULL;1116cmdline = get_cmdline();1117if (cmdline != NULL) {1118process_info->set_command_line(allocate_string(cmdline));1119FREE_C_HEAP_ARRAY(char, cmdline);1120}11211122return OS_OK;1123}11241125int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {1126if (!is_valid()) {1127return OS_ERR;1128}11291130do {1131_entry = os::readdir(_dir);1132if (_entry == NULL) {1133// Error or reached end. Could use errno to distinguish those cases.1134_valid = false;1135return OS_ERR;1136}1137} while(!is_valid_entry(_entry));11381139_valid = true;1140return OS_OK;1141}11421143SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {1144_dir = NULL;1145_entry = NULL;1146_valid = false;1147}11481149bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {1150_dir = os::opendir("/proc");1151_entry = NULL;1152_valid = true;1153next_process();11541155return true;1156}11571158SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {1159if (_dir != NULL) {1160os::closedir(_dir);1161}1162}11631164SystemProcessInterface::SystemProcesses::SystemProcesses() {1165_iterator = NULL;1166}11671168bool SystemProcessInterface::SystemProcesses::initialize() {1169_iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();1170return _iterator->initialize();1171}11721173SystemProcessInterface::SystemProcesses::~SystemProcesses() {1174if (_iterator != NULL) {1175delete _iterator;1176}1177}11781179int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {1180assert(system_processes != NULL, "system_processes pointer is NULL!");1181assert(no_of_sys_processes != NULL, "system_processes counter pointers is NULL!");1182assert(_iterator != NULL, "iterator is NULL!");11831184// initialize pointers1185*no_of_sys_processes = 0;1186*system_processes = NULL;11871188while (_iterator->is_valid()) {1189SystemProcess* tmp = new SystemProcess();1190_iterator->current(tmp);11911192//if already existing head1193if (*system_processes != NULL) {1194//move "first to second"1195tmp->set_next(*system_processes);1196}1197// new head1198*system_processes = tmp;1199// increment1200(*no_of_sys_processes)++;1201// step forward1202_iterator->next_process();1203}1204return OS_OK;1205}12061207int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {1208return _impl->system_processes(system_procs, no_of_sys_processes);1209}12101211SystemProcessInterface::SystemProcessInterface() {1212_impl = NULL;1213}12141215bool SystemProcessInterface::initialize() {1216_impl = new SystemProcessInterface::SystemProcesses();1217return _impl->initialize();1218}12191220SystemProcessInterface::~SystemProcessInterface() {1221if (_impl != NULL) {1222delete _impl;1223}1224}12251226CPUInformationInterface::CPUInformationInterface() {1227_cpu_info = NULL;1228}12291230bool CPUInformationInterface::initialize() {1231_cpu_info = new CPUInformation();1232_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());1233_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());1234_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());1235_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());1236_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());1237return true;1238}12391240CPUInformationInterface::~CPUInformationInterface() {1241if (_cpu_info != NULL) {1242if (_cpu_info->cpu_name() != NULL) {1243const char* cpu_name = _cpu_info->cpu_name();1244FREE_C_HEAP_ARRAY(char, cpu_name);1245_cpu_info->set_cpu_name(NULL);1246}1247if (_cpu_info->cpu_description() != NULL) {1248const char* cpu_desc = _cpu_info->cpu_description();1249FREE_C_HEAP_ARRAY(char, cpu_desc);1250_cpu_info->set_cpu_description(NULL);1251}1252delete _cpu_info;1253}1254}12551256int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {1257if (_cpu_info == NULL) {1258return OS_ERR;1259}12601261cpu_info = *_cpu_info; // shallow copy assignment1262return OS_OK;1263}12641265class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {1266friend class NetworkPerformanceInterface;1267private:1268NetworkPerformance();1269NONCOPYABLE(NetworkPerformance);1270bool initialize();1271~NetworkPerformance();1272int64_t read_counter(const char* iface, const char* counter) const;1273int network_utilization(NetworkInterface** network_interfaces) const;1274};12751276NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {12771278}12791280bool NetworkPerformanceInterface::NetworkPerformance::initialize() {1281return true;1282}12831284NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {1285}12861287int64_t NetworkPerformanceInterface::NetworkPerformance::read_counter(const char* iface, const char* counter) const {1288char buf[128];12891290snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics/%s", iface, counter);12911292int fd = os::open(buf, O_RDONLY, 0);1293if (fd == -1) {1294return -1;1295}12961297ssize_t num_bytes = read(fd, buf, sizeof(buf));1298close(fd);1299if ((num_bytes == -1) || (num_bytes >= static_cast<ssize_t>(sizeof(buf))) || (num_bytes < 1)) {1300return -1;1301}13021303buf[num_bytes] = '\0';1304int64_t value = strtoll(buf, NULL, 10);13051306return value;1307}13081309int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const1310{1311ifaddrs* addresses;1312ifaddrs* cur_address;13131314if (getifaddrs(&addresses) != 0) {1315return OS_ERR;1316}13171318NetworkInterface* ret = NULL;1319for (cur_address = addresses; cur_address != NULL; cur_address = cur_address->ifa_next) {1320if ((cur_address->ifa_addr == NULL) || (cur_address->ifa_addr->sa_family != AF_PACKET)) {1321continue;1322}13231324int64_t bytes_in = read_counter(cur_address->ifa_name, "rx_bytes");1325int64_t bytes_out = read_counter(cur_address->ifa_name, "tx_bytes");13261327NetworkInterface* cur = new NetworkInterface(cur_address->ifa_name, bytes_in, bytes_out, ret);1328ret = cur;1329}13301331freeifaddrs(addresses);1332*network_interfaces = ret;13331334return OS_OK;1335}13361337NetworkPerformanceInterface::NetworkPerformanceInterface() {1338_impl = NULL;1339}13401341NetworkPerformanceInterface::~NetworkPerformanceInterface() {1342if (_impl != NULL) {1343delete _impl;1344}1345}13461347bool NetworkPerformanceInterface::initialize() {1348_impl = new NetworkPerformanceInterface::NetworkPerformance();1349return _impl->initialize();1350}13511352int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {1353return _impl->network_utilization(network_interfaces);1354}135513561357