Moving static AdaptationContext to outside function
Summary: Moving static AdaptationContext to outside function to bypass tsan's false report with static initializers. It is because with optimization enabled std::atomic is simplified to as a simple read with no locks. The existing lock produced by static initializer is __cxa_guard_acquire which is apparently not understood by tsan as it is different from normal locks (__gthrw_pthread_mutex_lock). This is a known problem with tsan: https://stackoverflow.com/questions/27464190/gccs-tsan-reports-a-data-race-with-a-thread-safe-static-local https://stackoverflow.com/questions/42062557/c-multithreading-is-initialization-of-a-local-static-lambda-thread-safe A workaround that I tried was to move the static variable outside the function. It is not a good coding practice since it gives global visibility to variable but it is a hackish workaround until g++ tsan is improved. Closes https://github.com/facebook/rocksdb/pull/2598 Differential Revision: D5445281 Pulled By: yiwu-arbug fbshipit-source-id: 6142bd934eb5852d8fd7ce027af593ba697ed41d
This commit is contained in:
parent
6e3ee015fb
commit
36651d14ee
@ -267,8 +267,8 @@ void WriteThread::CompleteFollower(Writer* w, WriteGroup& write_group) {
|
|||||||
SetState(w, STATE_COMPLETED);
|
SetState(w, STATE_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WriteThread::AdaptationContext jbg_ctx("JoinBatchGroup");
|
||||||
void WriteThread::JoinBatchGroup(Writer* w) {
|
void WriteThread::JoinBatchGroup(Writer* w) {
|
||||||
static AdaptationContext ctx("JoinBatchGroup");
|
|
||||||
|
|
||||||
assert(w->batch != nullptr);
|
assert(w->batch != nullptr);
|
||||||
bool linked_as_leader = LinkOne(w, &newest_writer_);
|
bool linked_as_leader = LinkOne(w, &newest_writer_);
|
||||||
@ -294,7 +294,7 @@ void WriteThread::JoinBatchGroup(Writer* w) {
|
|||||||
*/
|
*/
|
||||||
AwaitState(w, STATE_GROUP_LEADER | STATE_MEMTABLE_WRITER_LEADER |
|
AwaitState(w, STATE_GROUP_LEADER | STATE_MEMTABLE_WRITER_LEADER |
|
||||||
STATE_PARALLEL_MEMTABLE_WRITER | STATE_COMPLETED,
|
STATE_PARALLEL_MEMTABLE_WRITER | STATE_COMPLETED,
|
||||||
&ctx);
|
&jbg_ctx);
|
||||||
TEST_SYNC_POINT_CALLBACK("WriteThread::JoinBatchGroup:DoneWaiting", w);
|
TEST_SYNC_POINT_CALLBACK("WriteThread::JoinBatchGroup:DoneWaiting", w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -473,9 +473,9 @@ void WriteThread::LaunchParallelMemTableWriters(WriteGroup* write_group) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WriteThread::AdaptationContext cpmtw_ctx("CompleteParallelMemTableWriter");
|
||||||
// This method is called by both the leader and parallel followers
|
// This method is called by both the leader and parallel followers
|
||||||
bool WriteThread::CompleteParallelMemTableWriter(Writer* w) {
|
bool WriteThread::CompleteParallelMemTableWriter(Writer* w) {
|
||||||
static AdaptationContext ctx("CompleteParallelMemTableWriter");
|
|
||||||
|
|
||||||
auto* write_group = w->write_group;
|
auto* write_group = w->write_group;
|
||||||
if (!w->status.ok()) {
|
if (!w->status.ok()) {
|
||||||
@ -485,7 +485,7 @@ bool WriteThread::CompleteParallelMemTableWriter(Writer* w) {
|
|||||||
|
|
||||||
if (write_group->running-- > 1) {
|
if (write_group->running-- > 1) {
|
||||||
// we're not the last one
|
// we're not the last one
|
||||||
AwaitState(w, STATE_COMPLETED, &ctx);
|
AwaitState(w, STATE_COMPLETED, &cpmtw_ctx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// else we're the last parallel worker and should perform exit duties.
|
// else we're the last parallel worker and should perform exit duties.
|
||||||
@ -504,9 +504,9 @@ void WriteThread::ExitAsBatchGroupFollower(Writer* w) {
|
|||||||
SetState(write_group->leader, STATE_COMPLETED);
|
SetState(write_group->leader, STATE_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WriteThread::AdaptationContext eabgl_ctx("ExitAsBatchGroupLeader");
|
||||||
void WriteThread::ExitAsBatchGroupLeader(WriteGroup& write_group,
|
void WriteThread::ExitAsBatchGroupLeader(WriteGroup& write_group,
|
||||||
Status status) {
|
Status status) {
|
||||||
static AdaptationContext ctx("ExitAsBatchGroupLeader");
|
|
||||||
Writer* leader = write_group.leader;
|
Writer* leader = write_group.leader;
|
||||||
Writer* last_writer = write_group.last_writer;
|
Writer* last_writer = write_group.last_writer;
|
||||||
assert(leader->link_older == nullptr);
|
assert(leader->link_older == nullptr);
|
||||||
@ -544,7 +544,7 @@ void WriteThread::ExitAsBatchGroupLeader(WriteGroup& write_group,
|
|||||||
}
|
}
|
||||||
AwaitState(leader, STATE_MEMTABLE_WRITER_LEADER |
|
AwaitState(leader, STATE_MEMTABLE_WRITER_LEADER |
|
||||||
STATE_PARALLEL_MEMTABLE_WRITER | STATE_COMPLETED,
|
STATE_PARALLEL_MEMTABLE_WRITER | STATE_COMPLETED,
|
||||||
&ctx);
|
&eabgl_ctx);
|
||||||
} else {
|
} else {
|
||||||
Writer* head = newest_writer_.load(std::memory_order_acquire);
|
Writer* head = newest_writer_.load(std::memory_order_acquire);
|
||||||
if (head != last_writer ||
|
if (head != last_writer ||
|
||||||
@ -591,15 +591,15 @@ void WriteThread::ExitAsBatchGroupLeader(WriteGroup& write_group,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WriteThread::AdaptationContext eu_ctx("EnterUnbatched");
|
||||||
void WriteThread::EnterUnbatched(Writer* w, InstrumentedMutex* mu) {
|
void WriteThread::EnterUnbatched(Writer* w, InstrumentedMutex* mu) {
|
||||||
static AdaptationContext ctx("EnterUnbatched");
|
|
||||||
assert(w != nullptr && w->batch == nullptr);
|
assert(w != nullptr && w->batch == nullptr);
|
||||||
mu->Unlock();
|
mu->Unlock();
|
||||||
bool linked_as_leader = LinkOne(w, &newest_writer_);
|
bool linked_as_leader = LinkOne(w, &newest_writer_);
|
||||||
if (!linked_as_leader) {
|
if (!linked_as_leader) {
|
||||||
TEST_SYNC_POINT("WriteThread::EnterUnbatched:Wait");
|
TEST_SYNC_POINT("WriteThread::EnterUnbatched:Wait");
|
||||||
// Last leader will not pick us as a follower since our batch is nullptr
|
// Last leader will not pick us as a follower since our batch is nullptr
|
||||||
AwaitState(w, STATE_GROUP_LEADER, &ctx);
|
AwaitState(w, STATE_GROUP_LEADER, &eu_ctx);
|
||||||
}
|
}
|
||||||
if (enable_pipelined_write_) {
|
if (enable_pipelined_write_) {
|
||||||
WaitForMemTableWriters();
|
WaitForMemTableWriters();
|
||||||
@ -619,15 +619,15 @@ void WriteThread::ExitUnbatched(Writer* w) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WriteThread::AdaptationContext wfmw_ctx("WaitForMemTableWriters");
|
||||||
void WriteThread::WaitForMemTableWriters() {
|
void WriteThread::WaitForMemTableWriters() {
|
||||||
static AdaptationContext ctx("WaitForMemTableWriters");
|
|
||||||
assert(enable_pipelined_write_);
|
assert(enable_pipelined_write_);
|
||||||
if (newest_memtable_writer_.load() == nullptr) {
|
if (newest_memtable_writer_.load() == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Writer w;
|
Writer w;
|
||||||
if (!LinkOne(&w, &newest_memtable_writer_)) {
|
if (!LinkOne(&w, &newest_memtable_writer_)) {
|
||||||
AwaitState(&w, STATE_MEMTABLE_WRITER_LEADER, &ctx);
|
AwaitState(&w, STATE_MEMTABLE_WRITER_LEADER, &wfmw_ctx);
|
||||||
}
|
}
|
||||||
newest_memtable_writer_.store(nullptr);
|
newest_memtable_writer_.store(nullptr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user