Skip to content

Commit d61d6ad

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm] More TSAN profiler issues.
TEST=tsan Bug: #61594 Change-Id: I82598218a98b764d66deb671f8ec841c8e1c3cab Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452280 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Alexander Aprelev <[email protected]>
1 parent 220aac2 commit d61d6ad

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

runtime/vm/isolate.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,9 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
11951195
void set_current_sample_block(SampleBlock* block) {
11961196
current_sample_block_ = block;
11971197
}
1198+
SampleBlock* exchange_current_sample_block(SampleBlock* block) {
1199+
return current_sample_block_.exchange(block, std::memory_order_acq_rel);
1200+
}
11981201
void ProcessFreeSampleBlocks(Thread* thread);
11991202

12001203
// Returns the current SampleBlock used to track Dart allocation samples.
@@ -1204,6 +1207,10 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
12041207
void set_current_allocation_sample_block(SampleBlock* block) {
12051208
current_allocation_sample_block_ = block;
12061209
}
1210+
SampleBlock* exchange_current_allocation_sample_block(SampleBlock* block) {
1211+
return current_allocation_sample_block_.exchange(block,
1212+
std::memory_order_acq_rel);
1213+
}
12071214

12081215
bool TakeHasCompletedBlocks() {
12091216
return has_completed_blocks_.exchange(0) != 0;

runtime/vm/profiler.cc

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -794,15 +794,14 @@ void SampleBlockBuffer::FreeCompletedBlocks() {
794794
static void FlushSampleBlocks(Isolate* isolate) {
795795
ASSERT(isolate != nullptr);
796796

797-
SampleBlock* block = isolate->current_sample_block();
797+
SampleBlock* block = isolate->exchange_current_sample_block(nullptr);
798798
if (block != nullptr) {
799-
isolate->set_current_sample_block(nullptr);
800799
block->MarkCompleted();
801800
}
802801

803-
block = isolate->current_allocation_sample_block();
802+
block = isolate->exchange_current_allocation_sample_block(nullptr);
804803
if (block != nullptr) {
805-
isolate->set_current_allocation_sample_block(nullptr);
804+
// Allocation samples are collected synchronously.
806805
block->MarkCompleted();
807806
}
808807
}
@@ -1416,6 +1415,25 @@ void Profiler::SampleThreadSingleFrame(Thread* thread,
14161415
sample->SetAt(0, pc);
14171416
}
14181417

1418+
void ReleaseToCurrentBlock(Isolate* isolate) {
1419+
#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_WINDOWS) || \
1420+
defined(DART_HOST_OS_FUCHSIA)
1421+
// The sample is collected by a different thread. The sample appears all at
1422+
// once from the profiled thread's point of view. Establish the isolate
1423+
// flushing its own current block happens-after the most recent sample
1424+
// written in that block by dumping a dependency through the current block.
1425+
// TSAN doesn't otherwise know this is already true because it doesn't have
1426+
// special treatment for thread_suspend/resume.
1427+
SampleBlock* block = isolate->current_sample_block();
1428+
isolate->exchange_current_sample_block(block);
1429+
#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
1430+
// The sample is collected by a signal handler on the same thread being
1431+
// sampled.
1432+
#else
1433+
#error What kind of sampler?
1434+
#endif
1435+
}
1436+
14191437
void Profiler::SampleThread(Thread* thread,
14201438
const InterruptedThreadState& state) {
14211439
ASSERT(thread != nullptr);
@@ -1494,6 +1512,7 @@ void Profiler::SampleThread(Thread* thread,
14941512
if (thread->IGNORE_RACE2(IsDeoptimizing)()) {
14951513
counters_.single_frame_sample_deoptimizing.fetch_add(1);
14961514
SampleThreadSingleFrame(thread, sample, pc);
1515+
ReleaseToCurrentBlock(isolate);
14971516
return;
14981517
}
14991518
}
@@ -1505,6 +1524,7 @@ void Profiler::SampleThread(Thread* thread,
15051524
counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
15061525
// Could not get stack boundary.
15071526
SampleThreadSingleFrame(thread, sample, pc);
1527+
ReleaseToCurrentBlock(isolate);
15081528
return;
15091529
}
15101530

@@ -1531,6 +1551,7 @@ void Profiler::SampleThread(Thread* thread,
15311551
CollectSample(isolate, exited_dart_code, in_dart_code, sample,
15321552
&native_stack_walker, &dart_stack_walker, pc, fp, sp,
15331553
&counters_);
1554+
ReleaseToCurrentBlock(isolate);
15341555
}
15351556

15361557
CodeDescriptor::CodeDescriptor(const AbstractCode code) : code_(code) {}

runtime/vm/profiler_test.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "platform/assert.h"
66

7+
#include "platform/thread_sanitizer.h"
78
#include "vm/dart_api_impl.h"
89
#include "vm/dart_api_state.h"
910
#include "vm/flags.h"
@@ -29,19 +30,27 @@ const int64_t kValidTimeStamp = 1;
2930
// SampleVisitor ignores samples with pc == 0.
3031
const uword kValidPc = 0xFF;
3132

33+
NO_SANITIZE_THREAD
34+
static void SetIgnoreRace(bool* flag, bool value) {
35+
*flag = value;
36+
}
37+
3238
// Some tests are written assuming native stack trace profiling is disabled.
3339
class DisableNativeProfileScope : public ValueObject {
3440
public:
3541
DisableNativeProfileScope()
3642
: FLAG_profile_vm_(FLAG_profile_vm),
3743
FLAG_profile_vm_allocation_(FLAG_profile_vm_allocation) {
38-
FLAG_profile_vm = false;
39-
FLAG_profile_vm_allocation = false;
44+
// Ignore race: we generally don't try to ensure the profiler is disabled
45+
// when changing setting for unit tests. On Linux/Android, there is no way
46+
// to wait for outstanding SIGPROFs.
47+
SetIgnoreRace(&FLAG_profile_vm, false);
48+
SetIgnoreRace(&FLAG_profile_vm_allocation, false);
4049
}
4150

4251
~DisableNativeProfileScope() {
43-
FLAG_profile_vm = FLAG_profile_vm_;
44-
FLAG_profile_vm_allocation = FLAG_profile_vm_allocation_;
52+
SetIgnoreRace(&FLAG_profile_vm, FLAG_profile_vm_);
53+
SetIgnoreRace(&FLAG_profile_vm_allocation, FLAG_profile_vm_allocation_);
4554
}
4655

4756
private:

0 commit comments

Comments
 (0)