8056124: Hotspot should use PICL interface to get cacheline size on SPARC

Mon, 08 Sep 2014 18:11:37 -0700

author
iveresov
date
Mon, 08 Sep 2014 18:11:37 -0700
changeset 7135
d635fd1ac81c
parent 7133
2219e830b668
child 7136
3153adbad1e9

8056124: Hotspot should use PICL interface to get cacheline size on SPARC
Summary: Using libpicl to get L1 data and L2 cache line sizes
Reviewed-by: kvn, roland, morris

make/solaris/makefiles/vm.make file | annotate | diff | comparison | revisions
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/make/solaris/makefiles/vm.make	Mon Sep 08 23:01:01 2014 +0000
     1.2 +++ b/make/solaris/makefiles/vm.make	Mon Sep 08 18:11:37 2014 -0700
     1.3 @@ -141,7 +141,7 @@
     1.4  LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
     1.5  endif # sparcWorks
     1.6  
     1.7 -LIBS += -lkstat
     1.8 +LIBS += -lkstat -lpicl
     1.9  
    1.10  # By default, link the *.o into the library, not the executable.
    1.11  LINK_INTO$(LINK_INTO) = LIBJVM
     2.1 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Sep 08 23:01:01 2014 +0000
     2.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Sep 08 18:11:37 2014 -0700
     2.3 @@ -37,6 +37,7 @@
     2.4  
     2.5  int VM_Version::_features = VM_Version::unknown_m;
     2.6  const char* VM_Version::_features_str = "";
     2.7 +unsigned int VM_Version::_L2_cache_line_size = 0;
     2.8  
     2.9  void VM_Version::initialize() {
    2.10    _features = determine_features();
    2.11 @@ -197,7 +198,7 @@
    2.12    }
    2.13  
    2.14    assert(BlockZeroingLowLimit > 0, "invalid value");
    2.15 -  if (has_block_zeroing()) {
    2.16 +  if (has_block_zeroing() && cache_line_size > 0) {
    2.17      if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
    2.18        FLAG_SET_DEFAULT(UseBlockZeroing, true);
    2.19      }
    2.20 @@ -207,7 +208,7 @@
    2.21    }
    2.22  
    2.23    assert(BlockCopyLowLimit > 0, "invalid value");
    2.24 -  if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache
    2.25 +  if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
    2.26      if (FLAG_IS_DEFAULT(UseBlockCopy)) {
    2.27        FLAG_SET_DEFAULT(UseBlockCopy, true);
    2.28      }
    2.29 @@ -362,6 +363,7 @@
    2.30  
    2.31  #ifndef PRODUCT
    2.32    if (PrintMiscellaneous && Verbose) {
    2.33 +    tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
    2.34      tty->print("Allocation");
    2.35      if (AllocatePrefetchStyle <= 0) {
    2.36        tty->print_cr(": no prefetching");
     3.1 --- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Sep 08 23:01:01 2014 +0000
     3.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Sep 08 18:11:37 2014 -0700
     3.3 @@ -96,6 +96,9 @@
     3.4    static int  _features;
     3.5    static const char* _features_str;
     3.6  
     3.7 +  static unsigned int _L2_cache_line_size;
     3.8 +  static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
     3.9 +
    3.10    static void print_features();
    3.11    static int  determine_features();
    3.12    static int  platform_features(int features);
    3.13 @@ -167,9 +170,8 @@
    3.14  
    3.15    static const char* cpu_features()     { return _features_str; }
    3.16  
    3.17 -  static intx prefetch_data_size()  {
    3.18 -    return is_T4() && !is_T7() ? 32 : 64;  // default prefetch block size on sparc
    3.19 -  }
    3.20 +  // default prefetch block size on sparc
    3.21 +  static intx prefetch_data_size()      { return L2_cache_line_size();  }
    3.22  
    3.23    // Prefetch
    3.24    static intx prefetch_copy_interval_in_bytes() {
     4.1 --- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Sep 08 23:01:01 2014 +0000
     4.2 +++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Sep 08 18:11:37 2014 -0700
     4.3 @@ -26,10 +26,140 @@
     4.4  #include "runtime/os.hpp"
     4.5  #include "vm_version_sparc.hpp"
     4.6  
     4.7 -# include <sys/auxv.h>
     4.8 -# include <sys/auxv_SPARC.h>
     4.9 -# include <sys/systeminfo.h>
    4.10 -# include <kstat.h>
    4.11 +#include <sys/auxv.h>
    4.12 +#include <sys/auxv_SPARC.h>
    4.13 +#include <sys/systeminfo.h>
    4.14 +#include <kstat.h>
    4.15 +#include <picl.h>
    4.16 +
    4.17 +extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
    4.18 +extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
    4.19 +
    4.20 +class PICL {
    4.21 +  // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
    4.22 +  // depending on the platform. The result is converted to int.
    4.23 +  static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
    4.24 +    picl_propinfo_t pinfo;
    4.25 +    picl_prophdl_t proph;
    4.26 +    if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
    4.27 +        picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
    4.28 +      return PICL_FAILURE;
    4.29 +    }
    4.30 +
    4.31 +    if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
    4.32 +      assert(false, "Invalid property type");
    4.33 +      return PICL_FAILURE;
    4.34 +    }
    4.35 +    if (pinfo.size == sizeof(int64_t)) {
    4.36 +      int64_t val;
    4.37 +      if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
    4.38 +        return PICL_FAILURE;
    4.39 +      }
    4.40 +      *result = static_cast<int>(val);
    4.41 +    } else if (pinfo.size == sizeof(int32_t)) {
    4.42 +      int32_t val;
    4.43 +      if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
    4.44 +        return PICL_FAILURE;
    4.45 +      }
    4.46 +      *result = static_cast<int>(val);
    4.47 +    } else {
    4.48 +      assert(false, "Unexpected integer property size");
    4.49 +      return PICL_FAILURE;
    4.50 +    }
    4.51 +    return PICL_SUCCESS;
    4.52 +  }
    4.53 +
    4.54 +  // Visitor and a state machine that visits integer properties and verifies that the
    4.55 +  // values are the same. Stores the unique value observed.
    4.56 +  class UniqueValueVisitor {
    4.57 +    enum {
    4.58 +      INITIAL,        // Start state, no assignments happened
    4.59 +      ASSIGNED,       // Assigned a value
    4.60 +      INCONSISTENT    // Inconsistent value seen
    4.61 +    } _state;
    4.62 +    int _value;
    4.63 +  public:
    4.64 +    UniqueValueVisitor() : _state(INITIAL) { }
    4.65 +    int value() {
    4.66 +      assert(_state == ASSIGNED, "Precondition");
    4.67 +      return _value;
    4.68 +    }
    4.69 +    void set_value(int value) {
    4.70 +      assert(_state == INITIAL, "Precondition");
    4.71 +      _value = value;
    4.72 +      _state = ASSIGNED;
    4.73 +    }
    4.74 +    bool is_initial()       { return _state == INITIAL;      }
    4.75 +    bool is_assigned()      { return _state == ASSIGNED;     }
    4.76 +    bool is_inconsistent()  { return _state == INCONSISTENT; }
    4.77 +    void set_inconsistent() { _state = INCONSISTENT;         }
    4.78 +
    4.79 +    static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
    4.80 +      UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
    4.81 +      assert(!state->is_inconsistent(), "Precondition");
    4.82 +      int curr;
    4.83 +      if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
    4.84 +        if (!state->is_assigned()) { // first iteration
    4.85 +          state->set_value(curr);
    4.86 +        } else if (curr != state->value()) { // following iterations
    4.87 +          state->set_inconsistent();
    4.88 +        }
    4.89 +      }
    4.90 +      if (state->is_inconsistent()) {
    4.91 +        return PICL_WALK_TERMINATE;
    4.92 +      }
    4.93 +      return PICL_WALK_CONTINUE;
    4.94 +    }
    4.95 +  };
    4.96 +
    4.97 +  int _L1_data_cache_line_size;
    4.98 +  int _L2_cache_line_size;
    4.99 +public:
   4.100 +  static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
   4.101 +    return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
   4.102 +  }
   4.103 +  static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
   4.104 +    return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
   4.105 +  }
   4.106 +
   4.107 +  PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
   4.108 +    if (picl_initialize() == PICL_SUCCESS) {
   4.109 +      picl_nodehdl_t rooth;
   4.110 +      if (picl_get_root(&rooth) == PICL_SUCCESS) {
   4.111 +        UniqueValueVisitor L1_state;
   4.112 +        // Visit all "cpu" class instances
   4.113 +        picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
   4.114 +        if (L1_state.is_initial()) { // Still initial, iteration found no values
   4.115 +          // Try walk all "core" class instances, it might be a Fujitsu machine
   4.116 +          picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
   4.117 +        }
   4.118 +        if (L1_state.is_assigned()) { // Is there a value?
   4.119 +          _L1_data_cache_line_size = L1_state.value();
   4.120 +        }
   4.121 +
   4.122 +        UniqueValueVisitor L2_state;
   4.123 +        picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
   4.124 +        if (L2_state.is_initial()) {
   4.125 +          picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
   4.126 +        }
   4.127 +        if (L2_state.is_assigned()) {
   4.128 +          _L2_cache_line_size = L2_state.value();
   4.129 +        }
   4.130 +      }
   4.131 +      picl_shutdown();
   4.132 +    }
   4.133 +  }
   4.134 +
   4.135 +  unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
   4.136 +  unsigned int L2_cache_line_size() const      { return _L2_cache_line_size;      }
   4.137 +};
   4.138 +
   4.139 +extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
   4.140 +  return PICL::get_l1_data_cache_line_size(nodeh, result);
   4.141 +}
   4.142 +extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
   4.143 +  return PICL::get_l2_cache_line_size(nodeh, result);
   4.144 +}
   4.145  
   4.146  // We need to keep these here as long as we have to build on Solaris
   4.147  // versions before 10.
   4.148 @@ -263,5 +393,9 @@
   4.149      kstat_close(kc);
   4.150    }
   4.151  
   4.152 +  // Figure out cache line sizes using PICL
   4.153 +  PICL picl;
   4.154 +  _L2_cache_line_size      = picl.L2_cache_line_size();
   4.155 +
   4.156    return features;
   4.157  }

mercurial