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