8369250: Assess and remedy any unsafe usage of the Semaphore used by NonJavaThread::List

Reviewed-by: kbarrett, stefank
This commit is contained in:
David Holmes 2025-10-08 20:28:21 +00:00
parent 92f2ab2e1b
commit 4d0da18ab6
3 changed files with 24 additions and 12 deletions

View File

@ -50,15 +50,19 @@ public:
List() : _head(nullptr), _protect() {}
};
NonJavaThread::List NonJavaThread::_the_list;
DeferredStatic<NonJavaThread::List> NonJavaThread::_the_list;
void NonJavaThread::init() {
_the_list.initialize();
}
NonJavaThread::Iterator::Iterator() :
_protect_enter(_the_list._protect.enter()),
_current(AtomicAccess::load_acquire(&_the_list._head))
_protect_enter(_the_list->_protect.enter()),
_current(AtomicAccess::load_acquire(&_the_list->_head))
{}
NonJavaThread::Iterator::~Iterator() {
_the_list._protect.exit(_protect_enter);
_the_list->_protect.exit(_protect_enter);
}
void NonJavaThread::Iterator::step() {
@ -76,8 +80,8 @@ void NonJavaThread::add_to_the_list() {
MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
// Initialize BarrierSet-related data before adding to list.
BarrierSet::barrier_set()->on_thread_attach(this);
AtomicAccess::release_store(&_next, _the_list._head);
AtomicAccess::release_store(&_the_list._head, this);
AtomicAccess::release_store(&_next, _the_list->_head);
AtomicAccess::release_store(&_the_list->_head, this);
}
void NonJavaThread::remove_from_the_list() {
@ -85,7 +89,7 @@ void NonJavaThread::remove_from_the_list() {
MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
// Cleanup BarrierSet-related data before removing from list.
BarrierSet::barrier_set()->on_thread_detach(this);
NonJavaThread* volatile* p = &_the_list._head;
NonJavaThread* volatile* p = &_the_list->_head;
for (NonJavaThread* t = *p; t != nullptr; p = &t->_next, t = *p) {
if (t == this) {
*p = _next;
@ -97,7 +101,7 @@ void NonJavaThread::remove_from_the_list() {
// allowed, so do it while holding a dedicated lock. Outside and distinct
// from NJTList_lock in case an iteration attempts to lock it.
MutexLocker ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag);
_the_list._protect.synchronize();
_the_list->_protect.synchronize();
_next = nullptr; // Safe to drop the link now.
}
@ -344,4 +348,3 @@ void WatcherThread::print_on(outputStream* st) const {
Thread::print_on(st);
st->cr();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -26,12 +26,18 @@
#define SHARE_RUNTIME_NONJAVATHREAD_HPP
#include "runtime/thread.hpp"
#include "utilities/deferredStatic.hpp"
class NonJavaThread: public Thread {
NonJavaThread* volatile _next;
friend class Threads;
class List;
static List _the_list;
static DeferredStatic<List> _the_list;
// Deferred static initialization
static void init();
NonJavaThread* volatile _next;
void add_to_the_list();
void remove_from_the_list();

View File

@ -446,6 +446,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// Check version
if (!is_supported_jni_version(args->version)) return JNI_EVERSION;
// Deferred "static" initialization
NonJavaThread::init();
// Initialize library-based TLS
ThreadLocalStorage::init();