112 ASSIGNED, // Assigned a value
113 INCONSISTENT // Inconsistent value seen
114 } _state;
115 int _value;
116 public:
117 UniqueValueVisitor(PICL* picl) : _picl(picl), _state(INITIAL) { }
118 int value() {
119 assert(_state == ASSIGNED, "Precondition");
120 return _value;
121 }
122 void set_value(int value) {
123 assert(_state == INITIAL, "Precondition");
124 _value = value;
125 _state = ASSIGNED;
126 }
127 bool is_initial() { return _state == INITIAL; }
128 bool is_assigned() { return _state == ASSIGNED; }
129 bool is_inconsistent() { return _state == INCONSISTENT; }
130 void set_inconsistent() { _state = INCONSISTENT; }
131
132 void visit(picl_nodehdl_t nodeh, const char* name) {
133 assert(!is_inconsistent(), "Precondition");
134 int curr;
135 if (_picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
136 if (!is_assigned()) { // first iteration
137 set_value(curr);
138 } else if (curr != value()) { // following iterations
139 set_inconsistent();
140 }
141 }
142 }
143 };
144
145 class CPUVisitor {
146 UniqueValueVisitor _l1_visitor;
147 UniqueValueVisitor _l2_visitor;
148 int _limit; // number of times visit() can be run
149 public:
150 CPUVisitor(PICL *picl, int limit) : _l1_visitor(picl), _l2_visitor(picl), _limit(limit) {}
151 static int visit(picl_nodehdl_t nodeh, void *arg) {
152 CPUVisitor *cpu_visitor = static_cast<CPUVisitor*>(arg);
153 UniqueValueVisitor* l1_visitor = cpu_visitor->l1_visitor();
154 UniqueValueVisitor* l2_visitor = cpu_visitor->l2_visitor();
155 if (!l1_visitor->is_inconsistent()) {
156 l1_visitor->visit(nodeh, "l1-dcache-line-size");
157 }
158 if (!l2_visitor->is_inconsistent()) {
159 l2_visitor->visit(nodeh, "l2-cache-line-size");
160 }
161
162 if (l1_visitor->is_inconsistent() && l2_visitor->is_inconsistent()) {
163 return PICL_WALK_TERMINATE;
164 }
165 cpu_visitor->_limit--;
166 if (cpu_visitor->_limit <= 0) {
167 return PICL_WALK_TERMINATE;
168 }
169 return PICL_WALK_CONTINUE;
170 }
171 UniqueValueVisitor* l1_visitor() { return &_l1_visitor; }
172 UniqueValueVisitor* l2_visitor() { return &_l2_visitor; }
173 };
174 int _L1_data_cache_line_size;
175 int _L2_cache_line_size;
176 public:
177 static int visit_cpu(picl_nodehdl_t nodeh, void *state) {
178 return CPUVisitor::visit(nodeh, state);
179 }
180
181 PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) {
182 if (!open_library()) {
183 return;
184 }
185 if (_picl_initialize() == PICL_SUCCESS) {
186 picl_nodehdl_t rooth;
187 if (_picl_get_root(&rooth) == PICL_SUCCESS) {
188 const char* cpu_class = "cpu";
189 // If it's a Fujitsu machine, it's a "core"
190 if (is_fujitsu) {
191 cpu_class = "core";
192 }
193 CPUVisitor cpu_visitor(this, os::processor_count());
194 _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper);
195 if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value?
196 _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value();
197 }
198 if (cpu_visitor.l2_visitor()->is_assigned()) {
199 _L2_cache_line_size = cpu_visitor.l2_visitor()->value();
200 }
201 }
202 _picl_shutdown();
203 }
204 close_library();
205 }
206
207 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
208 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
209 };
210
211
212 extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result) {
213 return PICL::visit_cpu(nodeh, result);
214 }
215
216 template<typename FuncType>
217 bool PICL::bind(FuncType& func, const char* name) {
218 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name));
219 return func != NULL;
220 }
221
222 bool PICL::bind_library_functions() {
223 assert(_dl_handle != NULL, "library should be open");
224 return bind(_picl_initialize, "picl_initialize" ) &&
225 bind(_picl_shutdown, "picl_shutdown" ) &&
226 bind(_picl_get_root, "picl_get_root" ) &&
227 bind(_picl_walk_tree_by_class, "picl_walk_tree_by_class") &&
228 bind(_picl_get_prop_by_name, "picl_get_prop_by_name" ) &&
414 // safe side.
415 warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl);
416 #endif
417 implementation = "SPARC";
418 }
419 }
420 os::free((void*)impl);
421 break;
422 }
423 } // for(
424 }
425 }
426 assert(strcmp(implementation, "UNKNOWN") != 0,
427 "unknown cpu info (changed kstat interface?)");
428 kstat_close(kc);
429 }
430
431 // Figure out cache line sizes using PICL
432 PICL picl((features & sparc64_family_m) != 0);
433 _L1_data_cache_line_size = picl.L1_data_cache_line_size();
434 _L2_cache_line_size = picl.L2_cache_line_size();
435
436 return features;
437 }
|
112 ASSIGNED, // Assigned a value
113 INCONSISTENT // Inconsistent value seen
114 } _state;
115 int _value;
116 public:
117 UniqueValueVisitor(PICL* picl) : _picl(picl), _state(INITIAL) { }
118 int value() {
119 assert(_state == ASSIGNED, "Precondition");
120 return _value;
121 }
122 void set_value(int value) {
123 assert(_state == INITIAL, "Precondition");
124 _value = value;
125 _state = ASSIGNED;
126 }
127 bool is_initial() { return _state == INITIAL; }
128 bool is_assigned() { return _state == ASSIGNED; }
129 bool is_inconsistent() { return _state == INCONSISTENT; }
130 void set_inconsistent() { _state = INCONSISTENT; }
131
132 bool visit(picl_nodehdl_t nodeh, const char* name) {
133 assert(!is_inconsistent(), "Precondition");
134 int curr;
135 if (_picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
136 if (!is_assigned()) { // first iteration
137 set_value(curr);
138 } else if (curr != value()) { // following iterations
139 set_inconsistent();
140 }
141 return true;
142 }
143 return false;
144 }
145 };
146
147 class CPUVisitor {
148 UniqueValueVisitor _l1_visitor;
149 UniqueValueVisitor _l2_visitor;
150 int _limit; // number of times visit() can be run
151 public:
152 CPUVisitor(PICL *picl, int limit) : _l1_visitor(picl), _l2_visitor(picl), _limit(limit) {}
153 static int visit(picl_nodehdl_t nodeh, void *arg) {
154 CPUVisitor *cpu_visitor = static_cast<CPUVisitor*>(arg);
155 UniqueValueVisitor* l1_visitor = cpu_visitor->l1_visitor();
156 UniqueValueVisitor* l2_visitor = cpu_visitor->l2_visitor();
157 if (!l1_visitor->is_inconsistent()) {
158 l1_visitor->visit(nodeh, "l1-dcache-line-size");
159 }
160 static const char* l2_data_cache_line_property_name = NULL;
161 // One the first visit determine the name of the l2 cache line size property and memoize it.
162 if (l2_data_cache_line_property_name == NULL) {
163 assert(!l2_visitor->is_inconsistent(), "First iteration cannot be inconsistent");
164 l2_data_cache_line_property_name = "l2-cache-line-size";
165 if (!l2_visitor->visit(nodeh, l2_data_cache_line_property_name)) {
166 l2_data_cache_line_property_name = "l2-dcache-line-size";
167 l2_visitor->visit(nodeh, l2_data_cache_line_property_name);
168 }
169 } else {
170 if (!l2_visitor->is_inconsistent()) {
171 l2_visitor->visit(nodeh, l2_data_cache_line_property_name);
172 }
173 }
174
175 if (l1_visitor->is_inconsistent() && l2_visitor->is_inconsistent()) {
176 return PICL_WALK_TERMINATE;
177 }
178 cpu_visitor->_limit--;
179 if (cpu_visitor->_limit <= 0) {
180 return PICL_WALK_TERMINATE;
181 }
182 return PICL_WALK_CONTINUE;
183 }
184 UniqueValueVisitor* l1_visitor() { return &_l1_visitor; }
185 UniqueValueVisitor* l2_visitor() { return &_l2_visitor; }
186 };
187 int _L1_data_cache_line_size;
188 int _L2_data_cache_line_size;
189 public:
190 static int visit_cpu(picl_nodehdl_t nodeh, void *state) {
191 return CPUVisitor::visit(nodeh, state);
192 }
193
194 PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) {
195 if (!open_library()) {
196 return;
197 }
198 if (_picl_initialize() == PICL_SUCCESS) {
199 picl_nodehdl_t rooth;
200 if (_picl_get_root(&rooth) == PICL_SUCCESS) {
201 const char* cpu_class = "cpu";
202 // If it's a Fujitsu machine, it's a "core"
203 if (is_fujitsu) {
204 cpu_class = "core";
205 }
206 CPUVisitor cpu_visitor(this, os::processor_count());
207 _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper);
208 if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value?
209 _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value();
210 }
211 if (cpu_visitor.l2_visitor()->is_assigned()) {
212 _L2_data_cache_line_size = cpu_visitor.l2_visitor()->value();
213 }
214 }
215 _picl_shutdown();
216 }
217 close_library();
218 }
219
220 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
221 unsigned int L2_data_cache_line_size() const { return _L2_data_cache_line_size; }
222 };
223
224
225 extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result) {
226 return PICL::visit_cpu(nodeh, result);
227 }
228
229 template<typename FuncType>
230 bool PICL::bind(FuncType& func, const char* name) {
231 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name));
232 return func != NULL;
233 }
234
235 bool PICL::bind_library_functions() {
236 assert(_dl_handle != NULL, "library should be open");
237 return bind(_picl_initialize, "picl_initialize" ) &&
238 bind(_picl_shutdown, "picl_shutdown" ) &&
239 bind(_picl_get_root, "picl_get_root" ) &&
240 bind(_picl_walk_tree_by_class, "picl_walk_tree_by_class") &&
241 bind(_picl_get_prop_by_name, "picl_get_prop_by_name" ) &&
427 // safe side.
428 warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl);
429 #endif
430 implementation = "SPARC";
431 }
432 }
433 os::free((void*)impl);
434 break;
435 }
436 } // for(
437 }
438 }
439 assert(strcmp(implementation, "UNKNOWN") != 0,
440 "unknown cpu info (changed kstat interface?)");
441 kstat_close(kc);
442 }
443
444 // Figure out cache line sizes using PICL
445 PICL picl((features & sparc64_family_m) != 0);
446 _L1_data_cache_line_size = picl.L1_data_cache_line_size();
447 _L2_data_cache_line_size = picl.L2_data_cache_line_size();
448
449 return features;
450 }
|