comparison src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @ 20421:d635fd1ac81c

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
author iveresov
date Mon, 08 Sep 2014 18:11:37 -0700
parents b20a35eae442
children c49cd31b6da6
comparison
equal deleted inserted replaced
20419:2219e830b668 20421:d635fd1ac81c
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "runtime/os.hpp" 26 #include "runtime/os.hpp"
27 #include "vm_version_sparc.hpp" 27 #include "vm_version_sparc.hpp"
28 28
29 # include <sys/auxv.h> 29 #include <sys/auxv.h>
30 # include <sys/auxv_SPARC.h> 30 #include <sys/auxv_SPARC.h>
31 # include <sys/systeminfo.h> 31 #include <sys/systeminfo.h>
32 # include <kstat.h> 32 #include <kstat.h>
33 #include <picl.h>
34
35 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
36 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
37
38 class PICL {
39 // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
40 // depending on the platform. The result is converted to int.
41 static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
42 picl_propinfo_t pinfo;
43 picl_prophdl_t proph;
44 if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
45 picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
46 return PICL_FAILURE;
47 }
48
49 if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
50 assert(false, "Invalid property type");
51 return PICL_FAILURE;
52 }
53 if (pinfo.size == sizeof(int64_t)) {
54 int64_t val;
55 if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
56 return PICL_FAILURE;
57 }
58 *result = static_cast<int>(val);
59 } else if (pinfo.size == sizeof(int32_t)) {
60 int32_t val;
61 if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
62 return PICL_FAILURE;
63 }
64 *result = static_cast<int>(val);
65 } else {
66 assert(false, "Unexpected integer property size");
67 return PICL_FAILURE;
68 }
69 return PICL_SUCCESS;
70 }
71
72 // Visitor and a state machine that visits integer properties and verifies that the
73 // values are the same. Stores the unique value observed.
74 class UniqueValueVisitor {
75 enum {
76 INITIAL, // Start state, no assignments happened
77 ASSIGNED, // Assigned a value
78 INCONSISTENT // Inconsistent value seen
79 } _state;
80 int _value;
81 public:
82 UniqueValueVisitor() : _state(INITIAL) { }
83 int value() {
84 assert(_state == ASSIGNED, "Precondition");
85 return _value;
86 }
87 void set_value(int value) {
88 assert(_state == INITIAL, "Precondition");
89 _value = value;
90 _state = ASSIGNED;
91 }
92 bool is_initial() { return _state == INITIAL; }
93 bool is_assigned() { return _state == ASSIGNED; }
94 bool is_inconsistent() { return _state == INCONSISTENT; }
95 void set_inconsistent() { _state = INCONSISTENT; }
96
97 static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
98 UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
99 assert(!state->is_inconsistent(), "Precondition");
100 int curr;
101 if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
102 if (!state->is_assigned()) { // first iteration
103 state->set_value(curr);
104 } else if (curr != state->value()) { // following iterations
105 state->set_inconsistent();
106 }
107 }
108 if (state->is_inconsistent()) {
109 return PICL_WALK_TERMINATE;
110 }
111 return PICL_WALK_CONTINUE;
112 }
113 };
114
115 int _L1_data_cache_line_size;
116 int _L2_cache_line_size;
117 public:
118 static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
119 return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
120 }
121 static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
122 return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
123 }
124
125 PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
126 if (picl_initialize() == PICL_SUCCESS) {
127 picl_nodehdl_t rooth;
128 if (picl_get_root(&rooth) == PICL_SUCCESS) {
129 UniqueValueVisitor L1_state;
130 // Visit all "cpu" class instances
131 picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
132 if (L1_state.is_initial()) { // Still initial, iteration found no values
133 // Try walk all "core" class instances, it might be a Fujitsu machine
134 picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
135 }
136 if (L1_state.is_assigned()) { // Is there a value?
137 _L1_data_cache_line_size = L1_state.value();
138 }
139
140 UniqueValueVisitor L2_state;
141 picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
142 if (L2_state.is_initial()) {
143 picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
144 }
145 if (L2_state.is_assigned()) {
146 _L2_cache_line_size = L2_state.value();
147 }
148 }
149 picl_shutdown();
150 }
151 }
152
153 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
154 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
155 };
156
157 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
158 return PICL::get_l1_data_cache_line_size(nodeh, result);
159 }
160 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
161 return PICL::get_l2_cache_line_size(nodeh, result);
162 }
33 163
34 // We need to keep these here as long as we have to build on Solaris 164 // We need to keep these here as long as we have to build on Solaris
35 // versions before 10. 165 // versions before 10.
36 #ifndef SI_ARCHITECTURE_32 166 #ifndef SI_ARCHITECTURE_32
37 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ 167 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */
261 assert(strcmp(implementation, "UNKNOWN") != 0, 391 assert(strcmp(implementation, "UNKNOWN") != 0,
262 "unknown cpu info (changed kstat interface?)"); 392 "unknown cpu info (changed kstat interface?)");
263 kstat_close(kc); 393 kstat_close(kc);
264 } 394 }
265 395
396 // Figure out cache line sizes using PICL
397 PICL picl;
398 _L2_cache_line_size = picl.L2_cache_line_size();
399
266 return features; 400 return features;
267 } 401 }