提交 a4398dd3 编写于 作者: I iveresov

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
上级 fa413814
...@@ -141,7 +141,7 @@ else ...@@ -141,7 +141,7 @@ else
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks endif # sparcWorks
LIBS += -lkstat LIBS += -lkstat -lpicl
# By default, link the *.o into the library, not the executable. # By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM LINK_INTO$(LINK_INTO) = LIBJVM
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
int VM_Version::_features = VM_Version::unknown_m; int VM_Version::_features = VM_Version::unknown_m;
const char* VM_Version::_features_str = ""; const char* VM_Version::_features_str = "";
unsigned int VM_Version::_L2_cache_line_size = 0;
void VM_Version::initialize() { void VM_Version::initialize() {
_features = determine_features(); _features = determine_features();
...@@ -197,7 +198,7 @@ void VM_Version::initialize() { ...@@ -197,7 +198,7 @@ void VM_Version::initialize() {
} }
assert(BlockZeroingLowLimit > 0, "invalid value"); assert(BlockZeroingLowLimit > 0, "invalid value");
if (has_block_zeroing()) { if (has_block_zeroing() && cache_line_size > 0) {
if (FLAG_IS_DEFAULT(UseBlockZeroing)) { if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
FLAG_SET_DEFAULT(UseBlockZeroing, true); FLAG_SET_DEFAULT(UseBlockZeroing, true);
} }
...@@ -207,7 +208,7 @@ void VM_Version::initialize() { ...@@ -207,7 +208,7 @@ void VM_Version::initialize() {
} }
assert(BlockCopyLowLimit > 0, "invalid value"); assert(BlockCopyLowLimit > 0, "invalid value");
if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
if (FLAG_IS_DEFAULT(UseBlockCopy)) { if (FLAG_IS_DEFAULT(UseBlockCopy)) {
FLAG_SET_DEFAULT(UseBlockCopy, true); FLAG_SET_DEFAULT(UseBlockCopy, true);
} }
...@@ -362,6 +363,7 @@ void VM_Version::initialize() { ...@@ -362,6 +363,7 @@ void VM_Version::initialize() {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintMiscellaneous && Verbose) { if (PrintMiscellaneous && Verbose) {
tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
tty->print("Allocation"); tty->print("Allocation");
if (AllocatePrefetchStyle <= 0) { if (AllocatePrefetchStyle <= 0) {
tty->print_cr(": no prefetching"); tty->print_cr(": no prefetching");
......
...@@ -96,6 +96,9 @@ protected: ...@@ -96,6 +96,9 @@ protected:
static int _features; static int _features;
static const char* _features_str; static const char* _features_str;
static unsigned int _L2_cache_line_size;
static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
static void print_features(); static void print_features();
static int determine_features(); static int determine_features();
static int platform_features(int features); static int platform_features(int features);
...@@ -167,9 +170,8 @@ public: ...@@ -167,9 +170,8 @@ public:
static const char* cpu_features() { return _features_str; } static const char* cpu_features() { return _features_str; }
static intx prefetch_data_size() { // default prefetch block size on sparc
return is_T4() && !is_T7() ? 32 : 64; // default prefetch block size on sparc static intx prefetch_data_size() { return L2_cache_line_size(); }
}
// Prefetch // Prefetch
static intx prefetch_copy_interval_in_bytes() { static intx prefetch_copy_interval_in_bytes() {
......
...@@ -26,10 +26,140 @@ ...@@ -26,10 +26,140 @@
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "vm_version_sparc.hpp" #include "vm_version_sparc.hpp"
# include <sys/auxv.h> #include <sys/auxv.h>
# include <sys/auxv_SPARC.h> #include <sys/auxv_SPARC.h>
# include <sys/systeminfo.h> #include <sys/systeminfo.h>
# include <kstat.h> #include <kstat.h>
#include <picl.h>
extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
class PICL {
// Get a value of the integer property. The value in the tree can be either 32 or 64 bit
// depending on the platform. The result is converted to int.
static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
picl_propinfo_t pinfo;
picl_prophdl_t proph;
if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
return PICL_FAILURE;
}
if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
assert(false, "Invalid property type");
return PICL_FAILURE;
}
if (pinfo.size == sizeof(int64_t)) {
int64_t val;
if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
return PICL_FAILURE;
}
*result = static_cast<int>(val);
} else if (pinfo.size == sizeof(int32_t)) {
int32_t val;
if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
return PICL_FAILURE;
}
*result = static_cast<int>(val);
} else {
assert(false, "Unexpected integer property size");
return PICL_FAILURE;
}
return PICL_SUCCESS;
}
// Visitor and a state machine that visits integer properties and verifies that the
// values are the same. Stores the unique value observed.
class UniqueValueVisitor {
enum {
INITIAL, // Start state, no assignments happened
ASSIGNED, // Assigned a value
INCONSISTENT // Inconsistent value seen
} _state;
int _value;
public:
UniqueValueVisitor() : _state(INITIAL) { }
int value() {
assert(_state == ASSIGNED, "Precondition");
return _value;
}
void set_value(int value) {
assert(_state == INITIAL, "Precondition");
_value = value;
_state = ASSIGNED;
}
bool is_initial() { return _state == INITIAL; }
bool is_assigned() { return _state == ASSIGNED; }
bool is_inconsistent() { return _state == INCONSISTENT; }
void set_inconsistent() { _state = INCONSISTENT; }
static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
assert(!state->is_inconsistent(), "Precondition");
int curr;
if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
if (!state->is_assigned()) { // first iteration
state->set_value(curr);
} else if (curr != state->value()) { // following iterations
state->set_inconsistent();
}
}
if (state->is_inconsistent()) {
return PICL_WALK_TERMINATE;
}
return PICL_WALK_CONTINUE;
}
};
int _L1_data_cache_line_size;
int _L2_cache_line_size;
public:
static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
}
static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
}
PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
if (picl_initialize() == PICL_SUCCESS) {
picl_nodehdl_t rooth;
if (picl_get_root(&rooth) == PICL_SUCCESS) {
UniqueValueVisitor L1_state;
// Visit all "cpu" class instances
picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
if (L1_state.is_initial()) { // Still initial, iteration found no values
// Try walk all "core" class instances, it might be a Fujitsu machine
picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
}
if (L1_state.is_assigned()) { // Is there a value?
_L1_data_cache_line_size = L1_state.value();
}
UniqueValueVisitor L2_state;
picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
if (L2_state.is_initial()) {
picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
}
if (L2_state.is_assigned()) {
_L2_cache_line_size = L2_state.value();
}
}
picl_shutdown();
}
}
unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
};
extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
return PICL::get_l1_data_cache_line_size(nodeh, result);
}
extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
return PICL::get_l2_cache_line_size(nodeh, result);
}
// 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.
...@@ -263,5 +393,9 @@ int VM_Version::platform_features(int features) { ...@@ -263,5 +393,9 @@ int VM_Version::platform_features(int features) {
kstat_close(kc); kstat_close(kc);
} }
// Figure out cache line sizes using PICL
PICL picl;
_L2_cache_line_size = picl.L2_cache_line_size();
return features; return features;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册