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 */ |