src/share/vm/gc_implementation/shared/concurrentGCThread.cpp

Wed, 31 Jul 2019 14:28:51 -0400

author
kbarrett
date
Wed, 31 Jul 2019 14:28:51 -0400
changeset 9787
9f28a4cac6d9
parent 7360
4e4ebe50c8e3
child 7535
7ae4e26cb1e0
permissions
-rw-r--r--

8048556: Unnecessary GCLocker-initiated young GCs
Summary: Fixed recognition of unnecessary GCLocker collections.
Reviewed-by: pliden, tschatzl
Contributed-by: johnc@azul.com

     1 /*
     2  * Copyright (c) 2001, 2012, 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  */
    25 #include "precompiled.hpp"
    26 #include "classfile/systemDictionary.hpp"
    27 #include "gc_implementation/shared/concurrentGCThread.hpp"
    28 #include "oops/instanceRefKlass.hpp"
    29 #include "oops/oop.inline.hpp"
    30 #include "runtime/init.hpp"
    31 #include "runtime/interfaceSupport.hpp"
    32 #include "runtime/java.hpp"
    33 #include "runtime/javaCalls.hpp"
    35 // CopyrightVersion 1.2
    37 int  ConcurrentGCThread::_CGC_flag            = CGC_nil;
    39 ConcurrentGCThread::ConcurrentGCThread() :
    40   _should_terminate(false), _has_terminated(false) {
    41 };
    43 void ConcurrentGCThread::create_and_start() {
    44   if (os::create_thread(this, os::cgc_thread)) {
    45     // XXX: need to set this to low priority
    46     // unless "agressive mode" set; priority
    47     // should be just less than that of VMThread.
    48     os::set_priority(this, NearMaxPriority);
    49     if (!_should_terminate && !DisableStartThread) {
    50       os::start_thread(this);
    51     }
    52   }
    53 }
    55 void ConcurrentGCThread::initialize_in_thread() {
    56   this->record_stack_base_and_size();
    57   this->initialize_thread_local_storage();
    58   this->set_active_handles(JNIHandleBlock::allocate_block());
    59   // From this time Thread::current() should be working.
    60   assert(this == Thread::current(), "just checking");
    61 }
    63 void ConcurrentGCThread::wait_for_universe_init() {
    64   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
    65   while (!is_init_completed() && !_should_terminate) {
    66     CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
    67   }
    68 }
    70 void ConcurrentGCThread::terminate() {
    71   // Signal that it is terminated
    72   {
    73     MutexLockerEx mu(Terminator_lock,
    74                      Mutex::_no_safepoint_check_flag);
    75     _has_terminated = true;
    76     Terminator_lock->notify();
    77   }
    79   // Thread destructor usually does this..
    80   ThreadLocalStorage::set_thread(NULL);
    81 }
    83 static void _sltLoop(JavaThread* thread, TRAPS) {
    84   SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
    85   slt->loop();
    86 }
    88 SurrogateLockerThread::SurrogateLockerThread() :
    89   JavaThread(&_sltLoop),
    90   _monitor(Mutex::nonleaf, "SLTMonitor"),
    91   _buffer(empty)
    92 {}
    94 SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
    95   Klass* k =
    96     SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
    97                                       true, CHECK_NULL);
    98   instanceKlassHandle klass (THREAD, k);
    99   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
   101   const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
   102   Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
   104   // Initialize thread_oop to put it into the system threadGroup
   105   Handle thread_group (THREAD, Universe::system_thread_group());
   106   JavaValue result(T_VOID);
   107   JavaCalls::call_special(&result, thread_oop,
   108                           klass,
   109                           vmSymbols::object_initializer_name(),
   110                           vmSymbols::threadgroup_string_void_signature(),
   111                           thread_group,
   112                           string,
   113                           CHECK_NULL);
   115   SurrogateLockerThread* res;
   116   {
   117     MutexLocker mu(Threads_lock);
   118     res = new SurrogateLockerThread();
   120     // At this point it may be possible that no osthread was created for the
   121     // JavaThread due to lack of memory. We would have to throw an exception
   122     // in that case. However, since this must work and we do not allow
   123     // exceptions anyway, check and abort if this fails.
   124     if (res == NULL || res->osthread() == NULL) {
   125       vm_exit_during_initialization("java.lang.OutOfMemoryError",
   126                                     "unable to create new native thread");
   127     }
   128     java_lang_Thread::set_thread(thread_oop(), res);
   129     java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
   130     java_lang_Thread::set_daemon(thread_oop());
   132     res->set_threadObj(thread_oop());
   133     Threads::add(res);
   134     Thread::start(res);
   135   }
   136   os::yield(); // This seems to help with initial start-up of SLT
   137   return res;
   138 }
   140 void SurrogateLockerThread::report_missing_slt() {
   141   vm_exit_during_initialization(
   142     "GC before GC support fully initialized: "
   143     "SLT is needed but has not yet been created.");
   144   ShouldNotReachHere();
   145 }
   147 void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
   148   MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
   149   assert(_buffer == empty, "Should be empty");
   150   assert(msg != empty, "empty message");
   151   assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
   153   _buffer = msg;
   154   while (_buffer != empty) {
   155     _monitor.notify();
   156     _monitor.wait(Mutex::_no_safepoint_check_flag);
   157   }
   158 }
   160 // ======= Surrogate Locker Thread =============
   162 void SurrogateLockerThread::loop() {
   163   BasicLock pll_basic_lock;
   164   SLT_msg_type msg;
   165   debug_only(unsigned int owned = 0;)
   167   while (/* !isTerminated() */ 1) {
   168     {
   169       MutexLocker x(&_monitor);
   170       // Since we are a JavaThread, we can't be here at a safepoint.
   171       assert(!SafepointSynchronize::is_at_safepoint(),
   172              "SLT is a JavaThread");
   173       // wait for msg buffer to become non-empty
   174       while (_buffer == empty) {
   175         _monitor.notify();
   176         _monitor.wait();
   177       }
   178       msg = _buffer;
   179     }
   180     switch(msg) {
   181       case acquirePLL: {
   182         InstanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
   183         debug_only(owned++;)
   184         break;
   185       }
   186       case releaseAndNotifyPLL: {
   187         assert(owned > 0, "Don't have PLL");
   188         InstanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
   189         debug_only(owned--;)
   190         break;
   191       }
   192       case empty:
   193       default: {
   194         guarantee(false,"Unexpected message in _buffer");
   195         break;
   196       }
   197     }
   198     {
   199       MutexLocker x(&_monitor);
   200       // Since we are a JavaThread, we can't be here at a safepoint.
   201       assert(!SafepointSynchronize::is_at_safepoint(),
   202              "SLT is a JavaThread");
   203       _buffer = empty;
   204       _monitor.notify();
   205     }
   206   }
   207   assert(!_monitor.owned_by_self(), "Should unlock before exit.");
   208 }

mercurial