Skip to content

Commit

Permalink
8269466: Factor out the common code for initializing and starting int…
Browse files Browse the repository at this point in the history
…ernal VM JavaThreads

Reviewed-by: mbaesken
Backport-of: 4107dcf6ec3fb7fd6eb0e12cdc404a2dee9ccaa1
  • Loading branch information
TheRealMDoerr committed Jun 29, 2023
1 parent c5649ac commit 1472676
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 220 deletions.
123 changes: 54 additions & 69 deletions src/hotspot/share/compiler/compileBroker.cpp
Expand Up @@ -878,90 +878,75 @@ void DeoptimizeObjectsALotThread::deoptimize_objects_alot_loop_all() {

JavaThread* CompileBroker::make_thread(ThreadType type, jobject thread_handle, CompileQueue* queue, AbstractCompiler* comp, JavaThread* THREAD) {
JavaThread* new_thread = NULL;
{
MutexLocker mu(THREAD, Threads_lock);
switch (type) {
case compiler_t:
assert(comp != NULL, "Compiler instance missing.");
if (!InjectCompilerCreationFailure || comp->num_compiler_threads() == 0) {
CompilerCounters* counters = new CompilerCounters();
new_thread = new CompilerThread(queue, counters);
}
break;
case sweeper_t:
new_thread = new CodeCacheSweeperThread();
break;

switch (type) {
case compiler_t:
assert(comp != NULL, "Compiler instance missing.");
if (!InjectCompilerCreationFailure || comp->num_compiler_threads() == 0) {
CompilerCounters* counters = new CompilerCounters();
new_thread = new CompilerThread(queue, counters);
}
break;
case sweeper_t:
new_thread = new CodeCacheSweeperThread();
break;
#if defined(ASSERT) && COMPILER2_OR_JVMCI
case deoptimizer_t:
new_thread = new DeoptimizeObjectsALotThread();
break;
case deoptimizer_t:
new_thread = new DeoptimizeObjectsALotThread();
break;
#endif // ASSERT
default:
ShouldNotReachHere();
}

// At this point the new CompilerThread data-races with this startup
// thread (which I believe is the primoridal thread and NOT the VM
// thread). This means Java bytecodes being executed at startup can
// queue compile jobs which will run at whatever default priority the
// newly created CompilerThread runs at.


// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory. We would have to throw an exception
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails. But first release the
// lock.

if (new_thread != NULL && new_thread->osthread() != NULL) {

java_lang_Thread::set_thread(JNIHandles::resolve_non_null(thread_handle), new_thread);
default:
ShouldNotReachHere();
}

// Note that this only sets the JavaThread _priority field, which by
// definition is limited to Java priorities and not OS priorities.
// The os-priority is set in the CompilerThread startup code itself
// At this point the new CompilerThread data-races with this startup
// thread (which is the main thread and NOT the VM thread).
// This means Java bytecodes being executed at startup can
// queue compile jobs which will run at whatever default priority the
// newly created CompilerThread runs at.

java_lang_Thread::set_priority(JNIHandles::resolve_non_null(thread_handle), NearMaxPriority);

// Note that we cannot call os::set_priority because it expects Java
// priorities and we are *explicitly* using OS priorities so that it's
// possible to set the compiler thread priority higher than any Java
// thread.
// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of resources. We will handle that failure below.
// Also check new_thread so that static analysis is happy.
if (new_thread != NULL && new_thread->osthread() != NULL) {
Handle thread_oop(THREAD, JNIHandles::resolve_non_null(thread_handle));

int native_prio = CompilerThreadPriority;
if (native_prio == -1) {
if (UseCriticalCompilerThreadPriority) {
native_prio = os::java_to_os_priority[CriticalPriority];
} else {
native_prio = os::java_to_os_priority[NearMaxPriority];
}
}
os::set_native_priority(new_thread, native_prio);
if (type == compiler_t) {
CompilerThread::cast(new_thread)->set_compiler(comp);
}

java_lang_Thread::set_daemon(JNIHandles::resolve_non_null(thread_handle));
// Note that we cannot call os::set_priority because it expects Java
// priorities and we are *explicitly* using OS priorities so that it's
// possible to set the compiler thread priority higher than any Java
// thread.

new_thread->set_threadObj(JNIHandles::resolve_non_null(thread_handle));
if (type == compiler_t) {
CompilerThread::cast(new_thread)->set_compiler(comp);
int native_prio = CompilerThreadPriority;
if (native_prio == -1) {
if (UseCriticalCompilerThreadPriority) {
native_prio = os::java_to_os_priority[CriticalPriority];
} else {
native_prio = os::java_to_os_priority[NearMaxPriority];
}
Threads::add(new_thread);
Thread::start(new_thread);
}
}
os::set_native_priority(new_thread, native_prio);

// First release lock before aborting VM.
if (new_thread == NULL || new_thread->osthread() == NULL) {
if (UseDynamicNumberOfCompilerThreads && type == compiler_t && comp->num_compiler_threads() > 0) {
if (new_thread != NULL) {
new_thread->smr_delete();
}
// Note that this only sets the JavaThread _priority field, which by
// definition is limited to Java priorities and not OS priorities.
JavaThread::start_internal_daemon(THREAD, new_thread, thread_oop, NearMaxPriority);

} else { // osthread initialization failure
if (UseDynamicNumberOfCompilerThreads && type == compiler_t
&& comp->num_compiler_threads() > 0) {
// The new thread is not known to Thread-SMR yet so we can just delete.
delete new_thread;
return NULL;
} else {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}

// Let go of Threads_lock before yielding
os::naked_yield(); // make sure that the compiler thread is started early (especially helpful on SOLARIS)

return new_thread;
Expand Down
33 changes: 11 additions & 22 deletions src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp
Expand Up @@ -46,29 +46,18 @@ static Thread* start_thread(instanceHandle thread_oop, ThreadFunction proc, TRAP
assert(thread_oop.not_null(), "invariant");
assert(proc != NULL, "invariant");

bool allocation_failed = false;
JavaThread* new_thread = NULL;
{
MutexLocker mu(THREAD, Threads_lock);
new_thread = new JavaThread(proc);
// At this point it may be possible that no
// osthread was created for the JavaThread due to lack of memory.
if (new_thread == NULL || new_thread->osthread() == NULL) {
delete new_thread;
allocation_failed = true;
} else {
java_lang_Thread::set_thread(thread_oop(), new_thread);
java_lang_Thread::set_priority(thread_oop(), NormPriority);
java_lang_Thread::set_daemon(thread_oop());
new_thread->set_threadObj(thread_oop());
Threads::add(new_thread);
}
}
if (allocation_failed) {
JfrJavaSupport::throw_out_of_memory_error("Unable to create native recording thread for JFR", CHECK_NULL);
JavaThread* new_thread = new JavaThread(proc);

// At this point it may be possible that no
// osthread was created for the JavaThread due to lack of resources.
if (new_thread->osthread() == NULL) {
delete new_thread;
JfrJavaSupport::throw_out_of_memory_error("Unable to create native recording thread for JFR", THREAD);
return NULL;
} else {
JavaThread::start_internal_daemon(THREAD, new_thread, thread_oop, NormPriority);
return new_thread;
}
Thread::start(new_thread);
return new_thread;
}

JfrPostBox* JfrRecorderThread::_post_box = NULL;
Expand Down
29 changes: 10 additions & 19 deletions src/hotspot/share/prims/jvmtiEnv.cpp
Expand Up @@ -1326,28 +1326,19 @@ JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* ar
}

Handle thread_hndl(current_thread, thread_oop);
{
MutexLocker mu(current_thread, Threads_lock); // grab Threads_lock

JvmtiAgentThread *new_thread = new JvmtiAgentThread(this, proc, arg);
JvmtiAgentThread* new_thread = new JvmtiAgentThread(this, proc, arg);

// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory.
if (new_thread == NULL || new_thread->osthread() == NULL) {
if (new_thread != NULL) {
new_thread->smr_delete();
}
return JVMTI_ERROR_OUT_OF_MEMORY;
}

java_lang_Thread::set_thread(thread_hndl(), new_thread);
java_lang_Thread::set_priority(thread_hndl(), (ThreadPriority)priority);
java_lang_Thread::set_daemon(thread_hndl());
// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of resources.
if (new_thread->osthread() == NULL) {
// The new thread is not known to Thread-SMR yet so we can just delete.
delete new_thread;
return JVMTI_ERROR_OUT_OF_MEMORY;
}

new_thread->set_threadObj(thread_hndl());
Threads::add(new_thread);
Thread::start(new_thread);
} // unlock Threads_lock
JavaThread::start_internal_daemon(current_thread, new_thread, thread_hndl,
(ThreadPriority)priority);

return JVMTI_ERROR_NONE;
} /* end RunAgentThread */
Expand Down
26 changes: 3 additions & 23 deletions src/hotspot/share/runtime/monitorDeflationThread.cpp
Expand Up @@ -33,8 +33,6 @@
#include "runtime/monitorDeflationThread.hpp"
#include "runtime/mutexLocker.hpp"

MonitorDeflationThread* MonitorDeflationThread::_instance = NULL;

void MonitorDeflationThread::initialize() {
EXCEPTION_MARK;

Expand All @@ -50,28 +48,10 @@ void MonitorDeflationThread::initialize() {
string,
CHECK);

{
MutexLocker mu(THREAD, Threads_lock);
MonitorDeflationThread* thread = new MonitorDeflationThread(&monitor_deflation_thread_entry);

// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory. We would have to throw an exception
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails.
if (thread == NULL || thread->osthread() == NULL) {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}
MonitorDeflationThread* thread = new MonitorDeflationThread(&monitor_deflation_thread_entry);
JavaThread::vm_exit_on_osthread_failure(thread);

java_lang_Thread::set_thread(thread_oop(), thread);
java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
java_lang_Thread::set_daemon(thread_oop());
thread->set_threadObj(thread_oop());
_instance = thread;

Threads::add(thread);
Thread::start(thread);
}
JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority);
}

void MonitorDeflationThread::monitor_deflation_thread_entry(JavaThread* jt, TRAPS) {
Expand Down
3 changes: 1 addition & 2 deletions src/hotspot/share/runtime/monitorDeflationThread.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -32,7 +32,6 @@
class MonitorDeflationThread : public JavaThread {
friend class VMStructs;
private:
static MonitorDeflationThread* _instance;

static void monitor_deflation_thread_entry(JavaThread* thread, TRAPS);
MonitorDeflationThread(ThreadFunction entry_point) : JavaThread(entry_point) {};
Expand Down
26 changes: 3 additions & 23 deletions src/hotspot/share/runtime/notificationThread.cpp
Expand Up @@ -35,8 +35,6 @@
#include "services/gcNotifier.hpp"
#include "services/lowMemoryDetector.hpp"

NotificationThread* NotificationThread::_instance = NULL;

void NotificationThread::initialize() {
EXCEPTION_MARK;

Expand All @@ -61,28 +59,11 @@ void NotificationThread::initialize() {
vmSymbols::thread_void_signature(),
thread_oop,
THREAD);
{
MutexLocker mu(THREAD, Threads_lock);
NotificationThread* thread = new NotificationThread(&notification_thread_entry);

// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory. We would have to throw an exception
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails.
if (thread == NULL || thread->osthread() == NULL) {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}

java_lang_Thread::set_thread(thread_oop(), thread);
java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
java_lang_Thread::set_daemon(thread_oop());
thread->set_threadObj(thread_oop());
_instance = thread;
NotificationThread* thread = new NotificationThread(&notification_thread_entry);
JavaThread::vm_exit_on_osthread_failure(thread);

Threads::add(thread);
Thread::start(thread);
}
JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority);
}


Expand Down Expand Up @@ -128,4 +109,3 @@ void NotificationThread::notification_thread_entry(JavaThread* jt, TRAPS) {

}
}

4 changes: 1 addition & 3 deletions src/hotspot/share/runtime/notificationThread.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -36,8 +36,6 @@ class NotificationThread : public JavaThread {
friend class VMStructs;
private:

static NotificationThread* _instance;

static void notification_thread_entry(JavaThread* thread, TRAPS);
NotificationThread(ThreadFunction entry_point) : JavaThread(entry_point) {};

Expand Down
22 changes: 3 additions & 19 deletions src/hotspot/share/runtime/os.cpp
Expand Up @@ -485,26 +485,10 @@ void os::initialize_jdk_signal_support(TRAPS) {
thread_oop,
CHECK);

{ MutexLocker mu(THREAD, Threads_lock);
JavaThread* signal_thread = new JavaThread(&signal_thread_entry);

// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory. We would have to throw an exception
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails.
if (signal_thread == NULL || signal_thread->osthread() == NULL) {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}

java_lang_Thread::set_thread(thread_oop(), signal_thread);
java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
java_lang_Thread::set_daemon(thread_oop());
JavaThread* thread = new JavaThread(&signal_thread_entry);
JavaThread::vm_exit_on_osthread_failure(thread);

signal_thread->set_threadObj(thread_oop());
Threads::add(signal_thread);
Thread::start(signal_thread);
}
JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority);
}
}

Expand Down

1 comment on commit 1472676

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.