8134119: Use new API to get cache line sizes

Fri, 17 Mar 2017 07:52:54 -0700

author
kevinw
date
Fri, 17 Mar 2017 07:52:54 -0700
changeset 8731
3cb2feaca8cf
parent 8730
4b7ea2e3f901
child 8732
ef91cb539697

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

src/cpu/sparc/vm/vm_version_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/vm_version_sparc.hpp file | annotate | diff | comparison | revisions
src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp file | annotate | diff | comparison | revisions
     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  }

mercurial