Files
sdk/runtime/vm/version_in.cc
T
Martin Kustermann f94936c549 [vm] Fix racy initialization of lazily populated ObjectStore members
If two threads concurrently trigger initialization of the lazily
populated ObjectStore members, they have to coordinate.

We ensure mutual exclusion by holding a writer lock, to ensure only one
thread can perform the lazy initialization. Furthermore we use
store-release/load-acquire for those ObjectStore fields to ensure that
once an object is made available on ObjectStore all of it's initializing
stores are visible at that point.

We no longer make public setters for those fields, since they shouldn't
be used (only the getters + lazy initialization should be used)

Fixes https://github.com/dart-lang/sdk/issues/46611

TEST=Fixes TSAN races reported on iso-stres builder.

Change-Id: Icaf54bb224e74baf1bfbb4a9bfc386ebfbd52755
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206782
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
2021-07-14 18:44:42 +00:00

50 lines
1.4 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/atomic.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/version.h"
namespace dart {
// We use acquire-release semantics to ensure initializing stores to the string
// are visible when the string becomes visible.
static AcqRelAtomic<const char*> formatted_version = nullptr;
const char* Version::String() {
if (formatted_version.load() == nullptr) {
const char* os = OS::Name();
const char* arch = CPU::Id();
char* version_string =
OS::SCreate(nullptr, "%s on \"%s_%s\"", str_, os, arch);
const char* expect_old_is_null = nullptr;
if (!formatted_version.compare_exchange_strong(expect_old_is_null,
version_string)) {
free(version_string);
}
}
return formatted_version.load();
}
const char* Version::SnapshotString() {
return snapshot_hash_;
}
const char* Version::CommitString() {
return commit_;
}
const char* Version::SdkHash() {
return git_short_hash_;
}
const char* Version::snapshot_hash_ = "{{SNAPSHOT_HASH}}";
const char* Version::str_ = "{{VERSION_STR}} ({{CHANNEL}}) ({{COMMIT_TIME}})";
const char* Version::commit_ = "{{VERSION_STR}}";
const char* Version::git_short_hash_ = "{{GIT_HASH}}";
} // namespace dart