comparison src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @ 20582:c49cd31b6da6

8059200: Promoted JDK9 b31 for Solaris-amd64 fails (Error: dl failure on line 744, no picl library) on Solaris 11.1 Summary: Manually load libpicl.so (used on SPARC only) Reviewed-by: kvn
author iveresov
date Sat, 25 Oct 2014 21:02:29 -1000
parents d635fd1ac81c
children 7848fc12602b
comparison
equal deleted inserted replaced
20581:b8e2e616c1e9 20582:c49cd31b6da6
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> 33 #include <picl.h>
34 #include <dlfcn.h>
35 #include <link.h>
34 36
35 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result); 37 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); 38 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
37 39
40 // Functions from the library we need (signatures should match those in picl.h)
41 extern "C" {
42 typedef int (*picl_initialize_func_t)(void);
43 typedef int (*picl_shutdown_func_t)(void);
44 typedef int (*picl_get_root_func_t)(picl_nodehdl_t *nodehandle);
45 typedef int (*picl_walk_tree_by_class_func_t)(picl_nodehdl_t rooth,
46 const char *classname, void *c_args,
47 int (*callback_fn)(picl_nodehdl_t hdl, void *args));
48 typedef int (*picl_get_prop_by_name_func_t)(picl_nodehdl_t nodeh, const char *nm,
49 picl_prophdl_t *ph);
50 typedef int (*picl_get_propval_func_t)(picl_prophdl_t proph, void *valbuf, size_t sz);
51 typedef int (*picl_get_propinfo_func_t)(picl_prophdl_t proph, picl_propinfo_t *pi);
52 }
53
38 class PICL { 54 class PICL {
55 // Pointers to functions in the library
56 picl_initialize_func_t _picl_initialize;
57 picl_shutdown_func_t _picl_shutdown;
58 picl_get_root_func_t _picl_get_root;
59 picl_walk_tree_by_class_func_t _picl_walk_tree_by_class;
60 picl_get_prop_by_name_func_t _picl_get_prop_by_name;
61 picl_get_propval_func_t _picl_get_propval;
62 picl_get_propinfo_func_t _picl_get_propinfo;
63 // Handle to the library that is returned by dlopen
64 void *_dl_handle;
65
66 bool open_library();
67 void close_library();
68
69 template<typename FuncType> bool bind(FuncType& func, const char* name);
70 bool bind_library_functions();
71
39 // Get a value of the integer property. The value in the tree can be either 32 or 64 bit 72 // 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. 73 // 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) { 74 int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
42 picl_propinfo_t pinfo; 75 picl_propinfo_t pinfo;
43 picl_prophdl_t proph; 76 picl_prophdl_t proph;
44 if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS || 77 if (_picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
45 picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) { 78 _picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
46 return PICL_FAILURE; 79 return PICL_FAILURE;
47 } 80 }
48 81
49 if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) { 82 if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
50 assert(false, "Invalid property type"); 83 assert(false, "Invalid property type");
51 return PICL_FAILURE; 84 return PICL_FAILURE;
52 } 85 }
53 if (pinfo.size == sizeof(int64_t)) { 86 if (pinfo.size == sizeof(int64_t)) {
54 int64_t val; 87 int64_t val;
55 if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) { 88 if (_picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
56 return PICL_FAILURE; 89 return PICL_FAILURE;
57 } 90 }
58 *result = static_cast<int>(val); 91 *result = static_cast<int>(val);
59 } else if (pinfo.size == sizeof(int32_t)) { 92 } else if (pinfo.size == sizeof(int32_t)) {
60 int32_t val; 93 int32_t val;
61 if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) { 94 if (_picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
62 return PICL_FAILURE; 95 return PICL_FAILURE;
63 } 96 }
64 *result = static_cast<int>(val); 97 *result = static_cast<int>(val);
65 } else { 98 } else {
66 assert(false, "Unexpected integer property size"); 99 assert(false, "Unexpected integer property size");
70 } 103 }
71 104
72 // Visitor and a state machine that visits integer properties and verifies that the 105 // Visitor and a state machine that visits integer properties and verifies that the
73 // values are the same. Stores the unique value observed. 106 // values are the same. Stores the unique value observed.
74 class UniqueValueVisitor { 107 class UniqueValueVisitor {
108 PICL *_picl;
75 enum { 109 enum {
76 INITIAL, // Start state, no assignments happened 110 INITIAL, // Start state, no assignments happened
77 ASSIGNED, // Assigned a value 111 ASSIGNED, // Assigned a value
78 INCONSISTENT // Inconsistent value seen 112 INCONSISTENT // Inconsistent value seen
79 } _state; 113 } _state;
80 int _value; 114 int _value;
81 public: 115 public:
82 UniqueValueVisitor() : _state(INITIAL) { } 116 UniqueValueVisitor(PICL* picl) : _picl(picl), _state(INITIAL) { }
83 int value() { 117 int value() {
84 assert(_state == ASSIGNED, "Precondition"); 118 assert(_state == ASSIGNED, "Precondition");
85 return _value; 119 return _value;
86 } 120 }
87 void set_value(int value) { 121 void set_value(int value) {
94 bool is_inconsistent() { return _state == INCONSISTENT; } 128 bool is_inconsistent() { return _state == INCONSISTENT; }
95 void set_inconsistent() { _state = INCONSISTENT; } 129 void set_inconsistent() { _state = INCONSISTENT; }
96 130
97 static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) { 131 static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
98 UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg); 132 UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
133 PICL* picl = state->_picl;
99 assert(!state->is_inconsistent(), "Precondition"); 134 assert(!state->is_inconsistent(), "Precondition");
100 int curr; 135 int curr;
101 if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) { 136 if (picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
102 if (!state->is_assigned()) { // first iteration 137 if (!state->is_assigned()) { // first iteration
103 state->set_value(curr); 138 state->set_value(curr);
104 } else if (curr != state->value()) { // following iterations 139 } else if (curr != state->value()) { // following iterations
105 state->set_inconsistent(); 140 state->set_inconsistent();
106 } 141 }
120 } 155 }
121 static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) { 156 static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
122 return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state); 157 return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
123 } 158 }
124 159
125 PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) { 160 PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) {
126 if (picl_initialize() == PICL_SUCCESS) { 161 if (!open_library()) {
162 return;
163 }
164 if (_picl_initialize() == PICL_SUCCESS) {
127 picl_nodehdl_t rooth; 165 picl_nodehdl_t rooth;
128 if (picl_get_root(&rooth) == PICL_SUCCESS) { 166 if (_picl_get_root(&rooth) == PICL_SUCCESS) {
129 UniqueValueVisitor L1_state; 167 UniqueValueVisitor L1_state(this);
130 // Visit all "cpu" class instances 168 // Visit all "cpu" class instances
131 picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper); 169 _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 170 if (L1_state.is_initial()) { // Still initial, iteration found no values
133 // Try walk all "core" class instances, it might be a Fujitsu machine 171 // 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); 172 _picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
135 } 173 }
136 if (L1_state.is_assigned()) { // Is there a value? 174 if (L1_state.is_assigned()) { // Is there a value?
137 _L1_data_cache_line_size = L1_state.value(); 175 _L1_data_cache_line_size = L1_state.value();
138 } 176 }
139 177
140 UniqueValueVisitor L2_state; 178 UniqueValueVisitor L2_state(this);
141 picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper); 179 _picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
142 if (L2_state.is_initial()) { 180 if (L2_state.is_initial()) {
143 picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper); 181 _picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
144 } 182 }
145 if (L2_state.is_assigned()) { 183 if (L2_state.is_assigned()) {
146 _L2_cache_line_size = L2_state.value(); 184 _L2_cache_line_size = L2_state.value();
147 } 185 }
148 } 186 }
149 picl_shutdown(); 187 _picl_shutdown();
150 } 188 }
189 close_library();
151 } 190 }
152 191
153 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; } 192 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; } 193 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
155 }; 194 };
157 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { 196 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); 197 return PICL::get_l1_data_cache_line_size(nodeh, result);
159 } 198 }
160 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { 199 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); 200 return PICL::get_l2_cache_line_size(nodeh, result);
201 }
202
203 template<typename FuncType>
204 bool PICL::bind(FuncType& func, const char* name) {
205 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name));
206 return func != NULL;
207 }
208
209 bool PICL::bind_library_functions() {
210 assert(_dl_handle != NULL, "library should be open");
211 return bind(_picl_initialize, "picl_initialize" ) &&
212 bind(_picl_shutdown, "picl_shutdown" ) &&
213 bind(_picl_get_root, "picl_get_root" ) &&
214 bind(_picl_walk_tree_by_class, "picl_walk_tree_by_class") &&
215 bind(_picl_get_prop_by_name, "picl_get_prop_by_name" ) &&
216 bind(_picl_get_propval, "picl_get_propval" ) &&
217 bind(_picl_get_propinfo, "picl_get_propinfo" );
218 }
219
220 bool PICL::open_library() {
221 _dl_handle = dlopen("libpicl.so.1", RTLD_LAZY);
222 if (_dl_handle == NULL) {
223 warning("PICL (libpicl.so.1) is missing. Performance will not be optimal.");
224 return false;
225 }
226 if (!bind_library_functions()) {
227 assert(false, "unexpected PICL API change");
228 close_library();
229 return false;
230 }
231 return true;
232 }
233
234 void PICL::close_library() {
235 assert(_dl_handle != NULL, "library should be open");
236 dlclose(_dl_handle);
237 _dl_handle = NULL;
162 } 238 }
163 239
164 // We need to keep these here as long as we have to build on Solaris 240 // We need to keep these here as long as we have to build on Solaris
165 // versions before 10. 241 // versions before 10.
166 #ifndef SI_ARCHITECTURE_32 242 #ifndef SI_ARCHITECTURE_32