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. 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. 152 bool VM_Version_Ext::initialize_cpu_information(void) { 153 // Not yet implemented. 154 return false; 155 } 156 #endif 157 158 int VM_Version_Ext::number_of_threads(void) { 159 initialize_cpu_information(); 160 return _no_of_threads; 161 } 162 163 int VM_Version_Ext::number_of_cores(void) { 164 initialize_cpu_information(); 165 return _no_of_cores; 166 } 167 168 int VM_Version_Ext::number_of_sockets(void) { 169 initialize_cpu_information(); 170 return _no_of_sockets; 171 } 172 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 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 }