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