342N/A/*
2273N/A * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
342N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
342N/A *
342N/A * This code is free software; you can redistribute it and/or modify it
342N/A * under the terms of the GNU General Public License version 2 only, as
342N/A * published by the Free Software Foundation.
342N/A *
342N/A * This code is distributed in the hope that it will be useful, but WITHOUT
342N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
342N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
342N/A * version 2 for more details (a copy is included in the LICENSE file that
342N/A * accompanied this code).
342N/A *
342N/A * You should have received a copy of the GNU General Public License version
342N/A * 2 along with this work; if not, write to the Free Software Foundation,
342N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
342N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
342N/A *
342N/A */
342N/A
1879N/A#include "precompiled.hpp"
1879N/A#include "classfile/systemDictionary.hpp"
1879N/A#include "gc_implementation/shared/concurrentGCThread.hpp"
1879N/A#include "oops/instanceRefKlass.hpp"
1879N/A#include "oops/oop.inline.hpp"
1879N/A#include "runtime/init.hpp"
1879N/A#include "runtime/interfaceSupport.hpp"
1879N/A#include "runtime/java.hpp"
1879N/A#include "runtime/javaCalls.hpp"
342N/A
1879N/A// CopyrightVersion 1.2
342N/A
342N/Aint ConcurrentGCThread::_CGC_flag = CGC_nil;
342N/A
342N/ASuspendibleThreadSet ConcurrentGCThread::_sts;
342N/A
794N/AConcurrentGCThread::ConcurrentGCThread() :
794N/A _should_terminate(false), _has_terminated(false) {
342N/A _sts.initialize();
342N/A};
342N/A
342N/Avoid ConcurrentGCThread::safepoint_synchronize() {
342N/A _sts.suspend_all();
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::safepoint_desynchronize() {
342N/A _sts.resume_all();
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::create_and_start() {
342N/A if (os::create_thread(this, os::cgc_thread)) {
342N/A // XXX: need to set this to low priority
342N/A // unless "agressive mode" set; priority
342N/A // should be just less than that of VMThread.
342N/A os::set_priority(this, NearMaxPriority);
342N/A if (!_should_terminate && !DisableStartThread) {
342N/A os::start_thread(this);
342N/A }
342N/A }
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::initialize_in_thread() {
342N/A this->record_stack_base_and_size();
342N/A this->initialize_thread_local_storage();
342N/A this->set_active_handles(JNIHandleBlock::allocate_block());
342N/A // From this time Thread::current() should be working.
342N/A assert(this == Thread::current(), "just checking");
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::wait_for_universe_init() {
342N/A MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
342N/A while (!is_init_completed() && !_should_terminate) {
342N/A CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
342N/A }
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::terminate() {
342N/A // Signal that it is terminated
342N/A {
342N/A MutexLockerEx mu(Terminator_lock,
342N/A Mutex::_no_safepoint_check_flag);
342N/A _has_terminated = true;
342N/A Terminator_lock->notify();
342N/A }
342N/A
342N/A // Thread destructor usually does this..
342N/A ThreadLocalStorage::set_thread(NULL);
342N/A}
342N/A
342N/A
342N/Avoid SuspendibleThreadSet::initialize_work() {
342N/A MutexLocker x(STS_init_lock);
342N/A if (!_initialized) {
342N/A _m = new Monitor(Mutex::leaf,
342N/A "SuspendibleThreadSetLock", true);
342N/A _async = 0;
342N/A _async_stop = false;
342N/A _async_stopped = 0;
342N/A _initialized = true;
342N/A }
342N/A}
342N/A
342N/Avoid SuspendibleThreadSet::join() {
342N/A initialize();
342N/A MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
342N/A while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
342N/A _async++;
342N/A assert(_async > 0, "Huh.");
342N/A}
342N/A
342N/Avoid SuspendibleThreadSet::leave() {
342N/A assert(_initialized, "Must be initialized.");
342N/A MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
342N/A _async--;
342N/A assert(_async >= 0, "Huh.");
342N/A if (_async_stop) _m->notify_all();
342N/A}
342N/A
342N/Avoid SuspendibleThreadSet::yield(const char* id) {
342N/A assert(_initialized, "Must be initialized.");
342N/A if (_async_stop) {
342N/A MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
342N/A if (_async_stop) {
342N/A _async_stopped++;
342N/A assert(_async_stopped > 0, "Huh.");
342N/A if (_async_stopped == _async) {
342N/A if (ConcGCYieldTimeout > 0) {
342N/A double now = os::elapsedTime();
342N/A guarantee((now - _suspend_all_start) * 1000.0 <
342N/A (double)ConcGCYieldTimeout,
342N/A "Long delay; whodunit?");
342N/A }
342N/A }
342N/A _m->notify_all();
342N/A while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
342N/A _async_stopped--;
342N/A assert(_async >= 0, "Huh");
342N/A _m->notify_all();
342N/A }
342N/A }
342N/A}
342N/A
342N/Avoid SuspendibleThreadSet::suspend_all() {
342N/A initialize(); // If necessary.
342N/A if (ConcGCYieldTimeout > 0) {
342N/A _suspend_all_start = os::elapsedTime();
342N/A }
342N/A MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
342N/A assert(!_async_stop, "Only one at a time.");
342N/A _async_stop = true;
342N/A while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
342N/A}
342N/A
342N/Avoid SuspendibleThreadSet::resume_all() {
342N/A assert(_initialized, "Must be initialized.");
342N/A MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
342N/A assert(_async_stopped == _async, "Huh.");
342N/A _async_stop = false;
342N/A _m->notify_all();
342N/A}
342N/A
342N/Astatic void _sltLoop(JavaThread* thread, TRAPS) {
342N/A SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
342N/A slt->loop();
342N/A}
342N/A
342N/ASurrogateLockerThread::SurrogateLockerThread() :
342N/A JavaThread(&_sltLoop),
342N/A _monitor(Mutex::nonleaf, "SLTMonitor"),
342N/A _buffer(empty)
342N/A{}
342N/A
342N/ASurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
342N/A klassOop k =
2062N/A SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
342N/A true, CHECK_NULL);
342N/A instanceKlassHandle klass (THREAD, k);
342N/A instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
342N/A
1762N/A const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
342N/A Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
342N/A
342N/A // Initialize thread_oop to put it into the system threadGroup
342N/A Handle thread_group (THREAD, Universe::system_thread_group());
342N/A JavaValue result(T_VOID);
342N/A JavaCalls::call_special(&result, thread_oop,
342N/A klass,
2062N/A vmSymbols::object_initializer_name(),
2062N/A vmSymbols::threadgroup_string_void_signature(),
342N/A thread_group,
342N/A string,
342N/A CHECK_NULL);
342N/A
342N/A SurrogateLockerThread* res;
342N/A {
342N/A MutexLocker mu(Threads_lock);
342N/A res = new SurrogateLockerThread();
342N/A
342N/A // At this point it may be possible that no osthread was created for the
342N/A // JavaThread due to lack of memory. We would have to throw an exception
342N/A // in that case. However, since this must work and we do not allow
342N/A // exceptions anyway, check and abort if this fails.
342N/A if (res == NULL || res->osthread() == NULL) {
342N/A vm_exit_during_initialization("java.lang.OutOfMemoryError",
342N/A "unable to create new native thread");
342N/A }
342N/A java_lang_Thread::set_thread(thread_oop(), res);
342N/A java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
342N/A java_lang_Thread::set_daemon(thread_oop());
342N/A
342N/A res->set_threadObj(thread_oop());
342N/A Threads::add(res);
342N/A Thread::start(res);
342N/A }
342N/A os::yield(); // This seems to help with initial start-up of SLT
342N/A return res;
342N/A}
342N/A
342N/Avoid SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
342N/A MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
342N/A assert(_buffer == empty, "Should be empty");
342N/A assert(msg != empty, "empty message");
2860N/A assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
2860N/A
342N/A _buffer = msg;
342N/A while (_buffer != empty) {
342N/A _monitor.notify();
342N/A _monitor.wait(Mutex::_no_safepoint_check_flag);
342N/A }
342N/A}
342N/A
342N/A// ======= Surrogate Locker Thread =============
342N/A
342N/Avoid SurrogateLockerThread::loop() {
342N/A BasicLock pll_basic_lock;
342N/A SLT_msg_type msg;
342N/A debug_only(unsigned int owned = 0;)
342N/A
342N/A while (/* !isTerminated() */ 1) {
342N/A {
342N/A MutexLocker x(&_monitor);
342N/A // Since we are a JavaThread, we can't be here at a safepoint.
342N/A assert(!SafepointSynchronize::is_at_safepoint(),
342N/A "SLT is a JavaThread");
342N/A // wait for msg buffer to become non-empty
342N/A while (_buffer == empty) {
342N/A _monitor.notify();
342N/A _monitor.wait();
342N/A }
342N/A msg = _buffer;
342N/A }
342N/A switch(msg) {
342N/A case acquirePLL: {
342N/A instanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
342N/A debug_only(owned++;)
342N/A break;
342N/A }
342N/A case releaseAndNotifyPLL: {
342N/A assert(owned > 0, "Don't have PLL");
342N/A instanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
342N/A debug_only(owned--;)
342N/A break;
342N/A }
342N/A case empty:
342N/A default: {
342N/A guarantee(false,"Unexpected message in _buffer");
342N/A break;
342N/A }
342N/A }
342N/A {
342N/A MutexLocker x(&_monitor);
342N/A // Since we are a JavaThread, we can't be here at a safepoint.
342N/A assert(!SafepointSynchronize::is_at_safepoint(),
342N/A "SLT is a JavaThread");
342N/A _buffer = empty;
342N/A _monitor.notify();
342N/A }
342N/A }
342N/A assert(!_monitor.owned_by_self(), "Should unlock before exit.");
342N/A}
342N/A
342N/A
342N/A// ===== STS Access From Outside CGCT =====
342N/A
342N/Avoid ConcurrentGCThread::stsYield(const char* id) {
342N/A assert( Thread::current()->is_ConcurrentGC_thread(),
342N/A "only a conc GC thread can call this" );
342N/A _sts.yield(id);
342N/A}
342N/A
342N/Abool ConcurrentGCThread::stsShouldYield() {
342N/A assert( Thread::current()->is_ConcurrentGC_thread(),
342N/A "only a conc GC thread can call this" );
342N/A return _sts.should_yield();
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::stsJoin() {
342N/A assert( Thread::current()->is_ConcurrentGC_thread(),
342N/A "only a conc GC thread can call this" );
342N/A _sts.join();
342N/A}
342N/A
342N/Avoid ConcurrentGCThread::stsLeave() {
342N/A assert( Thread::current()->is_ConcurrentGC_thread(),
342N/A "only a conc GC thread can call this" );
342N/A _sts.leave();
342N/A}