Tue, 19 Aug 2014 02:05:49 -0700
8044406: JVM crash with JDK8 (build 1.8.0-b132) with G1 GC
Summary: Fill the last card that has been allocated into with a dummy object
Reviewed-by: tschatzl, mgerdin
ysr@777 | 1 | /* |
tschatzl@7445 | 2 | * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. |
ysr@777 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ysr@777 | 4 | * |
ysr@777 | 5 | * This code is free software; you can redistribute it and/or modify it |
ysr@777 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ysr@777 | 7 | * published by the Free Software Foundation. |
ysr@777 | 8 | * |
ysr@777 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ysr@777 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ysr@777 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ysr@777 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
ysr@777 | 13 | * accompanied this code). |
ysr@777 | 14 | * |
ysr@777 | 15 | * You should have received a copy of the GNU General Public License version |
ysr@777 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
ysr@777 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ysr@777 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
ysr@777 | 22 | * |
ysr@777 | 23 | */ |
ysr@777 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "gc_implementation/g1/ptrQueue.hpp" |
stefank@2314 | 27 | #include "memory/allocation.hpp" |
stefank@2314 | 28 | #include "memory/allocation.inline.hpp" |
stefank@2314 | 29 | #include "runtime/mutex.hpp" |
stefank@2314 | 30 | #include "runtime/mutexLocker.hpp" |
stefank@4299 | 31 | #include "runtime/thread.inline.hpp" |
ysr@777 | 32 | |
tonyp@2469 | 33 | PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : |
tschatzl@7445 | 34 | _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), |
ysr@777 | 35 | _perm(perm), _lock(NULL) |
ysr@777 | 36 | {} |
ysr@777 | 37 | |
tschatzl@7445 | 38 | PtrQueue::~PtrQueue() { |
tschatzl@7445 | 39 | assert(_perm || (_buf == NULL), "queue must be flushed before delete"); |
tschatzl@7445 | 40 | } |
tschatzl@7445 | 41 | |
tschatzl@7445 | 42 | void PtrQueue::flush_impl() { |
ysr@777 | 43 | if (!_perm && _buf != NULL) { |
ysr@777 | 44 | if (_index == _sz) { |
ysr@777 | 45 | // No work to do. |
ysr@777 | 46 | qset()->deallocate_buffer(_buf); |
ysr@777 | 47 | } else { |
ysr@777 | 48 | // We must NULL out the unused entries, then enqueue. |
ysr@777 | 49 | for (size_t i = 0; i < _index; i += oopSize) { |
ysr@777 | 50 | _buf[byte_index_to_index((int)i)] = NULL; |
ysr@777 | 51 | } |
ysr@777 | 52 | qset()->enqueue_complete_buffer(_buf); |
ysr@777 | 53 | } |
iveresov@876 | 54 | _buf = NULL; |
iveresov@876 | 55 | _index = 0; |
ysr@777 | 56 | } |
ysr@777 | 57 | } |
ysr@777 | 58 | |
ysr@777 | 59 | |
ysr@777 | 60 | void PtrQueue::enqueue_known_active(void* ptr) { |
ysr@777 | 61 | assert(0 <= _index && _index <= _sz, "Invariant."); |
ysr@777 | 62 | assert(_index == 0 || _buf != NULL, "invariant"); |
ysr@777 | 63 | |
ysr@777 | 64 | while (_index == 0) { |
ysr@777 | 65 | handle_zero_index(); |
ysr@777 | 66 | } |
iveresov@1546 | 67 | |
ysr@777 | 68 | assert(_index > 0, "postcondition"); |
ysr@777 | 69 | _index -= oopSize; |
ysr@777 | 70 | _buf[byte_index_to_index((int)_index)] = ptr; |
ysr@777 | 71 | assert(0 <= _index && _index <= _sz, "Invariant."); |
ysr@777 | 72 | } |
ysr@777 | 73 | |
ysr@777 | 74 | void PtrQueue::locking_enqueue_completed_buffer(void** buf) { |
ysr@777 | 75 | assert(_lock->owned_by_self(), "Required."); |
johnc@1604 | 76 | |
johnc@1604 | 77 | // We have to unlock _lock (which may be Shared_DirtyCardQ_lock) before |
johnc@1604 | 78 | // we acquire DirtyCardQ_CBL_mon inside enqeue_complete_buffer as they |
johnc@1604 | 79 | // have the same rank and we may get the "possible deadlock" message |
ysr@777 | 80 | _lock->unlock(); |
johnc@1604 | 81 | |
ysr@777 | 82 | qset()->enqueue_complete_buffer(buf); |
ysr@777 | 83 | // We must relock only because the caller will unlock, for the normal |
ysr@777 | 84 | // case. |
ysr@777 | 85 | _lock->lock_without_safepoint_check(); |
ysr@777 | 86 | } |
ysr@777 | 87 | |
ysr@777 | 88 | |
ysr@777 | 89 | PtrQueueSet::PtrQueueSet(bool notify_when_complete) : |
ysr@777 | 90 | _max_completed_queue(0), |
ysr@777 | 91 | _cbl_mon(NULL), _fl_lock(NULL), |
ysr@777 | 92 | _notify_when_complete(notify_when_complete), |
ysr@777 | 93 | _sz(0), |
ysr@777 | 94 | _completed_buffers_head(NULL), |
ysr@777 | 95 | _completed_buffers_tail(NULL), |
ysr@777 | 96 | _n_completed_buffers(0), |
ysr@777 | 97 | _process_completed_threshold(0), _process_completed(false), |
ysr@777 | 98 | _buf_free_list(NULL), _buf_free_list_sz(0) |
iveresov@1051 | 99 | { |
iveresov@1051 | 100 | _fl_owner = this; |
iveresov@1051 | 101 | } |
ysr@777 | 102 | |
ysr@777 | 103 | void** PtrQueueSet::allocate_buffer() { |
ysr@777 | 104 | assert(_sz > 0, "Didn't set a buffer size."); |
iveresov@1051 | 105 | MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); |
iveresov@1051 | 106 | if (_fl_owner->_buf_free_list != NULL) { |
iveresov@1546 | 107 | void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list); |
iveresov@1546 | 108 | _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next(); |
iveresov@1051 | 109 | _fl_owner->_buf_free_list_sz--; |
ysr@777 | 110 | return res; |
ysr@777 | 111 | } else { |
iveresov@1546 | 112 | // Allocate space for the BufferNode in front of the buffer. |
zgu@3900 | 113 | char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size(), mtGC); |
iveresov@1546 | 114 | return BufferNode::make_buffer_from_block(b); |
ysr@777 | 115 | } |
ysr@777 | 116 | } |
ysr@777 | 117 | |
ysr@777 | 118 | void PtrQueueSet::deallocate_buffer(void** buf) { |
ysr@777 | 119 | assert(_sz > 0, "Didn't set a buffer size."); |
iveresov@1051 | 120 | MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); |
iveresov@1546 | 121 | BufferNode *node = BufferNode::make_node_from_buffer(buf); |
iveresov@1546 | 122 | node->set_next(_fl_owner->_buf_free_list); |
iveresov@1546 | 123 | _fl_owner->_buf_free_list = node; |
iveresov@1051 | 124 | _fl_owner->_buf_free_list_sz++; |
ysr@777 | 125 | } |
ysr@777 | 126 | |
ysr@777 | 127 | void PtrQueueSet::reduce_free_list() { |
iveresov@1546 | 128 | assert(_fl_owner == this, "Free list reduction is allowed only for the owner"); |
ysr@777 | 129 | // For now we'll adopt the strategy of deleting half. |
ysr@777 | 130 | MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); |
ysr@777 | 131 | size_t n = _buf_free_list_sz / 2; |
ysr@777 | 132 | while (n > 0) { |
ysr@777 | 133 | assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong."); |
iveresov@1546 | 134 | void* b = BufferNode::make_block_from_node(_buf_free_list); |
iveresov@1546 | 135 | _buf_free_list = _buf_free_list->next(); |
zgu@3900 | 136 | FREE_C_HEAP_ARRAY(char, b, mtGC); |
johnc@1519 | 137 | _buf_free_list_sz --; |
ysr@777 | 138 | n--; |
ysr@777 | 139 | } |
ysr@777 | 140 | } |
ysr@777 | 141 | |
iveresov@1546 | 142 | void PtrQueue::handle_zero_index() { |
tonyp@2469 | 143 | assert(_index == 0, "Precondition."); |
tonyp@2469 | 144 | |
iveresov@1546 | 145 | // This thread records the full buffer and allocates a new one (while |
iveresov@1546 | 146 | // holding the lock if there is one). |
iveresov@1546 | 147 | if (_buf != NULL) { |
tonyp@2469 | 148 | if (!should_enqueue_buffer()) { |
tonyp@2469 | 149 | assert(_index > 0, "the buffer can only be re-used if it's not full"); |
tonyp@2469 | 150 | return; |
tonyp@2469 | 151 | } |
tonyp@2469 | 152 | |
iveresov@1546 | 153 | if (_lock) { |
johnc@1604 | 154 | assert(_lock->owned_by_self(), "Required."); |
johnc@1604 | 155 | |
johnc@1604 | 156 | // The current PtrQ may be the shared dirty card queue and |
johnc@1604 | 157 | // may be being manipulated by more than one worker thread |
johnc@1604 | 158 | // during a pause. Since the enqueuing of the completed |
johnc@1604 | 159 | // buffer unlocks the Shared_DirtyCardQ_lock more than one |
johnc@1604 | 160 | // worker thread can 'race' on reading the shared queue attributes |
johnc@1604 | 161 | // (_buf and _index) and multiple threads can call into this |
johnc@1604 | 162 | // routine for the same buffer. This will cause the completed |
johnc@1604 | 163 | // buffer to be added to the CBL multiple times. |
johnc@1604 | 164 | |
johnc@1604 | 165 | // We "claim" the current buffer by caching value of _buf in |
johnc@1604 | 166 | // a local and clearing the field while holding _lock. When |
johnc@1604 | 167 | // _lock is released (while enqueueing the completed buffer) |
johnc@1604 | 168 | // the thread that acquires _lock will skip this code, |
johnc@1604 | 169 | // preventing the subsequent the multiple enqueue, and |
johnc@1604 | 170 | // install a newly allocated buffer below. |
johnc@1604 | 171 | |
johnc@1604 | 172 | void** buf = _buf; // local pointer to completed buffer |
johnc@1604 | 173 | _buf = NULL; // clear shared _buf field |
johnc@1604 | 174 | |
johnc@1604 | 175 | locking_enqueue_completed_buffer(buf); // enqueue completed buffer |
johnc@1604 | 176 | |
johnc@1604 | 177 | // While the current thread was enqueuing the buffer another thread |
johnc@1604 | 178 | // may have a allocated a new buffer and inserted it into this pointer |
johnc@1604 | 179 | // queue. If that happens then we just return so that the current |
johnc@1604 | 180 | // thread doesn't overwrite the buffer allocated by the other thread |
johnc@1604 | 181 | // and potentially losing some dirtied cards. |
johnc@1604 | 182 | |
johnc@1604 | 183 | if (_buf != NULL) return; |
iveresov@1546 | 184 | } else { |
iveresov@1546 | 185 | if (qset()->process_or_enqueue_complete_buffer(_buf)) { |
iveresov@1546 | 186 | // Recycle the buffer. No allocation. |
iveresov@1546 | 187 | _sz = qset()->buffer_size(); |
iveresov@1546 | 188 | _index = _sz; |
iveresov@1546 | 189 | return; |
iveresov@1546 | 190 | } |
iveresov@1546 | 191 | } |
iveresov@1546 | 192 | } |
iveresov@1546 | 193 | // Reallocate the buffer |
iveresov@1546 | 194 | _buf = qset()->allocate_buffer(); |
iveresov@1546 | 195 | _sz = qset()->buffer_size(); |
iveresov@1546 | 196 | _index = _sz; |
iveresov@1546 | 197 | assert(0 <= _index && _index <= _sz, "Invariant."); |
iveresov@1546 | 198 | } |
ysr@777 | 199 | |
iveresov@1546 | 200 | bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) { |
iveresov@1546 | 201 | if (Thread::current()->is_Java_thread()) { |
iveresov@1546 | 202 | // We don't lock. It is fine to be epsilon-precise here. |
iveresov@1546 | 203 | if (_max_completed_queue == 0 || _max_completed_queue > 0 && |
iveresov@1546 | 204 | _n_completed_buffers >= _max_completed_queue + _completed_queue_padding) { |
iveresov@1546 | 205 | bool b = mut_process_buffer(buf); |
iveresov@1546 | 206 | if (b) { |
iveresov@1546 | 207 | // True here means that the buffer hasn't been deallocated and the caller may reuse it. |
iveresov@1546 | 208 | return true; |
iveresov@1546 | 209 | } |
iveresov@1546 | 210 | } |
iveresov@1546 | 211 | } |
iveresov@1546 | 212 | // The buffer will be enqueued. The caller will have to get a new one. |
iveresov@1546 | 213 | enqueue_complete_buffer(buf); |
iveresov@1546 | 214 | return false; |
iveresov@1546 | 215 | } |
ysr@777 | 216 | |
iveresov@1546 | 217 | void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { |
iveresov@1546 | 218 | MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
iveresov@1546 | 219 | BufferNode* cbn = BufferNode::new_from_buffer(buf); |
iveresov@1546 | 220 | cbn->set_index(index); |
ysr@777 | 221 | if (_completed_buffers_tail == NULL) { |
ysr@777 | 222 | assert(_completed_buffers_head == NULL, "Well-formedness"); |
ysr@777 | 223 | _completed_buffers_head = cbn; |
ysr@777 | 224 | _completed_buffers_tail = cbn; |
ysr@777 | 225 | } else { |
iveresov@1546 | 226 | _completed_buffers_tail->set_next(cbn); |
ysr@777 | 227 | _completed_buffers_tail = cbn; |
ysr@777 | 228 | } |
ysr@777 | 229 | _n_completed_buffers++; |
ysr@777 | 230 | |
iveresov@1546 | 231 | if (!_process_completed && _process_completed_threshold >= 0 && |
iveresov@1229 | 232 | _n_completed_buffers >= _process_completed_threshold) { |
ysr@777 | 233 | _process_completed = true; |
ysr@777 | 234 | if (_notify_when_complete) |
iveresov@1546 | 235 | _cbl_mon->notify(); |
ysr@777 | 236 | } |
ysr@777 | 237 | debug_only(assert_completed_buffer_list_len_correct_locked()); |
ysr@777 | 238 | } |
ysr@777 | 239 | |
ysr@777 | 240 | int PtrQueueSet::completed_buffers_list_length() { |
ysr@777 | 241 | int n = 0; |
iveresov@1546 | 242 | BufferNode* cbn = _completed_buffers_head; |
ysr@777 | 243 | while (cbn != NULL) { |
ysr@777 | 244 | n++; |
iveresov@1546 | 245 | cbn = cbn->next(); |
ysr@777 | 246 | } |
ysr@777 | 247 | return n; |
ysr@777 | 248 | } |
ysr@777 | 249 | |
ysr@777 | 250 | void PtrQueueSet::assert_completed_buffer_list_len_correct() { |
ysr@777 | 251 | MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
ysr@777 | 252 | assert_completed_buffer_list_len_correct_locked(); |
ysr@777 | 253 | } |
ysr@777 | 254 | |
ysr@777 | 255 | void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() { |
iveresov@1546 | 256 | guarantee(completed_buffers_list_length() == _n_completed_buffers, |
ysr@777 | 257 | "Completed buffer length is wrong."); |
ysr@777 | 258 | } |
ysr@777 | 259 | |
ysr@777 | 260 | void PtrQueueSet::set_buffer_size(size_t sz) { |
ysr@777 | 261 | assert(_sz == 0 && sz > 0, "Should be called only once."); |
ysr@777 | 262 | _sz = sz * oopSize; |
ysr@777 | 263 | } |
ysr@777 | 264 | |
iveresov@1546 | 265 | // Merge lists of buffers. Notify the processing threads. |
iveresov@1546 | 266 | // The source queue is emptied as a result. The queues |
iveresov@1051 | 267 | // must share the monitor. |
iveresov@1051 | 268 | void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) { |
iveresov@1051 | 269 | assert(_cbl_mon == src->_cbl_mon, "Should share the same lock"); |
iveresov@1051 | 270 | MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
iveresov@1051 | 271 | if (_completed_buffers_tail == NULL) { |
iveresov@1051 | 272 | assert(_completed_buffers_head == NULL, "Well-formedness"); |
iveresov@1051 | 273 | _completed_buffers_head = src->_completed_buffers_head; |
iveresov@1051 | 274 | _completed_buffers_tail = src->_completed_buffers_tail; |
iveresov@1051 | 275 | } else { |
iveresov@1051 | 276 | assert(_completed_buffers_head != NULL, "Well formedness"); |
iveresov@1051 | 277 | if (src->_completed_buffers_head != NULL) { |
iveresov@1546 | 278 | _completed_buffers_tail->set_next(src->_completed_buffers_head); |
iveresov@1051 | 279 | _completed_buffers_tail = src->_completed_buffers_tail; |
iveresov@1051 | 280 | } |
iveresov@1051 | 281 | } |
iveresov@1051 | 282 | _n_completed_buffers += src->_n_completed_buffers; |
iveresov@1051 | 283 | |
iveresov@1051 | 284 | src->_n_completed_buffers = 0; |
iveresov@1051 | 285 | src->_completed_buffers_head = NULL; |
iveresov@1051 | 286 | src->_completed_buffers_tail = NULL; |
iveresov@1051 | 287 | |
iveresov@1051 | 288 | assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL || |
iveresov@1051 | 289 | _completed_buffers_head != NULL && _completed_buffers_tail != NULL, |
iveresov@1051 | 290 | "Sanity"); |
iveresov@1546 | 291 | } |
iveresov@1051 | 292 | |
iveresov@1546 | 293 | void PtrQueueSet::notify_if_necessary() { |
iveresov@1546 | 294 | MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
iveresov@1546 | 295 | if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) { |
iveresov@1051 | 296 | _process_completed = true; |
iveresov@1051 | 297 | if (_notify_when_complete) |
iveresov@1546 | 298 | _cbl_mon->notify(); |
iveresov@1051 | 299 | } |
iveresov@1051 | 300 | } |