Mercurial > hg > graal-jvmci-8
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 } |