Fri, 17 Mar 2017 07:52:54 -0700
8134119: Use new API to get cache line sizes
Summary: Using new sysconf and sysinfo API on Solaris 12, avoid using libpicl and libkstat.
Reviewed-by: kvn
1.1 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Mar 31 01:25:26 2017 -0700 1.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Mar 17 07:52:54 2017 -0700 1.3 @@ -459,3 +459,37 @@ 1.4 } 1.5 return result; 1.6 } 1.7 + 1.8 + 1.9 +int VM_Version::parse_features(const char* implementation) { 1.10 + int features = unknown_m; 1.11 + // Convert to UPPER case before compare. 1.12 + char* impl = os::strdup(implementation); 1.13 + 1.14 + for (int i = 0; impl[i] != 0; i++) 1.15 + impl[i] = (char)toupper((uint)impl[i]); 1.16 + 1.17 + if (strstr(impl, "SPARC64") != NULL) { 1.18 + features |= sparc64_family_m; 1.19 + } else if (strstr(impl, "SPARC-M") != NULL) { 1.20 + // M-series SPARC is based on T-series. 1.21 + features |= (M_family_m | T_family_m); 1.22 + } else if (strstr(impl, "SPARC-T") != NULL) { 1.23 + features |= T_family_m; 1.24 + if (strstr(impl, "SPARC-T1") != NULL) { 1.25 + features |= T1_model_m; 1.26 + } 1.27 + } else { 1.28 + if (strstr(impl, "SPARC") == NULL) { 1.29 +#ifndef PRODUCT 1.30 + // kstat on Solaris 8 virtual machines (branded zones) 1.31 + // returns "(unsupported)" implementation. Solaris 8 is not 1.32 + // supported anymore, but include this check to be on the 1.33 + // safe side. 1.34 + warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl); 1.35 +#endif 1.36 + } 1.37 + } 1.38 + os::free((void*)impl); 1.39 + return features; 1.40 +}
2.1 --- a/src/cpu/sparc/vm/vm_version_sparc.hpp Fri Mar 31 01:25:26 2017 -0700 2.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.hpp Fri Mar 17 07:52:54 2017 -0700 2.3 @@ -119,7 +119,7 @@ 2.4 static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } 2.5 2.6 static int maximum_niagara1_processor_count() { return 32; } 2.7 - 2.8 + static int parse_features(const char* implementation); 2.9 public: 2.10 // Initialization 2.11 static void initialize();
3.1 --- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Mar 31 01:25:26 2017 -0700 3.2 +++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Mar 17 07:52:54 2017 -0700 3.3 @@ -262,6 +262,7 @@ 3.4 3.5 // We need to keep these here as long as we have to build on Solaris 3.6 // versions before 10. 3.7 + 3.8 #ifndef SI_ARCHITECTURE_32 3.9 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ 3.10 #endif 3.11 @@ -270,36 +271,88 @@ 3.12 #define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ 3.13 #endif 3.14 3.15 -static void do_sysinfo(int si, const char* string, int* features, int mask) { 3.16 - char tmp; 3.17 - size_t bufsize = sysinfo(si, &tmp, 1); 3.18 +#ifndef SI_CPUBRAND 3.19 +#define SI_CPUBRAND 523 /* return cpu brand string */ 3.20 +#endif 3.21 3.22 - // All SI defines used below must be supported. 3.23 - guarantee(bufsize != -1, "must be supported"); 3.24 +class Sysinfo { 3.25 + char* _string; 3.26 +public: 3.27 + Sysinfo(int si) : _string(NULL) { 3.28 + char tmp; 3.29 + size_t bufsize = sysinfo(si, &tmp, 1); 3.30 3.31 - char* buf = (char*) malloc(bufsize); 3.32 + if (bufsize != -1) { 3.33 + char* buf = (char*) os::malloc(bufsize, mtInternal); 3.34 + if (buf != NULL) { 3.35 + if (sysinfo(si, buf, bufsize) == bufsize) { 3.36 + _string = buf; 3.37 + } else { 3.38 + os::free(buf); 3.39 + } 3.40 + } 3.41 + } 3.42 + } 3.43 3.44 - if (buf == NULL) 3.45 - return; 3.46 - 3.47 - if (sysinfo(si, buf, bufsize) == bufsize) { 3.48 - // Compare the string. 3.49 - if (strcmp(buf, string) == 0) { 3.50 - *features |= mask; 3.51 + ~Sysinfo() { 3.52 + if (_string != NULL) { 3.53 + os::free(_string); 3.54 } 3.55 } 3.56 3.57 - free(buf); 3.58 -} 3.59 + const char* value() const { 3.60 + return _string; 3.61 + } 3.62 + 3.63 + bool valid() const { 3.64 + return _string != NULL; 3.65 + } 3.66 + 3.67 + bool match(const char* s) const { 3.68 + return valid() ? strcmp(_string, s) == 0 : false; 3.69 + } 3.70 + 3.71 + bool match_substring(const char* s) const { 3.72 + return valid() ? strstr(_string, s) != NULL : false; 3.73 + } 3.74 +}; 3.75 + 3.76 +class Sysconf { 3.77 + int _value; 3.78 +public: 3.79 + Sysconf(int sc) : _value(-1) { 3.80 + _value = sysconf(sc); 3.81 + } 3.82 + bool valid() const { 3.83 + return _value != -1; 3.84 + } 3.85 + int value() const { 3.86 + return _value; 3.87 + } 3.88 +}; 3.89 + 3.90 + 3.91 +#ifndef _SC_DCACHE_LINESZ 3.92 +#define _SC_DCACHE_LINESZ 508 /* Data cache line size */ 3.93 +#endif 3.94 + 3.95 +#ifndef _SC_L2CACHE_LINESZ 3.96 +#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */ 3.97 +#endif 3.98 + 3.99 3.100 int VM_Version::platform_features(int features) { 3.101 assert(os::Solaris::supports_getisax(), "getisax() must be available"); 3.102 3.103 // Check 32-bit architecture. 3.104 - do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); 3.105 + if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) { 3.106 + features |= v8_instructions_m; 3.107 + } 3.108 3.109 // Check 64-bit architecture. 3.110 - do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); 3.111 + if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) { 3.112 + features |= generic_v9_m; 3.113 + } 3.114 3.115 // Extract valid instruction set extensions. 3.116 uint_t avs[2]; 3.117 @@ -381,66 +434,63 @@ 3.118 if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; 3.119 3.120 // Determine the machine type. 3.121 - do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); 3.122 + if (Sysinfo(SI_MACHINE).match("sun4v")) { 3.123 + features |= sun4v_m; 3.124 + } 3.125 3.126 - { 3.127 - // Using kstat to determine the machine type. 3.128 + bool use_solaris_12_api = false; 3.129 + Sysinfo impl(SI_CPUBRAND); 3.130 + if (impl.valid()) { 3.131 + // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes 3.132 + // is available to us as well 3.133 + use_solaris_12_api = true; 3.134 + features |= parse_features(impl.value()); 3.135 + } else { 3.136 + // Otherwise use kstat to determine the machine type. 3.137 kstat_ctl_t* kc = kstat_open(); 3.138 kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); 3.139 - const char* implementation = "UNKNOWN"; 3.140 + const char* implementation; 3.141 + bool has_implementation = false; 3.142 if (ksp != NULL) { 3.143 if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { 3.144 kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; 3.145 for (int i = 0; i < ksp->ks_ndata; i++) { 3.146 if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { 3.147 implementation = KSTAT_NAMED_STR_PTR(&knm[i]); 3.148 + has_implementation = true; 3.149 #ifndef PRODUCT 3.150 if (PrintMiscellaneous && Verbose) { 3.151 tty->print_cr("cpu_info.implementation: %s", implementation); 3.152 } 3.153 #endif 3.154 - // Convert to UPPER case before compare. 3.155 - char* impl = strdup(implementation); 3.156 - 3.157 - for (int i = 0; impl[i] != 0; i++) 3.158 - impl[i] = (char)toupper((uint)impl[i]); 3.159 - 3.160 - if (strstr(impl, "SPARC64") != NULL) { 3.161 - features |= sparc64_family_m; 3.162 - } else if (strstr(impl, "SPARC-M") != NULL) { 3.163 - // M-series SPARC is based on T-series. 3.164 - features |= (M_family_m | T_family_m); 3.165 - } else if (strstr(impl, "SPARC-T") != NULL) { 3.166 - features |= T_family_m; 3.167 - if (strstr(impl, "SPARC-T1") != NULL) { 3.168 - features |= T1_model_m; 3.169 - } 3.170 - } else { 3.171 - if (strstr(impl, "SPARC") == NULL) { 3.172 -#ifndef PRODUCT 3.173 - // kstat on Solaris 8 virtual machines (branded zones) 3.174 - // returns "(unsupported)" implementation. Solaris 8 is not 3.175 - // supported anymore, but include this check to be on the 3.176 - // safe side. 3.177 - warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl); 3.178 -#endif 3.179 - implementation = "SPARC"; 3.180 - } 3.181 - } 3.182 - free((void*)impl); 3.183 + features |= parse_features(implementation); 3.184 break; 3.185 } 3.186 } // for( 3.187 } 3.188 } 3.189 - assert(strcmp(implementation, "UNKNOWN") != 0, 3.190 - "unknown cpu info (changed kstat interface?)"); 3.191 + assert(has_implementation, "unknown cpu info (changed kstat interface?)"); 3.192 kstat_close(kc); 3.193 } 3.194 3.195 - // Figure out cache line sizes using PICL 3.196 - PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); 3.197 - _L2_data_cache_line_size = picl.L2_data_cache_line_size(); 3.198 + bool is_sun4v = (features & sun4v_m) != 0; 3.199 + if (use_solaris_12_api && is_sun4v) { 3.200 + // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes 3.201 + Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ); 3.202 + if (l1_dcache_line_size.valid()) { 3.203 + _L1_data_cache_line_size = l1_dcache_line_size.value(); 3.204 + } 3.205 3.206 + Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ); 3.207 + if (l2_dcache_line_size.valid()) { 3.208 + _L2_data_cache_line_size = l2_dcache_line_size.value(); 3.209 + } 3.210 + } else { 3.211 + // Otherwise figure out the cache line sizes using PICL 3.212 + bool is_fujitsu = (features & sparc64_family_m) != 0; 3.213 + PICL picl(is_fujitsu, is_sun4v); 3.214 + _L1_data_cache_line_size = picl.L1_data_cache_line_size(); 3.215 + _L2_data_cache_line_size = picl.L2_data_cache_line_size(); 3.216 + } 3.217 return features; 3.218 }