提交 2aa938b9 编写于 作者: K kevinw

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
上级 659b1342
...@@ -459,3 +459,37 @@ unsigned int VM_Version::calc_parallel_worker_threads() { ...@@ -459,3 +459,37 @@ unsigned int VM_Version::calc_parallel_worker_threads() {
} }
return result; return result;
} }
int VM_Version::parse_features(const char* implementation) {
int features = unknown_m;
// Convert to UPPER case before compare.
char* impl = os::strdup(implementation);
for (int i = 0; impl[i] != 0; i++)
impl[i] = (char)toupper((uint)impl[i]);
if (strstr(impl, "SPARC64") != NULL) {
features |= sparc64_family_m;
} else if (strstr(impl, "SPARC-M") != NULL) {
// M-series SPARC is based on T-series.
features |= (M_family_m | T_family_m);
} else if (strstr(impl, "SPARC-T") != NULL) {
features |= T_family_m;
if (strstr(impl, "SPARC-T1") != NULL) {
features |= T1_model_m;
}
} else {
if (strstr(impl, "SPARC") == NULL) {
#ifndef PRODUCT
// kstat on Solaris 8 virtual machines (branded zones)
// returns "(unsupported)" implementation. Solaris 8 is not
// supported anymore, but include this check to be on the
// safe side.
warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl);
#endif
}
}
os::free((void*)impl);
return features;
}
...@@ -119,7 +119,7 @@ protected: ...@@ -119,7 +119,7 @@ protected:
static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); }
static int maximum_niagara1_processor_count() { return 32; } static int maximum_niagara1_processor_count() { return 32; }
static int parse_features(const char* implementation);
public: public:
// Initialization // Initialization
static void initialize(); static void initialize();
......
...@@ -262,6 +262,7 @@ void PICL::close_library() { ...@@ -262,6 +262,7 @@ void PICL::close_library() {
// We need to keep these here as long as we have to build on Solaris // We need to keep these here as long as we have to build on Solaris
// versions before 10. // versions before 10.
#ifndef SI_ARCHITECTURE_32 #ifndef SI_ARCHITECTURE_32
#define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */
#endif #endif
...@@ -270,36 +271,88 @@ void PICL::close_library() { ...@@ -270,36 +271,88 @@ void PICL::close_library() {
#define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ #define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */
#endif #endif
static void do_sysinfo(int si, const char* string, int* features, int mask) { #ifndef SI_CPUBRAND
char tmp; #define SI_CPUBRAND 523 /* return cpu brand string */
size_t bufsize = sysinfo(si, &tmp, 1); #endif
// All SI defines used below must be supported. class Sysinfo {
guarantee(bufsize != -1, "must be supported"); char* _string;
public:
Sysinfo(int si) : _string(NULL) {
char tmp;
size_t bufsize = sysinfo(si, &tmp, 1);
if (bufsize != -1) {
char* buf = (char*) os::malloc(bufsize, mtInternal);
if (buf != NULL) {
if (sysinfo(si, buf, bufsize) == bufsize) {
_string = buf;
} else {
os::free(buf);
}
}
}
}
char* buf = (char*) malloc(bufsize); ~Sysinfo() {
if (_string != NULL) {
os::free(_string);
}
}
if (buf == NULL) const char* value() const {
return; return _string;
}
if (sysinfo(si, buf, bufsize) == bufsize) { bool valid() const {
// Compare the string. return _string != NULL;
if (strcmp(buf, string) == 0) {
*features |= mask;
}
} }
free(buf); bool match(const char* s) const {
} return valid() ? strcmp(_string, s) == 0 : false;
}
bool match_substring(const char* s) const {
return valid() ? strstr(_string, s) != NULL : false;
}
};
class Sysconf {
int _value;
public:
Sysconf(int sc) : _value(-1) {
_value = sysconf(sc);
}
bool valid() const {
return _value != -1;
}
int value() const {
return _value;
}
};
#ifndef _SC_DCACHE_LINESZ
#define _SC_DCACHE_LINESZ 508 /* Data cache line size */
#endif
#ifndef _SC_L2CACHE_LINESZ
#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */
#endif
int VM_Version::platform_features(int features) { int VM_Version::platform_features(int features) {
assert(os::Solaris::supports_getisax(), "getisax() must be available"); assert(os::Solaris::supports_getisax(), "getisax() must be available");
// Check 32-bit architecture. // Check 32-bit architecture.
do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) {
features |= v8_instructions_m;
}
// Check 64-bit architecture. // Check 64-bit architecture.
do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) {
features |= generic_v9_m;
}
// Extract valid instruction set extensions. // Extract valid instruction set extensions.
uint_t avs[2]; uint_t avs[2];
...@@ -381,66 +434,63 @@ int VM_Version::platform_features(int features) { ...@@ -381,66 +434,63 @@ int VM_Version::platform_features(int features) {
if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; if (av & AV_SPARC_SHA512) features |= sha512_instruction_m;
// Determine the machine type. // Determine the machine type.
do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); if (Sysinfo(SI_MACHINE).match("sun4v")) {
features |= sun4v_m;
}
{ bool use_solaris_12_api = false;
// Using kstat to determine the machine type. Sysinfo impl(SI_CPUBRAND);
if (impl.valid()) {
// If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes
// is available to us as well
use_solaris_12_api = true;
features |= parse_features(impl.value());
} else {
// Otherwise use kstat to determine the machine type.
kstat_ctl_t* kc = kstat_open(); kstat_ctl_t* kc = kstat_open();
kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
const char* implementation = "UNKNOWN"; const char* implementation;
bool has_implementation = false;
if (ksp != NULL) { if (ksp != NULL) {
if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
for (int i = 0; i < ksp->ks_ndata; i++) { for (int i = 0; i < ksp->ks_ndata; i++) {
if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) {
implementation = KSTAT_NAMED_STR_PTR(&knm[i]); implementation = KSTAT_NAMED_STR_PTR(&knm[i]);
has_implementation = true;
#ifndef PRODUCT #ifndef PRODUCT
if (PrintMiscellaneous && Verbose) { if (PrintMiscellaneous && Verbose) {
tty->print_cr("cpu_info.implementation: %s", implementation); tty->print_cr("cpu_info.implementation: %s", implementation);
} }
#endif #endif
// Convert to UPPER case before compare. features |= parse_features(implementation);
char* impl = strdup(implementation);
for (int i = 0; impl[i] != 0; i++)
impl[i] = (char)toupper((uint)impl[i]);
if (strstr(impl, "SPARC64") != NULL) {
features |= sparc64_family_m;
} else if (strstr(impl, "SPARC-M") != NULL) {
// M-series SPARC is based on T-series.
features |= (M_family_m | T_family_m);
} else if (strstr(impl, "SPARC-T") != NULL) {
features |= T_family_m;
if (strstr(impl, "SPARC-T1") != NULL) {
features |= T1_model_m;
}
} else {
if (strstr(impl, "SPARC") == NULL) {
#ifndef PRODUCT
// kstat on Solaris 8 virtual machines (branded zones)
// returns "(unsupported)" implementation. Solaris 8 is not
// supported anymore, but include this check to be on the
// safe side.
warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl);
#endif
implementation = "SPARC";
}
}
free((void*)impl);
break; break;
} }
} // for( } // for(
} }
} }
assert(strcmp(implementation, "UNKNOWN") != 0, assert(has_implementation, "unknown cpu info (changed kstat interface?)");
"unknown cpu info (changed kstat interface?)");
kstat_close(kc); kstat_close(kc);
} }
// Figure out cache line sizes using PICL bool is_sun4v = (features & sun4v_m) != 0;
PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); if (use_solaris_12_api && is_sun4v) {
_L2_data_cache_line_size = picl.L2_data_cache_line_size(); // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes
Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ);
if (l1_dcache_line_size.valid()) {
_L1_data_cache_line_size = l1_dcache_line_size.value();
}
Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ);
if (l2_dcache_line_size.valid()) {
_L2_data_cache_line_size = l2_dcache_line_size.value();
}
} else {
// Otherwise figure out the cache line sizes using PICL
bool is_fujitsu = (features & sparc64_family_m) != 0;
PICL picl(is_fujitsu, is_sun4v);
_L1_data_cache_line_size = picl.L1_data_cache_line_size();
_L2_data_cache_line_size = picl.L2_data_cache_line_size();
}
return features; return features;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册