hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp
changeset 41034 f1a27e852c25
parent 41033 49af2ecba616
parent 41026 a47b3f11f995
child 41035 9cb87c88ed85
equal deleted inserted replaced
41033:49af2ecba616 41034:f1a27e852c25
     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     // Lock
       
   180     ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD);
       
   181 
       
   182     assert(is_locked_by_self(), "Locking failed");
       
   183 
       
   184     if (HAS_PENDING_EXCEPTION) {
       
   185       CLEAR_PENDING_EXCEPTION;
       
   186     }
       
   187   } else {
       
   188     // Delegate operation to locker thread
       
   189     assert(_locker_thread != NULL, "Locker thread not created");
       
   190     _locker_thread->lock();
       
   191   }
       
   192 }
       
   193 
       
   194 void ReferencePendingListLocker::unlock() {
       
   195   if (Thread::current()->is_Java_thread()) {
       
   196     assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
       
   197 
       
   198     // We may enter this with a pending exception
       
   199     PRESERVE_EXCEPTION_MARK;
       
   200 
       
   201     HandleMark hm;
       
   202     Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
       
   203 
       
   204     assert(is_locked_by_self(), "Should be locked by self");
       
   205 
       
   206     // Notify waiters if the pending list is non-empty
       
   207     if (java_lang_ref_Reference::pending_list() != NULL) {
       
   208       ObjectSynchronizer::notifyall(handle, THREAD);
       
   209     }
       
   210 
       
   211     // Unlock
       
   212     ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD);
       
   213 
       
   214     if (HAS_PENDING_EXCEPTION) {
       
   215       CLEAR_PENDING_EXCEPTION;
       
   216     }
       
   217   } else {
       
   218     // Delegate operation to locker thread
       
   219     assert(_locker_thread != NULL, "Locker thread not created");
       
   220     _locker_thread->unlock();
       
   221   }
       
   222 }