1 /*
2  * Copyright (c) 2012, 2021, 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 "runtime/vm_version.hpp"
34 #include "utilities/ostream.hpp"
35 
36 #include <stdlib.h> // for environment variables
37 
38 static JfrOSInterface* _instance = NULL;
39 
instance()40 JfrOSInterface& JfrOSInterface::instance() {
41   return *_instance;
42 }
43 
create()44 JfrOSInterface* JfrOSInterface::create() {
45   assert(_instance == NULL, "invariant");
46   _instance = new JfrOSInterface();
47   return _instance;
48 }
49 
destroy()50 void JfrOSInterface::destroy() {
51   JfrNetworkUtilization::destroy();
52   if (_instance != NULL) {
53     delete _instance;
54     _instance = NULL;
55   }
56 }
57 
58 class JfrOSInterface::JfrOSInterfaceImpl : public JfrCHeapObj {
59   friend class JfrOSInterface;
60  private:
61   CPUInformationInterface* _cpu_info_interface;
62   CPUPerformanceInterface* _cpu_perf_interface;
63   SystemProcessInterface* _system_process_interface;
64   NetworkPerformanceInterface* _network_performance_interface;
65 
66   CPUInformationInterface* cpu_info_interface();
67   CPUPerformanceInterface* cpu_perf_interface();
68   SystemProcessInterface* system_process_interface();
69   NetworkPerformanceInterface* network_performance_interface();
70 
71   JfrOSInterfaceImpl();
72   bool initialize();
73   ~JfrOSInterfaceImpl();
74 
75   // cpu info
76   int cpu_information(CPUInformation& cpu_info);
77   int cpu_load(int which_logical_cpu, double* cpu_load);
78   int context_switch_rate(double* rate);
79   int cpu_load_total_process(double* cpu_load);
80   int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotal);
81 
82   // os information
83   int os_version(char** os_version) const;
84 
85   // environment information
86   void generate_environment_variables_events();
87 
88    // system processes information
89   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes);
90 
91   int network_utilization(NetworkInterface** network_interfaces);
92 };
93 
JfrOSInterfaceImpl()94 JfrOSInterface::JfrOSInterfaceImpl::JfrOSInterfaceImpl() : _cpu_info_interface(NULL),
95                                                            _cpu_perf_interface(NULL),
96                                                            _system_process_interface(NULL),
97                                                            _network_performance_interface(NULL) {}
98 
99 template <typename T>
create_interface()100 static T* create_interface() {
101   ResourceMark rm;
102   T* iface = new T();
103   if (iface != NULL) {
104     if (!iface->initialize()) {
105       delete iface;
106       iface = NULL;
107     }
108   }
109   return iface;
110 }
111 
cpu_info_interface()112 CPUInformationInterface* JfrOSInterface::JfrOSInterfaceImpl::cpu_info_interface() {
113   if (_cpu_info_interface == NULL) {
114     _cpu_info_interface = create_interface<CPUInformationInterface>();
115   }
116   return _cpu_info_interface;
117 }
118 
cpu_perf_interface()119 CPUPerformanceInterface* JfrOSInterface::JfrOSInterfaceImpl::cpu_perf_interface() {
120   if (_cpu_perf_interface == NULL) {
121     _cpu_perf_interface = create_interface<CPUPerformanceInterface>();
122   }
123   return _cpu_perf_interface;
124 }
125 
system_process_interface()126 SystemProcessInterface* JfrOSInterface::JfrOSInterfaceImpl::system_process_interface() {
127   if (_system_process_interface == NULL) {
128     _system_process_interface = create_interface<SystemProcessInterface>();
129   }
130   return _system_process_interface;
131 }
132 
network_performance_interface()133 NetworkPerformanceInterface* JfrOSInterface::JfrOSInterfaceImpl::network_performance_interface() {
134   if (_network_performance_interface == NULL) {
135     _network_performance_interface = create_interface<NetworkPerformanceInterface>();
136   }
137   return _network_performance_interface;
138 }
139 
initialize()140 bool JfrOSInterface::JfrOSInterfaceImpl::initialize() {
141   return true;
142 }
143 
~JfrOSInterfaceImpl(void)144 JfrOSInterface::JfrOSInterfaceImpl::~JfrOSInterfaceImpl(void) {
145   if (_cpu_info_interface != NULL) {
146     delete _cpu_info_interface;
147     _cpu_info_interface = NULL;
148   }
149   if (_cpu_perf_interface != NULL) {
150     delete _cpu_perf_interface;
151     _cpu_perf_interface = NULL;
152   }
153   if (_system_process_interface != NULL) {
154     delete _system_process_interface;
155     _system_process_interface = NULL;
156   }
157   if (_network_performance_interface != NULL) {
158     delete _network_performance_interface;
159     _network_performance_interface = NULL;
160   }
161 }
162 
cpu_information(CPUInformation & cpu_info)163 int JfrOSInterface::JfrOSInterfaceImpl::cpu_information(CPUInformation& cpu_info) {
164   CPUInformationInterface* const iface = cpu_info_interface();
165   return iface == NULL ? OS_ERR : iface->cpu_information(cpu_info);
166 }
167 
cpu_load(int which_logical_cpu,double * cpu_load)168 int JfrOSInterface::JfrOSInterfaceImpl::cpu_load(int which_logical_cpu, double* cpu_load) {
169   CPUPerformanceInterface* const iface = cpu_perf_interface();
170   return iface == NULL ? OS_ERR : iface->cpu_load(which_logical_cpu, cpu_load);
171 }
172 
context_switch_rate(double * rate)173 int JfrOSInterface::JfrOSInterfaceImpl::context_switch_rate(double* rate) {
174   CPUPerformanceInterface* const iface = cpu_perf_interface();
175   return iface == NULL ? OS_ERR : iface->context_switch_rate(rate);
176 }
177 
cpu_load_total_process(double * cpu_load)178 int JfrOSInterface::JfrOSInterfaceImpl::cpu_load_total_process(double* cpu_load) {
179   CPUPerformanceInterface* const iface = cpu_perf_interface();
180   return iface == NULL ? OS_ERR : iface->cpu_load_total_process(cpu_load);
181 }
182 
cpu_loads_process(double * pjvmUserLoad,double * pjvmKernelLoad,double * psystemTotal)183 int JfrOSInterface::JfrOSInterfaceImpl::cpu_loads_process(double* pjvmUserLoad,
184                                                           double* pjvmKernelLoad,
185                                                           double* psystemTotal) {
186   CPUPerformanceInterface* const iface = cpu_perf_interface();
187   return iface == NULL ? OS_ERR : iface->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotal);
188 }
189 
system_processes(SystemProcess ** system_processes,int * no_of_sys_processes)190 int JfrOSInterface::JfrOSInterfaceImpl::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) {
191   assert(system_processes != NULL, "system_processes pointer is NULL!");
192   assert(no_of_sys_processes != NULL, "no_of_sys_processes pointer is NULL!");
193   SystemProcessInterface* const iface = system_process_interface();
194   return iface == NULL ? OS_ERR : iface->system_processes(system_processes, no_of_sys_processes);
195 }
196 
network_utilization(NetworkInterface ** network_interfaces)197 int JfrOSInterface::JfrOSInterfaceImpl::network_utilization(NetworkInterface** network_interfaces) {
198   NetworkPerformanceInterface* const iface = network_performance_interface();
199   return iface == NULL ? OS_ERR : iface->network_utilization(network_interfaces);
200 }
201 
202 // assigned char* is RESOURCE_HEAP_ALLOCATED
203 // caller need to ensure proper ResourceMark placement.
os_version(char ** os_version) const204 int JfrOSInterface::JfrOSInterfaceImpl::os_version(char** os_version) const {
205   assert(os_version != NULL, "os_version pointer is NULL!");
206   stringStream os_ver_info;
207   os::print_os_info_brief(&os_ver_info);
208   *os_version = os_ver_info.as_string();
209   return OS_OK;
210 }
211 
JfrOSInterface()212 JfrOSInterface::JfrOSInterface() {
213   _impl = NULL;
214 }
215 
initialize()216 bool JfrOSInterface::initialize() {
217   _impl = new JfrOSInterface::JfrOSInterfaceImpl();
218   return _impl != NULL && _impl->initialize();
219 }
220 
~JfrOSInterface()221 JfrOSInterface::~JfrOSInterface() {
222   if (_impl != NULL) {
223     delete _impl;
224     _impl = NULL;
225   }
226 }
227 
cpu_information(CPUInformation & cpu_info)228 int JfrOSInterface::cpu_information(CPUInformation& cpu_info) {
229   return instance()._impl->cpu_information(cpu_info);
230 }
231 
cpu_load(int which_logical_cpu,double * cpu_load)232 int JfrOSInterface::cpu_load(int which_logical_cpu, double* cpu_load) {
233   return instance()._impl->cpu_load(which_logical_cpu, cpu_load);
234 }
235 
context_switch_rate(double * rate)236 int JfrOSInterface::context_switch_rate(double* rate) {
237   return instance()._impl->context_switch_rate(rate);
238 }
239 
cpu_load_total_process(double * cpu_load)240 int JfrOSInterface::cpu_load_total_process(double* cpu_load) {
241   return instance()._impl->cpu_load_total_process(cpu_load);
242 }
243 
cpu_loads_process(double * jvm_user_load,double * jvm_kernel_load,double * system_total_load)244 int JfrOSInterface::cpu_loads_process(double* jvm_user_load, double* jvm_kernel_load, double* system_total_load){
245   return instance()._impl->cpu_loads_process(jvm_user_load, jvm_kernel_load, system_total_load);
246 }
247 
os_version(char ** os_version)248 int JfrOSInterface::os_version(char** os_version) {
249   return instance()._impl->os_version(os_version);
250 }
251 
virtualization_name()252 const char* JfrOSInterface::virtualization_name() {
253   VirtualizationType vrt = VM_Version::get_detected_virtualization();
254   if (vrt == XenHVM) {
255     return "Xen hardware-assisted virtualization";
256   } else if (vrt == KVM) {
257     return "KVM virtualization";
258   } else if (vrt == VMWare) {
259     return "VMWare virtualization";
260   } else if (vrt == HyperV) {
261     return "Hyper-V virtualization";
262   } else if (vrt == HyperVRole) {
263     return "Hyper-V role";
264   } else if (vrt == PowerVM) {
265     return "PowerVM virtualization";
266   } else if (vrt == PowerKVM) {
267     return "Power KVM virtualization";
268   } else if (vrt == PowerFullPartitionMode) {
269     return "Power full partition";
270   }
271 
272   return "No virtualization detected";
273 }
274 
generate_initial_environment_variable_events()275 int JfrOSInterface::generate_initial_environment_variable_events() {
276   if (os::get_environ() == NULL) {
277     return OS_ERR;
278   }
279 
280   if (EventInitialEnvironmentVariable::is_enabled()) {
281     // One time stamp for all events, so they can be grouped together
282     JfrTicks time_stamp = JfrTicks::now();
283     for (char** p = os::get_environ(); *p != NULL; p++) {
284       char* variable = *p;
285       char* equal_sign = strchr(variable, '=');
286       if (equal_sign != NULL) {
287         // Extract key/value
288         ResourceMark rm;
289         ptrdiff_t key_length = equal_sign - variable;
290         char* key = NEW_RESOURCE_ARRAY(char, key_length + 1);
291         char* value = equal_sign + 1;
292         strncpy(key, variable, key_length);
293         key[key_length] = '\0';
294         EventInitialEnvironmentVariable event(UNTIMED);
295         event.set_endtime(time_stamp);
296         event.set_key(key);
297         event.set_value(value);
298         event.commit();
299       }
300     }
301   }
302   return OS_OK;
303 }
304 
system_processes(SystemProcess ** sys_processes,int * no_of_sys_processes)305 int JfrOSInterface::system_processes(SystemProcess** sys_processes, int* no_of_sys_processes) {
306   return instance()._impl->system_processes(sys_processes, no_of_sys_processes);
307 }
308 
network_utilization(NetworkInterface ** network_interfaces)309 int JfrOSInterface::network_utilization(NetworkInterface** network_interfaces) {
310   return instance()._impl->network_utilization(network_interfaces);
311 }
312