mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-13 12:38:07 +00:00
8387490: G1: Dynamically creating worker threads exposes memory visibility race
Reviewed-by: aboldtch, ayang
This commit is contained in:
parent
fc73ca7f38
commit
f264341bac
@ -103,7 +103,7 @@ bool WorkerThreads::allow_inject_creation_failure() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_created_workers == 0) {
|
||||
if (_created_workers.load_relaxed() == 0) {
|
||||
// Never allow creation failures of the first worker, it will cause the VM to exit
|
||||
return false;
|
||||
}
|
||||
@ -135,18 +135,20 @@ uint WorkerThreads::set_active_workers(uint num_workers) {
|
||||
"Invalid number of active workers %u (should be 1-%u)",
|
||||
num_workers, _max_workers);
|
||||
|
||||
while (_created_workers < num_workers) {
|
||||
WorkerThread* const worker = create_worker(_created_workers);
|
||||
uint local_created_workers = created_workers();
|
||||
while (local_created_workers < num_workers) {
|
||||
WorkerThread* const worker = create_worker(local_created_workers);
|
||||
if (worker == nullptr) {
|
||||
log_error(gc, task)("Failed to create worker thread");
|
||||
break;
|
||||
}
|
||||
|
||||
_workers[_created_workers] = worker;
|
||||
_created_workers++;
|
||||
_workers[local_created_workers] = worker;
|
||||
local_created_workers++;
|
||||
_created_workers.release_store(local_created_workers);
|
||||
}
|
||||
|
||||
_active_workers = MIN2(_created_workers, num_workers);
|
||||
_active_workers = MIN2(local_created_workers, num_workers);
|
||||
|
||||
log_trace(gc, task)("%s: using %d out of %d workers", _name, _active_workers, _max_workers);
|
||||
|
||||
@ -154,14 +156,16 @@ uint WorkerThreads::set_active_workers(uint num_workers) {
|
||||
}
|
||||
|
||||
void WorkerThreads::threads_do(ThreadClosure* tc) const {
|
||||
for (uint i = 0; i < _created_workers; i++) {
|
||||
uint local_created_workers = created_workers();
|
||||
for (uint i = 0; i < local_created_workers; i++) {
|
||||
tc->do_thread(_workers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void WorkerThreads::threads_do_f(Function function) const {
|
||||
for (uint i = 0; i < _created_workers; i++) {
|
||||
uint local_created_workers = created_workers();
|
||||
for (uint i = 0; i < local_created_workers; i++) {
|
||||
function(_workers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,11 @@ private:
|
||||
const char* const _name;
|
||||
WorkerThread** _workers;
|
||||
const uint _max_workers;
|
||||
uint _created_workers;
|
||||
// _created_workers publishes the initialized prefix of _workers.
|
||||
// Writers release-store to it after initializing an entry. Readers
|
||||
// load-acquire before accessing _workers to not access uninitalized
|
||||
// data.
|
||||
Atomic<uint> _created_workers;
|
||||
uint _active_workers;
|
||||
WorkerTaskDispatcher _dispatcher;
|
||||
|
||||
@ -107,7 +111,7 @@ public:
|
||||
bool allow_inject_creation_failure() const;
|
||||
|
||||
uint max_workers() const { return _max_workers; }
|
||||
uint created_workers() const { return _created_workers; }
|
||||
uint created_workers() const { return _created_workers.load_acquire(); }
|
||||
uint active_workers() const { return _active_workers; }
|
||||
|
||||
uint set_active_workers(uint num_workers);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user