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