1 /*
2 * Copyright (c) 2013, 2018, 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 "jvm.h"
26 #include "memory/allocation.hpp"
27 #include "memory/allocation.inline.hpp"
28 #include "vm_version_ext_sparc.hpp"
29
30 // VM_Version_Ext statics
31 int VM_Version_Ext::_no_of_threads = 0;
32 int VM_Version_Ext::_no_of_cores = 0;
33 int VM_Version_Ext::_no_of_sockets = 0;
34 #if defined(SOLARIS)
35 kid_t VM_Version_Ext::_kcid = -1;
36 #endif
37 char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0};
38 char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0};
39
40 #if defined(SOLARIS)
41 // get cpu information. It takes into account if the kstat chain id
42 // has been changed and update the info if necessary.
initialize_cpu_information(void)43 bool VM_Version_Ext::initialize_cpu_information(void) {
44
45 int core_id = -1;
46 int chip_id = -1;
47 int len = 0;
48 char* src_string = NULL;
49 kstat_ctl_t* kc = kstat_open();
50 if (!kc) {
51 return false;
52 }
53
54 // check if kstat chain has been updated
55 kid_t kcid = kstat_chain_update(kc);
56 if (kcid == -1) {
57 kstat_close(kc);
58 return false;
59 }
60
61 bool updated = ((kcid > 0) && (kcid != _kcid)) ||
62 ((kcid == 0) && (_kcid == -1));
63 if (!updated) {
64 kstat_close(kc);
65 return true;
66 }
67
68 // update the cached _kcid
69 _kcid = kcid;
70
71 // find the number of online processors
72 // for modern processsors, it is also known as the
73 // hardware threads.
74 _no_of_threads = sysconf(_SC_NPROCESSORS_ONLN);
75
76 if (_no_of_threads <= 0 ) {
77 kstat_close(kc);
78 return false;
79 }
80
81 _no_of_cores = 0;
82 _no_of_sockets = 0;
83
84 // loop through the kstat chain
85 kstat_t* ksp = NULL;
86 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
87 // only interested in "cpu_info"
88 if (strcmp(ksp->ks_module, (char*)CPU_INFO) == 0) {
89 if (kstat_read(kc, ksp, NULL) == -1) {
90 kstat_close(kc);
91 return false;
92 }
93 if (ksp->ks_data != NULL) {
94 kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
95 // loop through the number of fields in each record
96 for (int i = 0; i < ksp->ks_ndata; i++) {
97 // set cpu type if it hasn't been already set
98 if ((strcmp((const char*)&(knm[i].name), CPU_TYPE) == 0) &&
99 (_cpu_name[0] == '\0')) {
100 if (knm[i].data_type == KSTAT_DATA_STRING) {
101 src_string = (char*)KSTAT_NAMED_STR_PTR(&knm[i]);
102 } else {
103 src_string = (char*)&(knm[i].value.c[0]);
104 }
105 len = strlen(src_string);
106 if (len < CPU_TYPE_DESC_BUF_SIZE) {
107 jio_snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE,
108 "%s", src_string);
109 }
110 }
111
112 // set cpu description if it hasn't been already set
113 if ((strcmp((const char*)&(knm[i].name), CPU_DESCRIPTION) == 0) &&
114 (_cpu_desc[0] == '\0')) {
115 if (knm[i].data_type == KSTAT_DATA_STRING) {
116 src_string = (char*)KSTAT_NAMED_STR_PTR(&knm[i]);
117 } else {
118 src_string = (char*)&(knm[i].value.c[0]);
119 }
120 len = strlen(src_string);
121 if (len < CPU_DETAILED_DESC_BUF_SIZE) {
122 jio_snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE,
123 "%s", src_string);
124 }
125 }
126
127 // count the number of sockets based on the chip id
128 if (strcmp((const char*)&(knm[i].name), CHIP_ID) == 0) {
129 if (chip_id != knm[i].value.l) {
130 chip_id = knm[i].value.l;
131 _no_of_sockets++;
132 }
133 }
134
135 // count the number of cores based on the core id
136 if (strcmp((const char*)&(knm[i].name), CORE_ID) == 0) {
137 if (core_id != knm[i].value.l) {
138 core_id = knm[i].value.l;
139 _no_of_cores++;
140 }
141 }
142 }
143 }
144 }
145 }
146
147 kstat_close(kc);
148 return true;
149 }
150 #elif defined(LINUX)
151 // get cpu information.
initialize_cpu_information(void)152 bool VM_Version_Ext::initialize_cpu_information(void) {
153 // Not yet implemented.
154 return false;
155 }
156 #endif
157
number_of_threads(void)158 int VM_Version_Ext::number_of_threads(void) {
159 initialize_cpu_information();
160 return _no_of_threads;
161 }
162
number_of_cores(void)163 int VM_Version_Ext::number_of_cores(void) {
164 initialize_cpu_information();
165 return _no_of_cores;
166 }
167
number_of_sockets(void)168 int VM_Version_Ext::number_of_sockets(void) {
169 initialize_cpu_information();
170 return _no_of_sockets;
171 }
172
cpu_name(void)173 const char* VM_Version_Ext::cpu_name(void) {
174 if (!initialize_cpu_information()) {
175 return NULL;
176 }
177 char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing);
178 if (NULL == tmp) {
179 return NULL;
180 }
181 strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE);
182 return tmp;
183 }
184
cpu_description(void)185 const char* VM_Version_Ext::cpu_description(void) {
186 if (!initialize_cpu_information()) {
187 return NULL;
188 }
189 char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing);
190 if (NULL == tmp) {
191 return NULL;
192 }
193 strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE);
194 return tmp;
195 }
196