1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "gc/shared/collectedHeap.hpp" 29 #include "gc/shared/referencePendingListLocker.hpp" 30 #include "memory/universe.hpp" 31 #include "runtime/javaCalls.hpp" 32 #include "utilities/preserveException.hpp" 33 34 ReferencePendingListLockerThread::ReferencePendingListLockerThread() : 35 JavaThread(&start), 36 _monitor(Monitor::nonleaf, "ReferencePendingListLocker", false, Monitor::_safepoint_check_sometimes), 37 _message(NONE) {} 38 39 ReferencePendingListLockerThread* ReferencePendingListLockerThread::create(TRAPS) { 40 // Create Java thread objects 41 instanceKlassHandle thread_klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL); 42 instanceHandle thread_object = thread_klass->allocate_instance_handle(CHECK_NULL); 43 Handle thread_name = java_lang_String::create_from_str("Reference Pending List Locker", CHECK_NULL); 44 Handle thread_group = Universe::system_thread_group(); 45 JavaValue result(T_VOID); 46 JavaCalls::call_special(&result, 47 thread_object, 48 thread_klass, 49 vmSymbols::object_initializer_name(), 50 vmSymbols::threadgroup_string_void_signature(), 51 thread_group, 52 thread_name, 53 CHECK_NULL); 54 55 { 56 MutexLocker ml(Threads_lock); 57 58 // Allocate thread 59 ReferencePendingListLockerThread* thread = new ReferencePendingListLockerThread(); 60 if (thread == NULL || thread->osthread() == NULL) { 61 vm_exit_during_initialization("java.lang.OutOfMemoryError", 62 os::native_thread_creation_failed_msg()); 63 } 64 65 // Initialize thread 66 java_lang_Thread::set_thread(thread_object(), thread); 67 java_lang_Thread::set_priority(thread_object(), NearMaxPriority); 68 java_lang_Thread::set_daemon(thread_object()); 69 thread->set_threadObj(thread_object()); 70 71 // Start thread 72 Threads::add(thread); 73 Thread::start(thread); 74 75 return thread; 76 } 77 } 78 79 void ReferencePendingListLockerThread::start(JavaThread* thread, TRAPS) { 80 ReferencePendingListLockerThread* locker_thread = static_cast<ReferencePendingListLockerThread*>(thread); 81 locker_thread->receive_and_handle_messages(); 82 } 83 84 bool ReferencePendingListLockerThread::is_hidden_from_external_view() const { 85 return true; 86 } 87 88 void ReferencePendingListLockerThread::send_message(Message message) { 89 assert(message != NONE, "Should not be none"); 90 MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); 91 92 // Wait for completion of current message 93 while (_message != NONE) { 94 ml.wait(Monitor::_no_safepoint_check_flag); 95 } 96 97 // Send new message 98 _message = message; 99 ml.notify_all(); 100 101 // Wait for completion of new message 102 while (_message != NONE) { 103 ml.wait(Monitor::_no_safepoint_check_flag); 104 } 105 } 106 107 void ReferencePendingListLockerThread::receive_and_handle_messages() { 108 ReferencePendingListLocker pending_list_locker; 109 MonitorLockerEx ml(&_monitor); 110 111 // Main loop, never terminates 112 for (;;) { 113 // Wait for message 114 while (_message == NONE) { 115 ml.wait(); 116 } 117 118 // Handle message 119 if (_message == LOCK) { 120 pending_list_locker.lock(); 121 } else if (_message == UNLOCK) { 122 pending_list_locker.unlock(); 123 } else { 124 ShouldNotReachHere(); 125 } 126 127 // Clear message 128 _message = NONE; 129 ml.notify_all(); 130 } 131 } 132 133 void ReferencePendingListLockerThread::lock() { 134 send_message(LOCK); 135 } 136 137 void ReferencePendingListLockerThread::unlock() { 138 send_message(UNLOCK); 139 } 140 141 bool ReferencePendingListLocker::_is_initialized = false; 142 ReferencePendingListLockerThread* ReferencePendingListLocker::_locker_thread = NULL; 143 144 void ReferencePendingListLocker::initialize(bool needs_locker_thread, TRAPS) { 145 if (needs_locker_thread) { 146 _locker_thread = ReferencePendingListLockerThread::create(CHECK); 147 } 148 149 _is_initialized = true; 150 } 151 152 bool ReferencePendingListLocker::is_initialized() { 153 return _is_initialized; 154 } 155 156 bool ReferencePendingListLocker::is_locked_by_self() { 157 oop pending_list_lock = java_lang_ref_Reference::pending_list_lock(); 158 if (pending_list_lock == NULL) { 159 return false; 160 } 161 162 JavaThread* thread = JavaThread::current(); 163 Handle handle(thread, pending_list_lock); 164 return ObjectSynchronizer::current_thread_holds_lock(thread, handle); 165 } 166 167 void ReferencePendingListLocker::lock() { 168 assert(!Heap_lock->owned_by_self(), "Heap_lock must not be owned by requesting thread"); 169 170 if (Thread::current()->is_Java_thread()) { 171 assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized"); 172 173 // We may enter this with a pending exception 174 PRESERVE_EXCEPTION_MARK; 175 176 HandleMark hm; 177 Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock()); 178 179 assert(!is_locked_by_self(), "Should not be locked by self"); 180 181 // Lock 182 ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD); 183 184 assert(is_locked_by_self(), "Locking failed"); 185 186 if (HAS_PENDING_EXCEPTION) { 187 CLEAR_PENDING_EXCEPTION; 188 } 189 } else { 190 // Delegate operation to locker thread 191 assert(_locker_thread != NULL, "Locker thread not created"); 192 _locker_thread->lock(); 193 } 194 } 195 196 void ReferencePendingListLocker::unlock() { 197 if (Thread::current()->is_Java_thread()) { 198 assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized"); 199 200 // We may enter this with a pending exception 201 PRESERVE_EXCEPTION_MARK; 202 203 HandleMark hm; 204 Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock()); 205 206 assert(is_locked_by_self(), "Should be locked by self"); 207 208 // Notify waiters if the pending list is non-empty 209 if (java_lang_ref_Reference::pending_list() != NULL) { 210 ObjectSynchronizer::notifyall(handle, THREAD); 211 } 212 213 // Unlock 214 ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD); 215 216 assert(!is_locked_by_self(), "Unlocking failed"); 217 218 if (HAS_PENDING_EXCEPTION) { 219 CLEAR_PENDING_EXCEPTION; 220 } 221 } else { 222 // Delegate operation to locker thread 223 assert(_locker_thread != NULL, "Locker thread not created"); 224 _locker_thread->unlock(); 225 } 226 }