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