|
1 | 1 | /* |
2 | | - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
@@ -1106,70 +1106,87 @@ void ThreadsSMRSupport::print_info_on(const Thread* thread, outputStream* st) { |
1106 | 1106 |
|
1107 | 1107 | // Print Threads class SMR info. |
1108 | 1108 | void ThreadsSMRSupport::print_info_on(outputStream* st) { |
1109 | | - // Only grab the Threads_lock if we don't already own it and if we |
1110 | | - // are not reporting an error. |
1111 | | - // Note: Not grabbing the Threads_lock during error reporting is |
1112 | | - // dangerous because the data structures we want to print can be |
1113 | | - // freed concurrently. However, grabbing the Threads_lock during |
1114 | | - // error reporting can be equally dangerous since this thread might |
1115 | | - // block during error reporting or a nested error could leave the |
1116 | | - // Threads_lock held. The classic no win scenario. |
1117 | | - // |
1118 | | - MutexLocker ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock); |
1119 | | - |
1120 | | - st->print_cr("Threads class SMR info:"); |
1121 | | - st->print_cr("_java_thread_list=" INTPTR_FORMAT ", length=%u, " |
1122 | | - "elements={", p2i(_java_thread_list), |
1123 | | - _java_thread_list->length()); |
1124 | | - print_info_elements_on(st, _java_thread_list); |
1125 | | - st->print_cr("}"); |
1126 | | - if (_to_delete_list != NULL) { |
1127 | | - st->print_cr("_to_delete_list=" INTPTR_FORMAT ", length=%u, " |
1128 | | - "elements={", p2i(_to_delete_list), |
1129 | | - _to_delete_list->length()); |
1130 | | - print_info_elements_on(st, _to_delete_list); |
| 1109 | + bool needs_unlock = false; |
| 1110 | + if (Threads_lock->try_lock()) { |
| 1111 | + // We were able to grab the Threads_lock which makes things safe for |
| 1112 | + // this call, but if we are error reporting, then a nested error |
| 1113 | + // could happen with the Threads_lock held. |
| 1114 | + needs_unlock = true; |
| 1115 | + } |
| 1116 | + |
| 1117 | + ThreadsList* saved_threads_list = NULL; |
| 1118 | + { |
| 1119 | + ThreadsListHandle tlh; // make the current ThreadsList safe for reporting |
| 1120 | + saved_threads_list = tlh.list(); // save for later comparison |
| 1121 | + |
| 1122 | + st->print_cr("Threads class SMR info:"); |
| 1123 | + st->print_cr("_java_thread_list=" INTPTR_FORMAT ", length=%u, elements={", |
| 1124 | + p2i(saved_threads_list), saved_threads_list->length()); |
| 1125 | + print_info_elements_on(st, saved_threads_list); |
1131 | 1126 | st->print_cr("}"); |
1132 | | - for (ThreadsList *t_list = _to_delete_list->next_list(); |
1133 | | - t_list != NULL; t_list = t_list->next_list()) { |
1134 | | - st->print("next-> " INTPTR_FORMAT ", length=%u, " |
1135 | | - "elements={", p2i(t_list), t_list->length()); |
1136 | | - print_info_elements_on(st, t_list); |
| 1127 | + } |
| 1128 | + |
| 1129 | + if (_to_delete_list != NULL) { |
| 1130 | + if (Threads_lock->owned_by_self()) { |
| 1131 | + // Only safe if we have the Threads_lock. |
| 1132 | + st->print_cr("_to_delete_list=" INTPTR_FORMAT ", length=%u, elements={", |
| 1133 | + p2i(_to_delete_list), _to_delete_list->length()); |
| 1134 | + print_info_elements_on(st, _to_delete_list); |
1137 | 1135 | st->print_cr("}"); |
| 1136 | + for (ThreadsList *t_list = _to_delete_list->next_list(); |
| 1137 | + t_list != NULL; t_list = t_list->next_list()) { |
| 1138 | + st->print("next-> " INTPTR_FORMAT ", length=%u, elements={", |
| 1139 | + p2i(t_list), t_list->length()); |
| 1140 | + print_info_elements_on(st, t_list); |
| 1141 | + st->print_cr("}"); |
| 1142 | + } |
| 1143 | + } else { |
| 1144 | + st->print_cr("_to_delete_list=" INTPTR_FORMAT, p2i(_to_delete_list)); |
| 1145 | + st->print_cr("Skipping _to_delete_list fields and contents for safety."); |
1138 | 1146 | } |
1139 | 1147 | } |
1140 | | - if (!EnableThreadSMRStatistics) { |
1141 | | - return; |
1142 | | - } |
1143 | | - st->print_cr("_java_thread_list_alloc_cnt=" UINT64_FORMAT ", " |
1144 | | - "_java_thread_list_free_cnt=" UINT64_FORMAT ", " |
1145 | | - "_java_thread_list_max=%u, " |
1146 | | - "_nested_thread_list_max=%u", |
1147 | | - _java_thread_list_alloc_cnt, |
1148 | | - _java_thread_list_free_cnt, |
1149 | | - _java_thread_list_max, |
1150 | | - _nested_thread_list_max); |
1151 | | - if (_tlh_cnt > 0) { |
1152 | | - st->print_cr("_tlh_cnt=%u" |
1153 | | - ", _tlh_times=%u" |
1154 | | - ", avg_tlh_time=%0.2f" |
1155 | | - ", _tlh_time_max=%u", |
1156 | | - _tlh_cnt, _tlh_times, |
1157 | | - ((double) _tlh_times / _tlh_cnt), |
1158 | | - _tlh_time_max); |
| 1148 | + if (EnableThreadSMRStatistics) { |
| 1149 | + st->print_cr("_java_thread_list_alloc_cnt=" UINT64_FORMAT ", " |
| 1150 | + "_java_thread_list_free_cnt=" UINT64_FORMAT ", " |
| 1151 | + "_java_thread_list_max=%u, " |
| 1152 | + "_nested_thread_list_max=%u", |
| 1153 | + _java_thread_list_alloc_cnt, |
| 1154 | + _java_thread_list_free_cnt, |
| 1155 | + _java_thread_list_max, |
| 1156 | + _nested_thread_list_max); |
| 1157 | + if (_tlh_cnt > 0) { |
| 1158 | + st->print_cr("_tlh_cnt=%u" |
| 1159 | + ", _tlh_times=%u" |
| 1160 | + ", avg_tlh_time=%0.2f" |
| 1161 | + ", _tlh_time_max=%u", |
| 1162 | + _tlh_cnt, _tlh_times, |
| 1163 | + ((double) _tlh_times / _tlh_cnt), |
| 1164 | + _tlh_time_max); |
| 1165 | + } |
| 1166 | + if (_deleted_thread_cnt > 0) { |
| 1167 | + st->print_cr("_deleted_thread_cnt=%u" |
| 1168 | + ", _deleted_thread_times=%u" |
| 1169 | + ", avg_deleted_thread_time=%0.2f" |
| 1170 | + ", _deleted_thread_time_max=%u", |
| 1171 | + _deleted_thread_cnt, _deleted_thread_times, |
| 1172 | + ((double) _deleted_thread_times / _deleted_thread_cnt), |
| 1173 | + _deleted_thread_time_max); |
| 1174 | + } |
| 1175 | + st->print_cr("_delete_lock_wait_cnt=%u, _delete_lock_wait_max=%u", |
| 1176 | + _delete_lock_wait_cnt, _delete_lock_wait_max); |
| 1177 | + st->print_cr("_to_delete_list_cnt=%u, _to_delete_list_max=%u", |
| 1178 | + _to_delete_list_cnt, _to_delete_list_max); |
1159 | 1179 | } |
1160 | | - if (_deleted_thread_cnt > 0) { |
1161 | | - st->print_cr("_deleted_thread_cnt=%u" |
1162 | | - ", _deleted_thread_times=%u" |
1163 | | - ", avg_deleted_thread_time=%0.2f" |
1164 | | - ", _deleted_thread_time_max=%u", |
1165 | | - _deleted_thread_cnt, _deleted_thread_times, |
1166 | | - ((double) _deleted_thread_times / _deleted_thread_cnt), |
1167 | | - _deleted_thread_time_max); |
| 1180 | + if (needs_unlock) { |
| 1181 | + Threads_lock->unlock(); |
| 1182 | + } else { |
| 1183 | + if (_java_thread_list != saved_threads_list) { |
| 1184 | + st->print_cr("The _java_thread_list has changed from " INTPTR_FORMAT |
| 1185 | + " to " INTPTR_FORMAT |
| 1186 | + " so some of the above information may be stale.", |
| 1187 | + p2i(saved_threads_list), p2i(_java_thread_list)); |
| 1188 | + } |
1168 | 1189 | } |
1169 | | - st->print_cr("_delete_lock_wait_cnt=%u, _delete_lock_wait_max=%u", |
1170 | | - _delete_lock_wait_cnt, _delete_lock_wait_max); |
1171 | | - st->print_cr("_to_delete_list_cnt=%u, _to_delete_list_max=%u", |
1172 | | - _to_delete_list_cnt, _to_delete_list_max); |
1173 | 1190 | } |
1174 | 1191 |
|
1175 | 1192 | // Print ThreadsList elements (4 per line). |
|
0 commit comments