1 /*
   2  * Copyright (c) 2012, 2020, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "jfr/jfrEvents.hpp"
  27 #include "jfr/periodic/jfrNetworkUtilization.hpp"
  28 #include "jfr/periodic/jfrOSInterface.hpp"
  29 #include "memory/allocation.inline.hpp"
  30 #include "memory/resourceArea.hpp"
  31 #include "runtime/os.hpp"
  32 #include "runtime/os_perf.hpp"
  33 #include "utilities/ostream.hpp"
  34 
  35 #include <stdlib.h> // for environment variables
  36 #ifdef __APPLE__
  37 #include <crt_externs.h>
  38 #define environ (*_NSGetEnviron())
  39 #endif
  40 
  41 #ifndef environ
  42 extern char** environ;
  43 #endif
  44 
  45 static JfrOSInterface* _instance = NULL;
  46 
  47 JfrOSInterface& JfrOSInterface::instance() {
  48   return *_instance;
  49 }
  50 
  51 JfrOSInterface* JfrOSInterface::create() {
  52   assert(_instance == NULL, "invariant");
  53   _instance = new JfrOSInterface();
  54   return _instance;
  55 }
  56 
  57 void JfrOSInterface::destroy() {
  58   JfrNetworkUtilization::destroy();
  59   if (_instance != NULL) {
  60     delete _instance;
  61     _instance = NULL;
  62   }
  63 }
  64 
  65 class JfrOSInterface::JfrOSInterfaceImpl : public JfrCHeapObj {
  66   friend class JfrOSInterface;
  67  private:
  68   CPUInformationInterface* _cpu_info_interface;
  69   CPUPerformanceInterface* _cpu_perf_interface;
  70   SystemProcessInterface* _system_process_interface;
  71   NetworkPerformanceInterface* _network_performance_interface;
  72 
  73   CPUInformationInterface* cpu_info_interface();
  74   CPUPerformanceInterface* cpu_perf_interface();
  75   SystemProcessInterface* system_process_interface();
  76   NetworkPerformanceInterface* network_performance_interface();
  77 
  78   JfrOSInterfaceImpl();
  79   bool initialize();
  80   ~JfrOSInterfaceImpl();
  81 
  82   // cpu info
  83   int cpu_information(CPUInformation& cpu_info);
  84   int cpu_load(int which_logical_cpu, double* cpu_load);
  85   int context_switch_rate(double* rate);
  86   int cpu_load_total_process(double* cpu_load);
  87   int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotal);
  88 
  89   // os information
  90   int os_version(char** os_version) const;
  91 
  92   // environment information
  93   void generate_environment_variables_events();
  94 
  95    // system processes information
  96   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes);
  97 
  98   int network_utilization(NetworkInterface** network_interfaces);
  99 };
 100 
 101 JfrOSInterface::JfrOSInterfaceImpl::JfrOSInterfaceImpl() : _cpu_info_interface(NULL),
 102                                                            _cpu_perf_interface(NULL),
 103                                                            _system_process_interface(NULL),
 104                                                            _network_performance_interface(NULL) {}
 105 
 106 template <typename T>
 107 static T* create_interface() {
 108   ResourceMark rm;
 109   T* iface = new T();
 110   if (iface != NULL) {
 111     if (!iface->initialize()) {
 112       delete iface;
 113       iface = NULL;
 114     }
 115   }
 116   return iface;
 117 }
 118 
 119 CPUInformationInterface* JfrOSInterface::JfrOSInterfaceImpl::cpu_info_interface() {
 120   if (_cpu_info_interface == NULL) {
 121     _cpu_info_interface = create_interface<CPUInformationInterface>();
 122   }
 123   return _cpu_info_interface;
 124 }
 125 
 126 CPUPerformanceInterface* JfrOSInterface::JfrOSInterfaceImpl::cpu_perf_interface() {
 127   if (_cpu_perf_interface == NULL) {
 128     _cpu_perf_interface = create_interface<CPUPerformanceInterface>();
 129   }
 130   return _cpu_perf_interface;
 131 }
 132 
 133 SystemProcessInterface* JfrOSInterface::JfrOSInterfaceImpl::system_process_interface() {
 134   if (_system_process_interface == NULL) {
 135     _system_process_interface = create_interface<SystemProcessInterface>();
 136   }
 137   return _system_process_interface;
 138 }
 139 
 140 NetworkPerformanceInterface* JfrOSInterface::JfrOSInterfaceImpl::network_performance_interface() {
 141   if (_network_performance_interface == NULL) {
 142     _network_performance_interface = create_interface<NetworkPerformanceInterface>();
 143   }
 144   return _network_performance_interface;
 145 }
 146 
 147 bool JfrOSInterface::JfrOSInterfaceImpl::initialize() {
 148   return true;
 149 }
 150 
 151 JfrOSInterface::JfrOSInterfaceImpl::~JfrOSInterfaceImpl(void) {
 152   if (_cpu_info_interface != NULL) {
 153     delete _cpu_info_interface;
 154     _cpu_info_interface = NULL;
 155   }
 156   if (_cpu_perf_interface != NULL) {
 157     delete _cpu_perf_interface;
 158     _cpu_perf_interface = NULL;
 159   }
 160   if (_system_process_interface != NULL) {
 161     delete _system_process_interface;
 162     _system_process_interface = NULL;
 163   }
 164   if (_network_performance_interface != NULL) {
 165     delete _network_performance_interface;
 166     _network_performance_interface = NULL;
 167   }
 168 }
 169 
 170 int JfrOSInterface::JfrOSInterfaceImpl::cpu_information(CPUInformation& cpu_info) {
 171   CPUInformationInterface* const iface = cpu_info_interface();
 172   return iface == NULL ? OS_ERR : iface->cpu_information(cpu_info);
 173 }
 174 
 175 int JfrOSInterface::JfrOSInterfaceImpl::cpu_load(int which_logical_cpu, double* cpu_load) {
 176   CPUPerformanceInterface* const iface = cpu_perf_interface();
 177   return iface == NULL ? OS_ERR : iface->cpu_load(which_logical_cpu, cpu_load);
 178 }
 179 
 180 int JfrOSInterface::JfrOSInterfaceImpl::context_switch_rate(double* rate) {
 181   CPUPerformanceInterface* const iface = cpu_perf_interface();
 182   return iface == NULL ? OS_ERR : iface->context_switch_rate(rate);
 183 }
 184 
 185 int JfrOSInterface::JfrOSInterfaceImpl::cpu_load_total_process(double* cpu_load) {
 186   CPUPerformanceInterface* const iface = cpu_perf_interface();
 187   return iface == NULL ? OS_ERR : iface->cpu_load_total_process(cpu_load);
 188 }
 189 
 190 int JfrOSInterface::JfrOSInterfaceImpl::cpu_loads_process(double* pjvmUserLoad,
 191                                                           double* pjvmKernelLoad,
 192                                                           double* psystemTotal) {
 193   CPUPerformanceInterface* const iface = cpu_perf_interface();
 194   return iface == NULL ? OS_ERR : iface->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotal);
 195 }
 196 
 197 int JfrOSInterface::JfrOSInterfaceImpl::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) {
 198   assert(system_processes != NULL, "system_processes pointer is NULL!");
 199   assert(no_of_sys_processes != NULL, "no_of_sys_processes pointer is NULL!");
 200   SystemProcessInterface* const iface = system_process_interface();
 201   return iface == NULL ? OS_ERR : iface->system_processes(system_processes, no_of_sys_processes);
 202 }
 203 
 204 int JfrOSInterface::JfrOSInterfaceImpl::network_utilization(NetworkInterface** network_interfaces) {
 205   NetworkPerformanceInterface* const iface = network_performance_interface();
 206   return iface == NULL ? OS_ERR : iface->network_utilization(network_interfaces);
 207 }
 208 
 209 // assigned char* is RESOURCE_HEAP_ALLOCATED
 210 // caller need to ensure proper ResourceMark placement.
 211 int JfrOSInterface::JfrOSInterfaceImpl::os_version(char** os_version) const {
 212   assert(os_version != NULL, "os_version pointer is NULL!");
 213   stringStream os_ver_info;
 214   os::print_os_info_brief(&os_ver_info);
 215   *os_version = os_ver_info.as_string();
 216   return OS_OK;
 217 }
 218 
 219 JfrOSInterface::JfrOSInterface() {
 220   _impl = NULL;
 221 }
 222 
 223 bool JfrOSInterface::initialize() {
 224   _impl = new JfrOSInterface::JfrOSInterfaceImpl();
 225   return _impl != NULL && _impl->initialize();
 226 }
 227 
 228 JfrOSInterface::~JfrOSInterface() {
 229   if (_impl != NULL) {
 230     delete _impl;
 231     _impl = NULL;
 232   }
 233 }
 234 
 235 int JfrOSInterface::cpu_information(CPUInformation& cpu_info) {
 236   return instance()._impl->cpu_information(cpu_info);
 237 }
 238 
 239 int JfrOSInterface::cpu_load(int which_logical_cpu, double* cpu_load) {
 240   return instance()._impl->cpu_load(which_logical_cpu, cpu_load);
 241 }
 242 
 243 int JfrOSInterface::context_switch_rate(double* rate) {
 244   return instance()._impl->context_switch_rate(rate);
 245 }
 246 
 247 int JfrOSInterface::cpu_load_total_process(double* cpu_load) {
 248   return instance()._impl->cpu_load_total_process(cpu_load);
 249 }
 250 
 251 int JfrOSInterface::cpu_loads_process(double* jvm_user_load, double* jvm_kernel_load, double* system_total_load){
 252   return instance()._impl->cpu_loads_process(jvm_user_load, jvm_kernel_load, system_total_load);
 253 }
 254 
 255 int JfrOSInterface::os_version(char** os_version) {
 256   return instance()._impl->os_version(os_version);
 257 }
 258 
 259 const char* JfrOSInterface::virtualization_name() {
 260   VirtualizationType vrt = VM_Version::get_detected_virtualization();
 261   if (vrt == XenHVM) {
 262     return "Xen hardware-assisted virtualization";
 263   } else if (vrt == KVM) {
 264     return "KVM virtualization";
 265   } else if (vrt == VMWare) {
 266     return "VMWare virtualization";
 267   } else if (vrt == HyperV) {
 268     return "Hyper-V virtualization";
 269   } else if (vrt == HyperVRole) {
 270     return "Hyper-V role";
 271   } else if (vrt == PowerVM) {
 272     return "PowerVM virtualization";
 273   } else if (vrt == PowerKVM) {
 274     return "Power KVM virtualization";
 275   } else if (vrt == PowerFullPartitionMode) {
 276     return "Power full partition";
 277   }
 278 
 279   return "No virtualization detected";
 280 }
 281 
 282 int JfrOSInterface::generate_initial_environment_variable_events() {
 283   if (environ == NULL) {
 284     return OS_ERR;
 285   }
 286 
 287   if (EventInitialEnvironmentVariable::is_enabled()) {
 288     // One time stamp for all events, so they can be grouped together
 289     JfrTicks time_stamp = JfrTicks::now();
 290     for (char** p = environ; *p != NULL; p++) {
 291       char* variable = *p;
 292       char* equal_sign = strchr(variable, '=');
 293       if (equal_sign != NULL) {
 294         // Extract key/value
 295         ResourceMark rm;
 296         ptrdiff_t key_length = equal_sign - variable;
 297         char* key = NEW_RESOURCE_ARRAY(char, key_length + 1);
 298         char* value = equal_sign + 1;
 299         strncpy(key, variable, key_length);
 300         key[key_length] = '\0';
 301         EventInitialEnvironmentVariable event(UNTIMED);
 302         event.set_endtime(time_stamp);
 303         event.set_key(key);
 304         event.set_value(value);
 305         event.commit();
 306       }
 307     }
 308   }
 309   return OS_OK;
 310 }
 311 
 312 int JfrOSInterface::system_processes(SystemProcess** sys_processes, int* no_of_sys_processes) {
 313   return instance()._impl->system_processes(sys_processes, no_of_sys_processes);
 314 }
 315 
 316 int JfrOSInterface::network_utilization(NetworkInterface** network_interfaces) {
 317   return instance()._impl->network_utilization(network_interfaces);
 318 }